diff --git a/.markdownlint-cli2.cjs b/.markdownlint-cli2.cjs index 2b370c76e3..d8555e8917 100644 --- a/.markdownlint-cli2.cjs +++ b/.markdownlint-cli2.cjs @@ -245,6 +245,9 @@ config.renamedLinks = { renames: [{ oldFile: '/docs/apis/plugintypes/tinymce/index.md', newFile: '/docs/apis/plugintypes/tiny/legacy.md', + }, { + oldFile: '/docs/apis/subsystems/output.md', + newFile: '/docs/apis/subsystems/output/index.md', }, { oldFile: '/docs/apis/subsystems/tool/index.md', newFile: '/docs/apis/subsystems/admin/index.md', diff --git a/data/libraries.json b/data/libraries.json index 0406a8770c..5c14b917a9 100644 --- a/data/libraries.json +++ b/data/libraries.json @@ -9,6 +9,33 @@ "repository": "https://github.com/olivernn/lunr.js", "customised": false }, + { + "copyrightHolders": [], + "location": "admin/tool/mfa/factor/totp/extlib/Assert", + "name": "Assert", + "version": "2.1", + "license": "MIT", + "repository": "https://github.com/beberlei/assert", + "customised": false + }, + { + "copyrightHolders": [], + "location": "admin/tool/mfa/factor/totp/extlib/OTPHP", + "name": "OTPHP", + "version": "9.1.1", + "license": "MIT", + "repository": "https://github.com/Spomky-Labs/otphp", + "customised": false + }, + { + "copyrightHolders": [], + "location": "admin/tool/mfa/factor/totp/extlib/ParagonIE/ConstantTime", + "name": "Constant-Time Encoding", + "version": "2.1.1", + "license": "MIT", + "repository": "https://github.com/paragonie/constant_time_encoding", + "customised": false + }, { "copyrightHolders": [ "2015 Richard Dancsi" @@ -138,7 +165,7 @@ "location": "lib/amd/src/chartjs-lazy.js", "name": "Chart.js", "description": "Simple yet flexible JavaScript charting for designers & developers.", - "version": "4.2.1", + "version": "4.4.0", "license": "MIT", "repository": "https://github.com/chartjs/Chart.js", "customised": true @@ -234,7 +261,7 @@ "location": "lib/editor/atto/plugins/html/yui/src/codemirror", "name": "codemirror", "description": "CodeMirror is a versatile text editor implemented in JavaScript for the browser.", - "version": "5.65.12", + "version": "5.65.15", "license": "MIT", "repository": "https://github.com/codemirror/codemirror5", "customised": false @@ -287,7 +314,7 @@ "location": "lib/emoji-data", "name": "Emoji data", "description": "Library to parse easily data and sprite sheets for emoji.", - "version": "14.0.1", + "version": "15.0.1", "license": "MIT", "repository": "https://github.com/iamcal/emoji-data/", "customised": true @@ -435,7 +462,7 @@ "location": "lib/jquery", "name": "jQuery", "description": "jQuery is a fast, small, and feature-rich JavaScript library widely used on moodle.", - "version": "3.6.4", + "version": "3.7.1", "license": "MIT", "repository": "https://github.com/jquery/jquery", "customised": false @@ -459,7 +486,7 @@ "location": "lib/lti1p3", "name": "LTI 1.3 Tool Library", "description": "A library used for building IMS-certified LTI 1.3 tool providers in PHP.", - "version": "5.2.6", + "version": "5.4.1", "license": "Apache", "licenseversion": "2.0", "repository": "https://github.com/packbackbooks/lti-1-3-php-library", @@ -680,7 +707,7 @@ "location": "lib/phpspreadsheet", "name": "PhpSpreadsheet", "description": "Library to read, write and create spreadsheet documents in PHP.", - "version": "1.28.0", + "version": "1.29.0", "license": "MIT", "repository": "https://github.com/PHPOffice/PhpSpreadsheet", "customised": true @@ -879,6 +906,15 @@ "licenseversion": "2.0+", "customised": true }, + { + "copyrightHolders": [], + "location": "lib/webauthn/src", + "name": "WebAuthn", + "version": "2.0.1", + "license": "MIT", + "repository": "https://github.com/lbuchs/WebAuthn", + "customised": false + }, { "copyrightHolders": [ "2009 Phacility" diff --git a/data/migratedPages.yml b/data/migratedPages.yml index 2dedb85d0a..2ef2f2c217 100644 --- a/data/migratedPages.yml +++ b/data/migratedPages.yml @@ -4,6 +4,9 @@ AJAX: AMD_Modal: - filePath: "/docs/guides/javascript/modal/index.md" slug: "/docs/guides/javascript/modal/" +Acceptance_testing: +- filePath: "/general/development/tools/behat/index.md" + slug: "/general/development/tools/behat/" Acceptance_testing/Browsers: - filePath: "/general/development/tools/behat/browsers/index.md" slug: "/general/development/tools/behat/browsers/" @@ -37,6 +40,9 @@ Adding_a_web_service_to_a_plugin: Admin_settings: - filePath: "/docs/apis/subsystems/admin/index.md" slug: "/docs/apis/subsystems/admin/" +Admin_tools: +- filePath: "/general/projects/api/admin-tools.md" + slug: "/general/projects/api/admin-tools" Advanced_grading_API: - filePath: "/docs/apis/core/grading/index.md" slug: "/docs/apis/core/grading/" @@ -112,6 +118,9 @@ Composer: Conditional_activities_API: - filePath: "/docs/apis/core/conditionalactivities/index.md" slug: "/docs/apis/core/conditionalactivities/" +Contributing_to_Moodle: +- filePath: "/general/community/contribute.md" + slug: "/general/community/contribute" Core_APIs: - filePath: "/docs/apis.md" slug: "/docs/apis" @@ -130,6 +139,9 @@ Credits: Custom_Moodle_Apps: - filePath: "/general/app/customisation/custom-apps.md" slug: "/general/app/customisation/custom-apps" +Custom_fields_API: +- filePath: "/docs/apis/core/customfields/index.md" + slug: "/docs/apis/core/customfields/" DDL_functions: - filePath: "/docs/apis/core/dml/ddl.md" slug: "/docs/apis/core/dml/ddl" @@ -240,6 +252,9 @@ Groups_API: Hardening_new_Roles_system: - filePath: "/docs/apis/subsystems/roles.md" slug: "/docs/apis/subsystems/roles" +Inplace_editable: +- filePath: "/docs/apis/subsystems/output/inplace.md" + slug: "/docs/apis/subsystems/output/inplace" Integration_Review: - filePath: "/general/development/process/integration/index.md" slug: "/general/development/process/integration" @@ -258,6 +273,9 @@ Lock_API: Machine_learning_backends: - filePath: "/docs/apis/plugintypes/mlbackend/index.md" slug: "/docs/apis/plugintypes/mlbackend/" +Message_API: +- filePath: "/docs/apis/core/message/index.md" + slug: "/docs/apis/core/message/" Mission: - filePath: "/general/community/mission.md" slug: "/general/community/mission" @@ -1468,10 +1486,10 @@ New_docs_version_process: - filePath: "/general/development/process/release/newuserdocs.md" slug: "/general/development/process/release/newuserdocs" Output_API: -- filePath: "/docs/apis/subsystems/output.md" +- filePath: "/docs/apis/subsystems/output/index.md" slug: "/docs/apis/subsystems/output" Output_functions: -- filePath: "/docs/apis/subsystems/output.md" +- filePath: "/docs/apis/subsystems/output/index.md" slug: "/docs/apis/subsystems/output#output-functions" Overview: - filePath: "/general/community/intro.md" diff --git a/data/moodle-contributors.txt b/data/moodle-contributors.txt index 6d18960377..5e44ebea1c 100644 --- a/data/moodle-contributors.txt +++ b/data/moodle-contributors.txt @@ -167,6 +167,7 @@ Candilio Carlos Carrick Carrier +Carrillo Carson Carsten Carter @@ -221,6 +222,7 @@ Cunningham Curry D'souza Dageförde +Dale Dallimore Dalton Damian @@ -240,6 +242,7 @@ Dave Davenport David Davidson +Davies Davis Davitasvili Davo @@ -293,6 +296,7 @@ Eberhardt Eddin Eduardo Ehringer +Eichelberger Eijdenberg EizEddin Elbert @@ -389,6 +393,7 @@ Gray Green Greeve Greg +Gregor Gregory Greidanus Grigory @@ -443,6 +448,7 @@ Hoobin Howard Hugh Hughes +Hummel HungTran Hunkler Hunt @@ -468,6 +474,7 @@ Iurii Iyer Iñaki Iñigo +Jablon Jackson Jacob Jade @@ -492,11 +499,13 @@ Jean-Roch Jeff Jenkins Jenny +Jeremy Jerome Jess Jesse Jetha Jinu +Joachim Joby Jody Joey @@ -935,6 +944,7 @@ Schach Schmadel Schrenk Schroeder +Schulz Scotson ScottVerbeek Scribner @@ -1142,6 +1152,7 @@ Wirianto Wojciech Woldeselassie Wolf +Wolfgang Woloszyn Wolters Woods @@ -1403,6 +1414,7 @@ skaldrom skodak spvickers stabijoh +stemiwe stevando stigbjarne stronk7 diff --git a/data/projects.json b/data/projects.json index 5c9047b665..065894f1c5 100644 --- a/data/projects.json +++ b/data/projects.json @@ -37,6 +37,22 @@ } ] }, + "api/admin-tools": { + "title": "Admin tools", + "status": "Complete", + "owners": [ + { + "name": "Petr Škoda", + "githubUsername": "škoďák" + } + ], + "issueLinks": [ + { + "link": "https://tracker.moodle.org/browse/MDL-29029", + "title": "MDL-29029" + } + ] + }, "api/amos": { "title": "Automated Manipulation of Strings (AMOS)", "status": "Complete", diff --git a/docs/apis.md b/docs/apis.md index 39d7699dfe..5f22ee85c6 100644 --- a/docs/apis.md +++ b/docs/apis.md @@ -40,7 +40,7 @@ The [Page API](https://docs.moodle.org/dev/Page_API) is used to set up the curre ### Output API (output) -The [Output API](./apis/subsystems/output.md) is used to render the HTML for all parts of the page. +The [Output API](./apis/subsystems/output/index.md) is used to render the HTML for all parts of the page. ### String API (string) @@ -139,7 +139,7 @@ The [Lock API](./apis/core/lock/index.md) lets you synchronise processing betwee ### Message API (message) -The [Message API](https://docs.moodle.org/dev/Message_API) lets you post messages to users. They decide how they want to receive them. +The [Message API](./apis/core/message/index.md) lets you post messages to users. They decide how they want to receive them. ### Media API (media) @@ -217,7 +217,7 @@ The [https://docs.moodle.org/dev/OpenBadges_User_Documentation Badges] user docu ### Custom fields API (customfield) -The [Custom fields API](https://docs.moodle.org/dev/Custom_fields_API) allows you to configure and add custom fields for different entities +The [Custom fields API](./apis/core/customfields/index.md) allows you to configure and add custom fields for different entities ## Activity module APIs diff --git a/docs/apis/_files/db-messages-php.mdx b/docs/apis/_files/db-messages-php.mdx index 000225f1dc..2b52b7cf0a 100644 --- a/docs/apis/_files/db-messages-php.mdx +++ b/docs/apis/_files/db-messages-php.mdx @@ -1,4 +1,4 @@ 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. +See the [Message API](../core/message/index.md) documentation for further information. diff --git a/docs/apis/core/customfields/index.md b/docs/apis/core/customfields/index.md new file mode 100644 index 0000000000..79c3e15769 --- /dev/null +++ b/docs/apis/core/customfields/index.md @@ -0,0 +1,174 @@ +--- +title: Custom fields API +tags: + - customfield + - Custom field +--- + +import { Since } from '@site/src/components'; + + + +## Custom fields API overview + +Custom fields API allows to configure custom fields that can be added to various contexts. Each **component** (or plugin) that wants to use custom fields can define several **areas**. + +:::info Example +The `core_course` component defines an area `course` that allows to add custom fields to the courses. The same component can define another area `coursecat` that will allow to add custom fields to the course categories. +::: + +Inside each area, the component/plugin can decide whether to use or not to use **itemid**. + +:::info Example +Course custom fields are the same throughout the system and they don't use `itemid` (it is always 0). But there could be an activity module that would want to configure different custom fields for each individual instance of module. Then this module would use the module id as the `itemid`, as in ([example](https://github.com/marinaglancy/moodle-mod_surveybuilder)). This would allow to create modules similar to `mod_data` and `mod_feedback` where each instance has its own set of fields. +::: + +New plugin type `customfield` was also added as part of the Custom fields API. Additional types of custom fields can be installed into `/customfield/field/`. + +## How to use custom fields + +Component/plugin that uses custom fields must define a **handler class** for each area and a **configuration page**. Handler class must be called `/customfield/_handler` and be placed in autoloaded location `/classes/customfield/_handler.php`. This class must extend **\core_customfield\handler** . Configuration page may be located anywhere. For course custom fields configuration the admin settings page is used [/course/customfield.php](https://github.com/moodle/moodle/blob/master/course/customfield.php). If the area uses `itemid` this page should take `itemid` as a parameter. + +Handler has protected constructor, to get a handler call `create()` method. Some areas may choose to return a singleton here: + +```php +$handler = HANDLERCLASS::create($itemid); +``` + +Configuration page contents will be: + +```php +$output = $PAGE->get_renderer('core_customfield'); +$outputpage = new \core_customfield\output\management($handler); +echo $output->render($outputpage); +``` + +Handler must implement all abstract methods (calculate configuration or instance context, check permissions to configure, view or edit) and also may choose to overwrite: + +```php +handler::uses_categories() +handler::generate_category_name() +handler::config_form_definition() // For example, the course_handler adds "locked" and "visibility" settings that control who can edit or view the particular field. +handler::setup_edit_page() // Sets page context/url/breadcrumb for the customfield/edit.php page, in some cases it must be overridden. +``` + +### Add custom fields to the instance edit form + +Custom fields are added to the **instances**. For example, course custom fields are added to the courses, so `courseid` is the `instanceid`. In the example of [`mod_surveybuilder`](https://github.com/marinaglancy/moodle-mod_surveybuilder) we use `$USER->id` as the `instanceid` (which means that in this example one user can fill the survey in one module only once). In each case of using custom fields there should be a clear concept of an **instance**. `Instanceid` is required to save the data but it may be empty when we render the instance edit form (for example, the course is not yet created). + +Developer must add custom field callbacks to the instance edit form. If the instance is "made up" (like in `mod_surveybuilder`), a new form has to be created with `id` field in it that will refer to the `instanceid`. + +The following callbacks should be used in `form definition`, `definition_after_data`, `validation` and `after form submission`: + +```php +$handler->instance_form_definition($mform) +$handler->instance_form_before_set_data() +$handler->instance_form_definition_after_data() +$handler->instance_form_validation() +$handler->instance_form_save($data) +``` + +The `instance_form_save()` method must be called after the form was saved as the `$data` parameter must have the `id` attribute. + +On deletion of an instance or on deletion of the whole item call: + +```php +$handler->delete_instance() +$handler->delete_all() +``` + +### Retrieving instances custom fields + +How custom fields are used depends entirely on the situation. + +```php title="Handler methods to retrieve custom fields values for the given instance(s)" +$handler->export_instance_data() +$handler->export_instance_data_object() +$handler->display_custom_fields_data() +``` + +Additional methods for advanced usage: + +```php +$handler->get_instance_data() +$handler->get_instances_data() +$handler->get_instance_data_for_backup() +``` + +Method `restore_instance_data_from_backup()` exists in the handler class but is not implemented. + +```php title="To retrieve the list of custom fields used in the given component/area/itemid" +$handler->get_categories_with_fields() +$handler->get_fields() +``` + +:::note +The list of fields is cached in the handler and these two functions can be called multiple times. +::: + +```php title="Example code for course custom fields. This function will return all the custom fields for a given courseid" +function get_course_metadata($courseid) { + $handler = \core_customfield\handler::get_handler('core_course', 'course'); + // This is equivalent to the line above. + //$handler = \core_course\customfield\course_handler::create(); + $datas = $handler->get_instance_data($courseid); + $metadata = []; + foreach ($datas as $data) { + if (empty($data->get_value())) { + continue; + } + $cat = $data->get_field()->get_category()->get('name'); + $metadata[$data->get_field()->get('shortname')] = $cat . ': ' . $data->get_value(); + } + return $metadata; +} +``` + +### Privacy API + +Custom fields API does not export or delete any data because it does not know how custom fields are used, what data is considered user data and if it is considered private or shared data. + +```php title="Plugins that store user information in custom fields should link subsystem in their get_metadata" +$collection->link_subsystem('core_customfield', 'privacy:metadata:customfieldpurpose'); +``` + +```php title="They can use the following methods in the export/delete functions" +use core_customfield\privacy\provider as customfield_provider; + +customfield_provider::get_customfields_data_contexts() +customfield_provider::export_customfields_data() +customfield_provider::delete_customfields_data() +customfield_provider::delete_customfields_data_for_context() +``` + +In case when custom fields configuration is considered to be user data (configuration means the definition of the fields, not the instance data), there are also couple of methods to help with privacy API implementations: + +```php +customfield_provider::get_customfields_configuration_contexts() +customfield_provider::delete_customfields_configuration() +customfield_provider::delete_customfields_configuration_for_context() +``` + +:::info +Export of configuration was not yet implemented at the time of writing this because of difficult implementation and very unclear use case. If it is needed please feel free to contribute to Moodle. +::: + +## Custom fields plugins + +Custom fields plugin type was added to allow implement different types of custom fields (somehow similar to user profile fields plugin type). Plugins are located in `/customfield/field/` and the full frankenstyle name of the plugins start with `customfield_`. + +Except for common [Plugin files](../../commonfiles/index.mdx) and tests the following classes must be present in `customfield` plugins (in respective autoloaded locations): + +```php +namespace customfield_; +class field_controller extends \core_customfield\field_controller; +class data_controller extends \core_customfield\data_controller; + +namespace customfield_\privacy; +class provider implements \core_privacy\local\metadata\null_provider, \core_customfield\privacy\customfield_provider; +``` + +## See also + +- [MDL-64626](https://tracker.moodle.org/browse/MDL-64626) - Custom fields API (Moodle 3.7+) implementations and improvements +- [MDL-57898](https://tracker.moodle.org/browse/MDL-57898) - Add custom field types plugin and course custom fields functionality diff --git a/docs/apis/core/message/index.md b/docs/apis/core/message/index.md new file mode 100644 index 0000000000..00a8d914a7 --- /dev/null +++ b/docs/apis/core/message/index.md @@ -0,0 +1,208 @@ +--- +title: Message API +tags: + - API + - Tutorial + - Plugins + - Messaging +--- + +import { Since } from '@site/src/components'; + +## What is this document? + +This document describes how to make use of the Moodle Messaging API to send messages to Moodle users. + +If you are after a general introduction on using the Moodle Messaging system go to [messaging user documentation](https://docs.moodle.org/en/Messaging). + +If you are looking for details of how the Messaging system's internal structure was implemented, go to [Messaging 2.0](https://docs.moodle.org/dev/Messaging_2.0). + +If you are looking for instructions on the implementation of a custom message processor (a component that receives messages sent to a user), go to [Messaging custom components](https://docs.moodle.org/dev/Messaging_custom_components). + +If you are looking for instructions on sending messages programmatically within Moodle then read on... + +## Overview + +Moodle components have the ability to send messages to users via the Moodle messaging system. Any type of component, for example a plugin or block, can register as a message producer then send messages to users. + +## File locations + +The Message API code is contained within `lib/messagelib.php` and is automatically included for you during page setup. + +## Functions + +`message_send()` is the primary point of contact for the message API. Call it to send a message to a user. See the php documentation for a full description of the arguments that must be supplied. There is also an example below. + +## Message pop-up + + + +A JavaScript pop-up can be displayed through a link to invite a user to message another. In order to use this feature, you need to require the JavaScript libraries using `message_messenger_requirejs()` and create a link with the attributes returned by `message_messenger_sendmessage_link_params()`. More in the examples. + +## Examples + +### How to register as a message producer + +The messages produced by a message provider is defined in the `/db/messages.php` file of a component. Below is code from the quiz module's `messages.php` file, shown as an example. + +```php title="mod/quiz/db/messages.php" +defined('MOODLE_INTERNAL') || die(); +$messageproviders = [ + // Notify teacher that a student has submitted a quiz attempt + 'submission' => [ + 'capability' => 'mod/quiz:emailnotifysubmission' + ], + // Confirm a student's quiz attempt + 'confirmation' => [ + 'capability' => 'mod/quiz:emailconfirmsubmission' + ], +]; +``` + +The quiz can send two kinds of messages, quiz "submission" and "confirmation" notifications. Each message type is only available to users with the appropriate capability. Please note that the capability is checked at the system level context. Users who have this capability will have this message listed in their messaging preferences. You can omit the capability section if your message should be visible for all users. For example forum post notifications are available to all users. + +```php +$messageproviders = [ + // Ordinary single forum posts + 'posts' => [], +]; +``` + +When displaying your message types in a user's messaging preferences it will use a string from your component's language file called `messageprovider:messagename`. For example here are the relevant strings from the quiz's language file. + +```php +$string['messageprovider:confirmation'] = 'Confirmation of your own quiz submissions'; +$string['messageprovider:submission'] = 'Notification of quiz submissions'; +``` + +Once your `messages.php` is complete you need to increase the version number of your component in its `version.php`. That will cause Moodle to check `messages.php` looking for new or changed message definitions. Log in as an admin and go to `/admin/index.php` (the Notifications page) to start the upgrade process. + +### Setting defaults + +```php title="The default processor can be set using an element of the array" +'mynotification' => [ + 'defaults' => [ + 'pop-up' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_LOGGEDIN + MESSAGE_DEFAULT_LOGGEDOFF, + 'email' => MESSAGE_PERMITTED, + ], +], +``` + +With that setting email will be permitted but disabled for each user by default. It can be turned on by each user through the `preferences/notification` preferences options (`/message/notificationpreferences.php?userid=X`) +The possible values are recorded in the lib.php file of messaging + +```php +/** + * Define contants for messaging default settings population. For unambiguity of + * plugin developer intentions we use 4-bit value (LSB numbering): + * bit 0 - whether to send message when user is loggedin (MESSAGE_DEFAULT_LOGGEDIN) + * bit 1 - whether to send message when user is loggedoff (MESSAGE_DEFAULT_LOGGEDOFF) + * bit 2..3 - messaging permission (MESSAGE_DISALLOWED|MESSAGE_PERMITTED|MESSAGE_FORCED) + * + * MESSAGE_PERMITTED_MASK contains the mask we use to distinguish permission setting + */ +``` + +Note that if you change the values in message.php and then upgrade the plugin the values will not automatically be changed in the `config_plugins` table where they are stored. + +### How to send a message + + + +Here is example code showing you how to actually send a notification message. The example shows the construction of a object with specific properties, which is then passed to the `message_send()` function that uses the information to send a message. + +```php title="Sending a message" +$message = new \core\message\message(); +$message->component = 'mod_yourmodule'; // Your plugin's name +$message->name = 'mynotification'; // Your notification name from message.php +$message->userfrom = core_user::get_noreply_user(); // If the message is 'from' a specific user you can set them here +$message->userto = $user; +$message->subject = 'message subject 1'; +$message->fullmessage = 'message body'; +$message->fullmessageformat = FORMAT_MARKDOWN; +$message->fullmessagehtml = '

message body

'; +$message->smallmessage = 'small message'; +$message->notification = 1; // Because this is a notification generated from Moodle, not a user-to-user message +$message->contexturl = (new \moodle_url('/course/'))->out(false); // A relevant URL for the notification +$message->contexturlname = 'Course list'; // Link title explaining where users get to for the contexturl +// Extra content for specific processor +$content = [ + '*' => [ + 'header' => ' test ', + 'footer' => ' test ', + ], +]; +$message->set_additional_content('email', $content); + +// You probably don't need attachments but if you do, here is how to add one +$usercontext = context_user::instance($user->id); +$file = new stdClass(); +$file->contextid = $usercontext->id; +$file->component = 'user'; +$file->filearea = 'private'; +$file->itemid = 0; +$file->filepath = '/'; +$file->filename = '1.txt'; +$file->source = 'test'; + +$fs = get_file_storage(); +$file = $fs->create_file_from_string($file, 'file1 content'); +$message->attachment = $file; + +// Actually send the message +$messageid = message_send($message); +``` + +```php title="Before 2.9 message data used to be a stdClass object as shown below (This formation of a message will no longer work as of Moodle 3.6. Only a message object will be accepted):" + +$message = new stdClass(); +$message->component = 'mod_quiz'; //your component name +$message->name = 'submission'; //this is the message name from messages.php +$message->userfrom = $USER; +$message->userto = $touser; +$message->subject = $subject; +$message->fullmessage = $message; +$message->fullmessageformat = FORMAT_PLAIN; +$message->fullmessagehtml = ''; +$message->smallmessage = ''; +$message->notification = 1; //this is only set to 0 for personal messages between users +message_send($message); +``` + +### How to set-up the message pop-up + +Here is example code showing you how to set-up the JavaScript pop-up link. + +```php +require_once('message/lib.php'); +$userid = 2; +$userto = $DB->get_record('user', ['id' => $userid]); + +message_messenger_requirejs(); +$url = new moodle_url('message/index.php', ['id' => $userto->id]); +$attributes = message_messenger_sendmessage_link_params($userto); +echo html_writer::link($url, 'Send a message', $attributes); +``` + +## Changes in Moodle 3.5 + + + +In Moodle 3.5, there were some moderately big changes. The only docs I have been able to find about them are in [upgrade.txt](https://github.com/moodle/moodle/blob/33a388eff737c049786ee42d7430db549568471c/message/upgrade.txt#L56) file. However, that is the details, here is an overview: + +The main `message_send()` API to send a message has not changed, so if your code is just sending messages, you don't need to do anything. + +Similarly, message_output plugins don't need to change, so no worries there. + +If you are doing things with messages, then you need to understand how the internals have changed. + +The database tables have changed. Messages from Moodle components to a user (e.g. mod_quiz), telling them that something has happened (e.g. an attempt was submitted) have always been 'Notifications'. In the past, this was just a column in the `mdl_message` table. Now, messages and notifications are stored in completely separate tables. Notifications are in `mdl_notifications`. The structure of this table is very similar to the old `mdl_message` table which is now not used at all. Messages are in `mdl_messages`, and related tables, that now exist to support group messaging. Those tables join together like this: + +```sql + SELECT * + FROM mdl_messages m + JOIN mdl_message_conversations con ON con.id = m.conversationid + JOIN mdl_message_conversation_members mem ON mem.conversationid = con.id +LEFT JOIN mdl_message_user_actions act ON act.userid = mem.userid AND act.messageid = m.id + ORDER BY m.timecreated, m.id, mem.userid, act.id +``` diff --git a/docs/apis/plugintypes/antivirus/index.mdx b/docs/apis/plugintypes/antivirus/index.mdx index dc9d920541..c28e2d0276 100644 --- a/docs/apis/plugintypes/antivirus/index.mdx +++ b/docs/apis/plugintypes/antivirus/index.mdx @@ -109,6 +109,6 @@ Writing unit tests is strongly encouraged as it can help to identify bugs, or ch 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://phpunit.de/manual/current/en/test-doubles.html). +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/docs/apis/plugintypes/assign/feedback.md b/docs/apis/plugintypes/assign/feedback.md index aa7a5c58a9..9c2f2f4429 100644 --- a/docs/apis/plugintypes/assign/feedback.md +++ b/docs/apis/plugintypes/assign/feedback.md @@ -30,10 +30,11 @@ Assignment Feedback plugins are located in the `/mod/assign/feedback` directory. :::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. +The plugin name should be no longer than 38 (13 before Moodle 4.3) 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 53 (28 before Moodle 4.3) chars due to a limitation with PostgreSQL. -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. +If a plugin requires multiple database tables, the plugin name will need to be shorter to allow different table names to fit under the 53 character limit (28 before Moodle 4.3). +Note: If your plugin is intended to work with versions of Moodle older than 4.3, then the plugin name must be 13 characters or shorter, and table names must be 28 characters or shorter. ::: 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. diff --git a/docs/apis/plugintypes/assign/submission.md b/docs/apis/plugintypes/assign/submission.md index dd5083acd8..87e35ab206 100644 --- a/docs/apis/plugintypes/assign/submission.md +++ b/docs/apis/plugintypes/assign/submission.md @@ -30,11 +30,11 @@ Assignment Feedback plugins are located in the `/mod/assign/submission` director :::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. +The plugin name should be no longer than 36 (11 before Moodle 4.3) 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 53 (28 before Moodle 4.3) chars due to a limitation with PostgreSQL. -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. +If a plugin requires multiple database tables, the plugin name will need to be shorter to allow different table names to fit under the 53 character limit (28 before Moodle 4.3). -::: +Note: If your plugin is intended to work with versions of Moodle older than 4.3, then the plugin name must be 11 characters or shorter, and table names must be 28 characters or shorter. 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. diff --git a/docs/apis/plugintypes/customfield/index.md b/docs/apis/plugintypes/customfield/index.md index 78a507c5f6..8db51954b5 100644 --- a/docs/apis/plugintypes/customfield/index.md +++ b/docs/apis/plugintypes/customfield/index.md @@ -1,12 +1,12 @@ --- -title: Course Custom fields +title: Custom fields tags: - - core_course + - customfield - Course - Custom field --- -Course custom fields allow you to create field types to be used for course custom fields. Instances of these field types can be added to a course. for example, if you want to display radio buttons on the course edit page, then you can create a radio custom course field plugin. +Custom fields allow you to create field types to be used for custom fields. Instances of these field types can be added to the respective areas that implement [Custom fields API](../../core/customfields/index.md). Currently in Moodle core only courses implement this API, however custom fields are also used in addon plugins for other areas. For example, if you want to display radio buttons on the course edit page, then you can add an instance of a radio custom field plugin to the Course custom fields configuration. import { Lang, @@ -16,7 +16,7 @@ import DataController from './_files/data_controller'; ## File structure -Course custom field plugins are located in the `/customfield/field` directory. A plugin should not include any custom files outside of it's own plugin folder. +Custom field plugins are located in the `/customfield/field` directory. A plugin should not include any custom files outside of it's own plugin folder. 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. @@ -44,10 +44,10 @@ customfield/field/checkbox -A course custom field plugin requires two _controller_ classes: +A custom field plugin requires two _controller_ classes: - a _field_ controller, which describes the field itself; and -- a _data_ controller, which describes with interface within the context of the course page. +- a _data_ controller, which describes with interface within the context of the instance (i.e. course). ### Field Controller @@ -121,8 +121,9 @@ The `datafield()` function returns an enumerated string and describes which data #### instance_form_definition() -The `instance_form_definition()` function adds any required field elements that are displayed on the course editing page. +The `instance_form_definition()` function adds any required field elements that are displayed on the instance editing page (i.e. on the course settings page). ## See Also +- [Custom files API](../../core/customfields/index.md) - [User Profile Fields](https://docs.moodle.org/dev/User_profile_fields) diff --git a/docs/apis/plugintypes/index.md b/docs/apis/plugintypes/index.md index 614ec4bb83..1e8fd2a290 100644 --- a/docs/apis/plugintypes/index.md +++ b/docs/apis/plugintypes/index.md @@ -55,7 +55,7 @@ The underscore character is not supported in activity modules for legacy reasons | [Assignment submission plugins](./assign/submission.md) | assignsubmission | /mod/assign/submission | Different forms of assignment submissions | 2.3+ | | [Assignment feedback plugins](./assign/feedback.md) | assignfeedback | /mod/assign/feedback | Different forms of assignment feedbacks | 2.3+ | | [Book tools](./mod_book/index.md) | booktool | /mod/book/tool | Small information-displays or tools that can be moved around pages | 2.1+ | -| [Course Custom fields](./customfield/index.md) | customfield | /customfield/field | Custom field types, used in Custom course fields | 3.7+ | +| [Custom fields](./customfield/index.md) | customfield | /customfield/field | Custom field types, used in Custom course fields | 3.7+ | | [Database fields](./mod_data/fields.md) | datafield | /mod/data/field | Different types of data that may be added to the Database activity module | 1.6+ | | [Database presets](./mod_data/presets.md) | datapreset | /mod/data/preset | Pre-defined templates for the Database activity module | 1.6+ | | [LTI sources](https://docs.moodle.org/dev/External_tool_source) | ltisource | /mod/lti/source | LTI providers can be added to external tools easily through the external tools interface see [Documentation on External Tools](https://docs.moodle.org/en/External_tool). This type of plugin is specific to LTI providers that need a plugin that can register custom handlers to process LTI messages | 2.7+ | @@ -79,7 +79,7 @@ The underscore character is not supported in activity modules for legacy reasons | [TinyMCE editor plugins](./tiny/legacy.md) | tinymce | /lib/editor/tinymce/plugins | Extra functionality for the TinyMCE text editor. | 2.4+ | | [Enrolment plugins](./enrol/index.md) | enrol | /enrol | Ways to control who is enrolled in courses | 2.0+ | | [Authentication plugins](https://docs.moodle.org/dev/Authentication_plugins) | auth | /auth | Allows connection to external sources of authentication | 2.0+ | -| [Admin tools](https://docs.moodle.org/dev/Admin_tools) | tool | /admin/tool | Provides utility scripts useful for various site administration and maintenance tasks | 2.2+ | +| [Admin tools](/general/projects/api/admin-tools) | tool | /admin/tool | Provides utility scripts useful for various site administration and maintenance tasks | 2.2+ | | [Log stores](./logstore/index.md) | logstore | /admin/tool/log/store | Event logs storage back-ends | 2.7+ | | [Availability conditions](./availability/index.md) | availability | /availability/condition | Conditions to restrict user access to activities and sections. | 2.7+ | | [Calendar types](https://docs.moodle.org/dev/Calendar_types) | calendartype | /calendar/type | Defines how dates are displayed throughout Moodle | 2.6+ | diff --git a/docs/apis/plugintypes/repository/_examples/lib.php b/docs/apis/plugintypes/repository/_examples/lib.php index 30346d3054..366cb2711d 100644 --- a/docs/apis/plugintypes/repository/_examples/lib.php +++ b/docs/apis/plugintypes/repository/_examples/lib.php @@ -12,7 +12,7 @@ class repository_pluginname extends repository { * * @param string $encodedpath * @param string $page - * @return array the list of files, including meta infomation + * @return array the list of files, including meta information */ public function get_listing($encodedpath = '', $page = '') { // This methods diff --git a/docs/apis/plugintypes/repository/index.md b/docs/apis/plugintypes/repository/index.md index a71418fb7e..d1e541cc3d 100644 --- a/docs/apis/plugintypes/repository/index.md +++ b/docs/apis/plugintypes/repository/index.md @@ -192,7 +192,7 @@ function supported_filetypes() { A system-wide instance of a repository is created when it is enabled. It is also possible to support both course, and user specific repositories.. This can be achieved by setting the `enablecourseinstances` and `enableuserinstances` options. There are three ways that this can be done: 1. Define **$string\['enablecourseinstances'\]** and **$string\['enableuserinstances'\]** in your plugin's language file. You can check an example in the [filesystem repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/filesystem/lang/en/repository_filesystem.php). -2. The plugin must provide a **get_instance_option_names** method which returns at least one instance option name. This method defined the specific instances options, if none instance atrtribute is needed, the system will not allow the plguin to define course and user instances. Note, you must not define the form fields for these options in the **type_config_form()** function. For example, [filesystem repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/filesystem/lib.php#L439). +2. The plugin must provide a **get_instance_option_names** method which returns at least one instance option name. This method defined the specific instances options, if none instance attribute is needed, the system will not allow the plugin to define course and user instances. Note, you must not define the form fields for these options in the **type_config_form()** function. For example, [filesystem repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/filesystem/lib.php#L439). 3. Several 'core' repositories use the **db/install.php** to create the original repository instance by constructing an instance of the **repository_type** class. The options can be defined in the array passed as the second parameter to the constructor. For example [Wikipedia repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/wikimedia/db/install.php). ### Developer-defined API diff --git a/docs/apis/subsystems/enrol.md b/docs/apis/subsystems/enrol.md index 661039e071..c1044c66a8 100644 --- a/docs/apis/subsystems/enrol.md +++ b/docs/apis/subsystems/enrol.md @@ -223,6 +223,19 @@ The method takes the following parameters: $enrolplugin->add_default_instance($course->id); ``` +### $enrol_plugin->add_custom_instance() + +Add a new enrolment instance to a specific course with custom settings an returns the instance id. This method will create a new instance record in the `enrol` table with the specified settings. + +The method takes the following parameters: + +- Course object +- Array of instance settings + +```php +$enrolplugin->add_custom_instance($course, $settings); +``` + ### $enrol_plugin->delete_instance() Remove an enrolment instance form a course and invalidate all related user enrolments. @@ -235,6 +248,11 @@ The method takes the following parameters: $enrolplugin->delete_instance($instance); ``` +### $enrol_plugin->is_csv_upload_supported() + +Checks whether enrolment plugin is supported in CSV course upload. Defaults to false. Override this function in your enrolment plugin if you want it to +be supported in CSV course upload. + ## See also - [Enrolment plugins](../plugintypes/enrol/index.md) diff --git a/docs/apis/subsystems/output/_inplace/inplace_editable_example.png b/docs/apis/subsystems/output/_inplace/inplace_editable_example.png new file mode 100644 index 0000000000..e276ade2fa Binary files /dev/null and b/docs/apis/subsystems/output/_inplace/inplace_editable_example.png differ diff --git a/docs/apis/subsystems/output.md b/docs/apis/subsystems/output/index.md similarity index 98% rename from docs/apis/subsystems/output.md rename to docs/apis/subsystems/output/index.md index 16b8191b1c..a1c478dc55 100644 --- a/docs/apis/subsystems/output.md +++ b/docs/apis/subsystems/output/index.md @@ -180,7 +180,7 @@ The template used in this plugin is located in the plugin's templates folder. Th ``` -This is the mustache template for this demo. It uses some bootstrap classes directly to position and style the content on the page. `{{sometext}}` is replaced with the variable from the context when this template is rendered. For more information on templates see [Templates](../../guides/templates/index.md). +This is the mustache template for this demo. It uses some bootstrap classes directly to position and style the content on the page. `{{sometext}}` is replaced with the variable from the context when this template is rendered. For more information on templates see [Templates](../../../guides/templates/index.md). ## Output Functions @@ -279,7 +279,7 @@ In earlier versions of Moodle, the third argument was integer `$courseid`. It is Those methods are designed to replace the old ```html_writer::tag(...)``` methods. Even if many of them are just wrappers around the old methods, they are more semantic and could be overridden by component renderers. ::: -While to render complex elements, you should use [templates](../../guides/templates/index.md), some simple elements can be rendered using the following functions: +While to render complex elements, you should use [templates](../../../guides/templates/index.md), some simple elements can be rendered using the following functions: #### container() @@ -338,4 +338,4 @@ In the standard Boost theme this method will output a span using the [Bootstrap - [HTML Guidelines](https://docs.moodle.org/dev/HTML_Guidelines) - [Output renderers](https://docs.moodle.org/dev/Output_renderers) - [Overriding a renderer](https://docs.moodle.org/dev/Overriding_a_renderer) -- [Templates](../../guides/templates/index.md) +- [Templates](../../../guides/templates/index.md) diff --git a/docs/apis/subsystems/output/inplace.md b/docs/apis/subsystems/output/inplace.md new file mode 100644 index 0000000000..ad6224ef06 --- /dev/null +++ b/docs/apis/subsystems/output/inplace.md @@ -0,0 +1,183 @@ +--- +title: Inplace editable +tags: + - AJAX + - Javascript +documentationDraft: true +--- + +The `inplace_editable` element is a mini-API which allows developers to easily support editing of a value on any page. The interface is used in places such as the course section and activity name editing. + +![inplace editable example.png](./_inplace/inplace_editable_example.png) + +## Implementing inplace_editable in a plugin + +The best way is to explain the usage on a simple example. Imagine we have plugin `tool_mytest` that needs to implement in-place editing of a field 'name' from db table `tool_mytest_mytable`. We are going to call this itemtype `mytestname`. Each plugin (or core component) may use as many item types as it needs. + +Define a callback in `/admin/tool/mytest/lib.php` that starts with the plugin name and ends with `_inplace_editable`: + +```php title="admin/tool/mytest/lib.php" +function tool_mytest_inplace_editable($itemtype, $itemid, $newvalue) { + global $DB; + + if ($itemtype === 'mytestname') { + $record = $DB->get_record('tool_mytest_mytable', ['id' => $itemid], '*', MUST_EXIST); + + // Must call validate_context for either system, or course or course module context. + // This will both check access and set current context. + \external_api::validate_context(context_system::instance()); + + // Check permission of the user to update this item. + require_capability('tool/mytest:update', context_system::instance()); + + // Clean input and update the record. + $newvalue = clean_param($newvalue, PARAM_NOTAGS); + + $DB->update_record('tool_mytest_mytable', ['id' => $itemid, 'name' => $newvalue)); + + // Prepare the element for the output: + $record->name = $newvalue; + + return new \core\output\inplace_editable( + 'tool_mytest', + 'mytestname', + $record->id, + true, + format_string($record->name), + $record->name, + get_string('editmytestnamefield', 'tool_mytest'), + get_string('newvaluestring', 'tool_mytest', format_string($record->name)) + ); + } +} +``` + +In your renderer or wherever you actually display the name, use the same `inplace_editable` template: + +```php +$tmpl = new \core\output\inplace_editable( + 'tool_mytest', + 'mytestname', + $record->id, + has_capability('tool/mytest:update', context_system::instance()), + format_string($record->name), + $record->name, + new lang_string('editmytestnamefield', 'tool_mytest'), + new lang_string('newvaluestring', 'tool_mytest', format_string($record->name)) +); +echo $OUTPUT->render($tmpl); +``` + +This was a very simplified example, in the real life you will probably want to: + +- Create a function (or class extending `core\output\inplace_editable`) to form the instance of templatable object so you don't need to duplicate code; +- Use an existing function to update a record (which hopefully also validates input value and triggers events) +- Add unit tests and behat tests + +## Toggles and dropdowns + +You may choose to set the UI for your inplace editable element to be a string value (default), toggle or dropdown. + +Examples of dropdown setup (see also [example by overriding class](https://github.com/moodle/moodle/blob/master/tag/classes/output/tagareacollection.php)): + +```php +$tagcollections = \core_tag_collection::get_collections_menu(true); +$tmpl = new \core\output\inplace_editable( + 'core_tag', + 'tagareacollection', + $tagarea->id, + $editable, + + // Note that $displayvalue is not needed (null was passed in the example above). + // It will be automatically taken from options. + null, + + // $value must be an existing index from the $tagcollections array, + // otherwise exception will be thrown. + $value, + $edithint, + $editlabel +); +$tmpl->set_type_select($tagcollections); +``` + +Example of toggle setup (see also [example by overriding class](https://github.com/moodle/moodle/blob/master/tag/classes/output/tagareaenabled.php)): + +```php +$tmpl = new \core\output\inplace_editable( + 'core_tag', + + 'tagflag', + + $tag->id, + + $editable, + + // $displayvalue usually toggles an image, for example closed/open eye. + // It is easier to implement by overriding the class. + // In this case $displayvalue can be generated from $value during exporting. + $displayvalue, + + // $value must be an existing element of the array + // passed to set_type_toggle(), otherwise exception will be thrown. + $value, + + $hint, +); +$tmpl->set_type_toggle([0, 1]); +``` + +## How does it work + +`inplace_editable` consists of + +- Templatable/renderable **class core\output\inplace_editable** +- Template **core/inplace_editable** +- JavaScript module **core/inplace_editable** +- Web service **core_update_inplace_editable** available from AJAX + +All four call each other so it's hard to decide where we start explaining this circle of friends but let's start with web service. + +1. **Web service** receives arguments (`$component`, `$itemtype`, `$itemid`, `$newvalue`) - it searches for the inplace_editable callback in the component. Then web service calls this callback as `{component}_inplace_editable($itemtype, $itemid, $newvalue)`, this must return templatable element which is sent back to the web service caller. Web service requires user to be logged in. **Any other `capability/access` checks must be performed inside the callback.** + +2. **Templatable element** contains such properties as component, `itemtype`, `itemid`, `displayvalue`, `value`, `editlabel` and `edithint`. When used in a **template** It only renders the display value and the edit link (with `title=edithint`). All other properties are rendered as `data-xxx` attributes. Template also ensures that JavaScript module is loaded. + +3. **JavaScript module** registers a listener to when the edit link is clicked and then it replaces the display value with the text input box that allows to edit value. When user presses "Enter" the AJAX request is called to the web service and code from the component is executed. If web service throws an exception it is displayed for user as a popup. + +## Events + +Plugin page can listen to JQuery events that are triggered on successful update or when update failed. Example of the listeners (as inline JS code): + +```php +$PAGE->requires->js_amd_inline(" +require(['jquery'], function(\$) { + $('body').on('updatefailed', '[data-inplaceeditable]', (e) => { + // The exception object returned by the callback. + const exception = e.exception; + + // The value that user tried to udpated the element to. + const newvalue = e.newvalue; + + // This will prevent default error dialogue. + e.preventDefault(); + + // Do your own error processing here. + }); + $('body').on('updated', '[data-inplaceeditable]', (e) => { + // Everything that web service returned. + const ajaxreturn = e.ajaxreturn; + + // Element value before editing (note, this is raw value and not display value). + const oldvalue = e.oldvalue; + + // Do your own stuff, for example update all other occurences of this element on the page. + }); +}); +"); +``` + +:::note + +The above examples are not recommended and just give an example of how these APIs work. + +::: diff --git a/docs/apis/subsystems/task/index.md b/docs/apis/subsystems/task/index.md index 9bb1325e2f..83ccb5515c 100644 --- a/docs/apis/subsystems/task/index.md +++ b/docs/apis/subsystems/task/index.md @@ -95,7 +95,7 @@ The older syntax of cron.php or modname_cron() is still supported, and will be r ### Generating output -Since Moodle 3.5 it is safe to use the [Output API](../output.md) in cron tasks. Prior to this there may be cases where the Output API has not been initialised. +Since Moodle 3.5 it is safe to use the [Output API](../output/index.md) in cron tasks. Prior to this there may be cases where the Output API has not been initialised. In order to improve debugging information, it is good practice to call `mtrace` to log what's going on within a task execution: diff --git a/docs/devupdate.md b/docs/devupdate.md index d9c786d344..2f77a2f1d1 100644 --- a/docs/devupdate.md +++ b/docs/devupdate.md @@ -12,6 +12,18 @@ import TabItem from '@theme/TabItem'; This page highlights the important changes that are coming in Moodle 4.3 for developers. +## Database table and column names + +Starting with Moodle 4.3 the limits for both table and column names have been raised. Now table names can be up to 53 characters long (from previous 28 characters limit) and column names can be up to 63 characters long (from previous 30 characters limit). + +:::caution +In order to achieve the above, the maximum length for the database prefix (`$CFG->prefix`) is now 10 characters. Installation or upgrade won't be possible with longer prefixes. +::: + +:::caution +If you are writing a plugin intended for older versions of Moodle then you must continue to use the lower limits of 28, and 30. +::: + ## Activity badge The new activity card design proposed for Moodle 4.3 differentiates badge information from other HTML content (displayed using the pre-existing `afterlink` feature). @@ -118,6 +130,32 @@ As a proof of concept, this feature has been implemented by: A new `core_courseformat/local/content/cm/activitybadge` template has been also created to display this activity badge data. As usual, it can be overridden by any format plugin. +## JavaScript String fetchers + + + +New string fetchers were introduced in MDL-79064: + +- `getString` - fetch a single string, resolving in a Native Promise +- `getStrings` - fetch a set of strings, resolving in an array of Native Promises + +Note: These new fetchers will return a _native_ Promise rather than a jQuery Promise. + +The `get_string` and `get_strings` methods have _not_ been deprecated at this time but work is underway to allow for their future deprecation. + +:::caution Native Promises vs jQuery Promises + +The use of jQuery Promises is discouraged in Moodle as they have a different behaviour in some cases: + +- native Promises do not have the `done` method. Please use `then` instead +- native Promises do not have the `fail` method. Please use `catch` instead + +Please note that the behaviour of `catch` differs from the jQuery `fail`. The `catch` method will return a resolved Promise, whist the `fail` method will not. + +You are **strongly** advised to convert all uses of `.done`, and `.fail` in your code to `.then`, and `.catch` as appropriate. + +::: + ## Modal Dialogues Moodle 4.3 brings a number of improvements to Modal dialogues. These improvements focus on: @@ -217,43 +255,61 @@ export default class MyModal extends Modal { -### Registration helper +### Instantiation and deprecation of `core/modal_factory` - + + +Moodle 4.3 introduces a new way to instantiate modals which is significantly simpler than earlier versions. Rather than calling the `create` method on the `modal_factory`, it can now be called on the class that you are instantiating. + +In addition, a new `configure` method is introduced which allows you to override configuration options, provide your own, and more. + +Modals which are instantiated using the new method *do not* need to be registered if they are not consumed using the modal factory. -Moodle 4.3 introduces a new `registerModalType` method on the Modal class to aid in registering a modal. +This change will increase encapsulation and allow modals to handle common actions such as showing on creation, and removing on close much more easily. :::note Compatibility with Moodle 4.2 and older -If your code is intended to work with Moodle 4.2 and older, then you must continue to use the old method of registration. This legacy method will be maintained until Moodle 4.6. +If your code is intended to work with Moodle 4.2 and older, then you must continue to use the existing `core/modal_factory`, and you must continue to register your modal. This legacy method will be maintained until Moodle 4.6. ::: - The legacy registration will continue to work and should be used if your plugin will be used in Moodle 4.2, or earlier. -```js -var MyModal = function(root) { - Modal.call(this, root); -}; - -MyModal.TYPE = 'mod_example/myModal'; -MyModal.prototype = Object.create(Modal.prototype); -MyModal.prototype.constructor = MyModal; +```js title="mod/example/amd/src/mymodal.js" +export default class MyModal extends Modal { + static TYPE = 'mod_example/myModal'; + static TEMPLATE = 'mod_example/my_modal'; + myCustomSetter(value) { + this.value = value; + } +} let registered = false; if (!registered) { ModalRegistry.register(MyModal.TYPE, MyModal, 'mod_example/my_modal'); registered = true; } +``` -return MyModal; +```js title="mod/example/amd/src/consumer.js" +import MyModal from './mymodal'; +import ModalFactory from 'core/modal_factory'; + +// ... +ModalFactory.create({ + TYPE: MyModal.TYPE, +}).then((modal) => { + modal.show(); + modal.myCustomSetter('someValue'); + + return modal; +}) ``` @@ -261,18 +317,36 @@ return MyModal; -The shortcut helper for Modal registration is suitable for Moodle 4.3 onwards. - -```js +```js title="mod/example/amd/src/mymodal.js" export default class MyModal extends Modal { static TYPE = 'mod_example/myModal'; static TEMPLATE = 'mod_example/my_modal'; + + configure(modalConfig) { + // Specify any defaults you like here. + modalConfig.show = true; + super.configure(modalConfig); + + this.myCustomSetter(modalConfig.myCustomValue); + } + + myCustomSetter(value) { + this.value = value; + } } +``` + +```js title="mod/example/amd/src/consumer.js" +import MyModal from './mymodal'; -MyModal.registerModalType(); +// ... +MyModal.create({ + myCustomValue: 'someValue', + show: true, +}); ``` @@ -431,33 +505,82 @@ The MIME icons located in the `pix/f` directory, have undergone an update. These To streamline the variety of icons associated with different MIME types, several specific MIME icons have been replaced. Instead, their corresponding generic icons have been integrated from the existing collection, leading to a more efficient representation: -- avi -> video -- base -> database -- bmp -> image -- html -> markup -- jpeg -> image -- mov -> video -- mp3 -> audio -- mpeg -> video -- png -> image -- quicktime -> video -- tiff -> image -- wav -> audio -- wmv -> video +- `avi` -> `video` +- `base` -> `database` +- `bmp` -> `image` +- `html` -> `markup` +- `jpeg` -> `image` +- `mov` -> `video` +- `mp3` -> `audio` +- `mpeg` -> `video` +- `png` -> `image` +- `quicktime` -> `video` +- `tiff` -> `image` +- `wav` -> `audio` +- `wmv` -> `video` The subsequent MIME icons have been entirely removed: -- clip-353 -- edit -- env -- explore -- folder-open -- help -- move -- parent +- `clip-353` +- `edit` +- `env` +- `explore` +- `folder-open` +- `help` +- `move` +- `parent` :::warning Files utilizing any of these removed icons will now be represented by the "unknown" icon. ::: + +### SVG icons + +A new PHPUnit test has been introduced to verify the presence of SVG files for all system icons in Moodle LMS. Any missing SVG files have been rectified within Moodle LMS. + +:::tip + +Third-party plugins are strongly encouraged to follow suit, adding missing SVG files too, to avoid PHPUnit test failures. + +The SVG icons in Moodle LMS were sourced from https://fontawesome.com/search?m=free&o=r, which offers free icons under the Creative Commons Attribution 4.0 International license, consistent with the Moodle icon set. + +::: + + +## Behat + +### Removal of Goutte and Goutte Mink Driver + +The [goutte behat mink driver](https://packagist.org/packages/behat/mink-goutte-driver) has been replaced by the [browserkit](https://packagist.org/packages/behat/mink-browserkit-driver) one because the former has been abandoned. + +The change should be completely transparent for (near) everybody. Only **if you are using some custom-generated `behat.yml`** file or other configuration alternatives different from the Moodle default one, then, **any `goutte` browser occurrence needs to be changed to `browserkit_http`** when configuring the behat mink extension. + +See MDL-78934 for more details and changes applied. + +### Removal of the `--skip-passed` option + +The legacy (and custom) Behat `--skip-passed` option has been removed completely. Please, use the standard `--rerun` option that provides exactly the same (execution of failed scenarios only). + +## Enrolment methods support in CSV course upload + +As part of [MDL-78855](https://tracker.moodle.org/browse/MDL-78855) new methods have been created for `enrol_plugin` to explicitly mark those enrolment methods that are supported in CSV course upload + +Example below for method to be supported: + +```php title="CSV supported" +public function is_csv_upload_supported(): bool { + return true; +} +``` + +Also a new method has been created for `enrol_plugin` to create enrolment instance with custom settings + +```php title="Add custom instance" +public function add_custom_instance(stdClass $course, ?array $fields = null): ?int { + return $this->add_instance($course, $fields); +} +``` + +In [MDL-73839](https://tracker.moodle.org/browse/MDL-73839) cohort enrolment method has been updated to support CSV course upload. diff --git a/docs/guides/javascript/_examples/str.js b/docs/guides/javascript/_examples/str.js index ff550819bd..631c9ce980 100644 --- a/docs/guides/javascript/_examples/str.js +++ b/docs/guides/javascript/_examples/str.js @@ -1,7 +1,7 @@ -import {get_string as getString} from 'core/str'; +import {getString} from 'core/str'; getString('close', 'core') -.then(closeString => { +.then((closeString) => { window.console.log(closeString); return closeString; diff --git a/docs/guides/javascript/index.md b/docs/guides/javascript/index.md index c9374dac29..2bf8a87d3c 100644 --- a/docs/guides/javascript/index.md +++ b/docs/guides/javascript/index.md @@ -433,7 +433,12 @@ import GetModal from '!!raw-loader!./_examples/promises/getModal'; One of the most helpful core modules is `core/str` which allows you to fetch and render language Strings in JavaScript. -The `core/str` module has two main functions, which both return Promises containing the resolved string. +The `core/str` module has several core methods to support fetching strings: + +- `getString` - fetch a single string, returned in a _native_ Promise +- `getStrings` - fetch a set of strings, returned in an array of _native_ Promises +- `get_string` - fetch a single string, returned in a _jQuery_ Promise +- `get_strings` - fetch a set of strings, returned in an array of _jQuery_ Promises Strings are fetched on request from Moodle, and are then cached in LocalStorage. @@ -441,6 +446,19 @@ import WorkingWithStrings from '!!raw-loader!./_examples/str'; {WorkingWithStrings} +:::caution Native vs jQuery promises + + + +The `getString` and `getStrings` methods should be preferred from Moodle 4.3 onwards. These return _native_ Promises, which differ slightly in behaviour from jQuery Promises. + +Care should be taken in the following scenarios: + +- when writing a plugin which supports Moodle 4.2 or earlier, you _must_ use the `get_string` and `get_strings` methods +- you should _never_ use `.done` or `.fail` as they do not exist in the native Promise specification, and their failure behaviour differs + +::: + ## Templates ## Modals diff --git a/docs/guides/javascript/modal/index.md b/docs/guides/javascript/modal/index.md index d53dda6d01..3f2daef807 100644 --- a/docs/guides/javascript/modal/index.md +++ b/docs/guides/javascript/modal/index.md @@ -8,7 +8,7 @@ tags: -import { CodeBlock, CodeExample, InvalidExample, ValidExample, Since } from '@site/src/components'; +import { CodeBlock, CodeExample, InvalidExample, ValidExample, Since, DeprecatedSince } from '@site/src/components'; The use of modal modules provides a simplified developer experience for creating modal dialogues within Moodle. @@ -20,6 +20,36 @@ Moodle ships with several standard modal types for you to re-use including a sim ## Creating a basic modal + + +Modals can be created by calling the static `create` method on the modal type you wish to create, for example: + +```javascript title="Creating a stadard modal" +import Modal from 'core/modal'; + +export const init = async () => { + const modal = await Modal.create({ + title: 'Test title', + body: '

Example body content

', + footer: 'An example footer content', + show: true, + removeOnClose: true, + }); +} +``` + +Other standard options are described in the JS Documentation for [the MoodleConfig type](https://jsdoc.moodledev.io/master/module-core_modal.html#~MoodleConfig). + +:::note Support for earlier versions + +If you are supporting an earlier version of Moodle, then you must use the Modal Factory and register your modal. + +::: + +### Modal Factory + + + The Modal Factory can be used to instantiate a new Modal. The factory provides a `create` function, accepting some configuration which is used to create the modal instance, and an optional _trigger element_. The `create` function returns a Promise that is resolved with the created modal. The configuration is provided as an object with key/value pairs. The options are: @@ -65,7 +95,9 @@ export const init = async () => { }; ``` -### Using the 'trigger' +#### Using the 'trigger' + + Moodle Modals created using the Modal Factory support an optional _trigger_ element. Whilst this is available, it is no longer recommended and support for it will likely be removed in Moodle 4.3. @@ -93,6 +125,59 @@ A number of commonly used modals are available as standard, these include: - a Save / Cancel modal - a Cancel modal +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + + +:::note + +If you are developing code for use in Moodle 4.2, or earlier, then you must continue to follow the 4.2 guidelines. + +::: + +To use these modals you can call the `create` method on the relevant Modal Class. + +```javascript title="Creating a save/cancel modal" +import ModalSaveCancel from 'core/modal_save_cancel'; +import {get_string as getString} from 'core/str'; + +export const init = async () => { + const modal = await ModalSaveCancel.create({ + title: 'test title', + body: getString('confirmchange', 'mod_example'), + }); + + // ... +}; +``` + +Each type of modal may fire additional events to allow your code to handle the new functionality being offered -- for example, if you wanted to have a save/cancel modal that you did some form validation on before saving you could do something like the example below. + +```javascript title="Listening to a Save event" +import ModalSaveCancel from 'core/modal_save_cancel'; +import ModalEvents from 'core/modal_events'; +import {get_string as getString} from 'core/str'; + +export const init = async () => { + const modal = await ModalSaveCancel.create({ + title: 'test title', + body: getString('confirmchange', 'mod_example'), + }); + + modal.getRoot().on(ModalEvents.save, (e) => { + // ... + }) + + // ... +}; +``` + + + + To use these modals you can provide the `type` argument to the `ModalFactory.create` method. This argument takes a string value and values can be found for these modals in `ModalFactory.TYPES`. ```javascript title="Creating a save/cancel modal" @@ -132,6 +217,9 @@ export const init = async () => { }; ``` + + + ## Creating a custom modal type In some situations it is desirable to write a brand new modal. @@ -141,19 +229,21 @@ There are two parts to this: - a new Modal class which extends the `core/modal` class; and - a template -Creating the Modal class is as simple as extending the `core/modal` class, providing a `TYPE` property, a `TEMPLATE` property, and registering the modal with the modal factory. +:::important Custom modals in Moodle 4.2 and earlier + +Since Moodle 4.3, creating the Modal class is as simple as extending the `core/modal` class, and providing a `TYPE` property, and `TEMPLATE` property. + +For older versions of Moodle, refer to the [Moodle 4.2 documentation](/versioned_docs/version-4.2/guides/javascript/modal/index.md#creating-a-custom-modal-type). + +::: ```javascript title="mod/example/amd/src/my_modal.js" import Modal from 'core/modal'; -import ModalFactory from 'core/modal_factory'; export default MyModal extends Modal { static TYPE = "mod_example/my_modal"; static TEMPLATE = "mod_example/my_modal"; } - -// Modal Registration process for Moodle 4.3 onwards. -MyModal.registerModalType(); ``` The template should extend the `core/modal` core template and can override any of the title, body, or footer regions, for example: @@ -186,18 +276,47 @@ The template should extend the `core/modal` core template and can override any o {{/ core/modal }} ``` -Once defined, the new modal can be instantiated using the Modal Factory, for example: +Once defined, the new modal can be instantiated using the standard `create` method, for example: ```javascript title="Instantiating a custom modal" -import ModalFactory from 'core/modal_factory'; import MyModal from 'mod_example/my_modal'; export default const init = async() => { // ... - const modal = await ModalFactory.create({ - type: MyModal.TYPE, - }); + const modal = await MyModal.create({}); modal.show(); } ``` + +### Overriding default configuration + +When creating your own modal type, you may wish to override the standard configuration. This can be achieved by overriding the `configure` class and providing your own options, for example: + +```javascript title="Overriding standard options" +import Modal from 'core/modal'; + +export default MyModal extends Modal { + static TYPE = "mod_example/my_modal"; + static TEMPLATE = "mod_example/my_modal"; + + configure(modalConfig) { + // Show this modal on instantiation. + modalConfig.show = true; + + // Remove from the DOM on close. + modalConfig.removeOnClose = true; + + super.configure(modalConfig); + + // Accept our own custom arguments too. + if (modalConfig.someValue) { + this.setSomeValue(someValue); + } + } + + setSomeValue(value) { + this.someValue = value; + } +} +``` diff --git a/docs/guides/javascript/reactive/index.md b/docs/guides/javascript/reactive/index.md index 80c75d1c76..4a8636e00e 100644 --- a/docs/guides/javascript/reactive/index.md +++ b/docs/guides/javascript/reactive/index.md @@ -14,7 +14,7 @@ import { Since, TabItem, Tabs, ValidExample, InvalidExample } from '@site/src/co -Third-party plugin developers are free to use any framework they want to implement reactive interfaces like React, Angular or Vue. However, for now Moodle does not provide any of them and all core developments are framework independant. +Third-party plugin developers are free to use any framework they want to implement reactive interfaces like React, Angular or Vue. However, for now Moodle does not provide any of them and all core developments are framework independent. Nevertheless, in terms of reusability, maintainability and user experience the advantages of having a reactive UI are undeniable. For this reason Moodle has an adhoc reactive library that can be used to implement small reactive applications on any Moodle page. diff --git a/docs/guides/templates/index.md b/docs/guides/templates/index.md index 2f6e0bec5a..85ddd48937 100644 --- a/docs/guides/templates/index.md +++ b/docs/guides/templates/index.md @@ -10,7 +10,7 @@ description: A guide to the features and use of Mustache templating in Moodle. Moodle makes use of the [Mustache](https://mustache.github.io) template system to render most of its HTML output, and in some other cases too. -Templates are defined as plain text, which typically includes HTML, and a range of Mustache tags and placeholders. THe Mustache placeholders are replaced with actual values during the render of the page. Mustache templates can be rendered both server-side in PHP, and client-side using JavaScript. Themes can overrides the templates defined in other components if required. +Templates are defined as plain text, which typically includes HTML, and a range of Mustache tags and placeholders. The Mustache placeholders are replaced with actual values during the render of the page. Mustache templates can be rendered both server-side in PHP, and client-side using JavaScript. Themes can overrides the templates defined in other components if required.
A simple example @@ -645,6 +645,7 @@ In PHP you have access to the `$CFG` object to allow access to properties. Musta ``` The properties available on the `globals.config` object are the same as normally exposed for JavaScript; these are gathered from `get_config_for_javascript()` function in `lib/outputrequirementslib.php`. +This object is only available when using client-side Mustache rendering in JavaScript; it is not added to templates rendered with the PHP Mustache engine. ## Core templates diff --git a/general/app/development/custom-push-notifications.md b/general/app/development/custom-push-notifications.md index a555d737aa..5ca5ccec3d 100644 --- a/general/app/development/custom-push-notifications.md +++ b/general/app/development/custom-push-notifications.md @@ -24,9 +24,9 @@ In both cases, please remember that the number of user devices that can receive ## Moodle's Message API -Please read the official Moodle documentation, [Message API](https://docs.moodle.org/dev/Message_API), where it is explained how to create a new message provider within a plugin. +Please read the official Moodle documentation, [Message API](/docs/apis/core/message/), where it is explained how to create a new message provider within a plugin. -Apart from what is explained in the [Message API](https://docs.moodle.org/dev/Message_API) please notice that it is possible to add a "customdata" field (json-encoded) with additional parameters. Those parameters are the ones described in the Airnotifier API section below. +Apart from what is explained in the [Message API](/docs/apis/core/message/) please notice that it is possible to add a "customdata" field (json-encoded) with additional parameters. Those parameters are the ones described in the Airnotifier API section below. ## Airnotifier API diff --git a/general/app/development/setup/app-in-browser.md b/general/app/development/setup/app-in-browser.md index 2a8d875fc0..b48ea23cb5 100644 --- a/general/app/development/setup/app-in-browser.md +++ b/general/app/development/setup/app-in-browser.md @@ -5,10 +5,12 @@ sidebar_position: 1 tags: - Moodle App --- -Browsers are not officially supported by the application, but you can use a **Chromium-based** browser for development if you don't need any native functionality. +Browsers are not officially supported by the application, but you can use a **Chromium-based** browser older than version 119 for development if you don't need any native functionality. :::note Notice -Please notice that it has to be a Chromium-based browser, because the application relies on the [Web SQL Database API](https://caniuse.com/?search=websql) which isn't supported in most browsers. This is a non-standard API, but that's not a problem because this is only used in the browser. Running on a native environment, the application relies on native APIs that are well supported. +Please notice that it has to be a Chromium-based browser older than version 119 because the application relies on the [Web SQL Database API](https://caniuse.com/?search=websql) which isn't supported in most browsers. This is a non-standard API, but that's not a problem because this is only used in the browser. Running on a native environment, the application relies on native APIs that are well supported. + +This requirement may be dropped in future versions of the app: [MOBILE-4304](https://tracker.moodle.org/browse/MOBILE-4304) ::: ## Differences between Chromium and Google Chrome @@ -34,7 +36,7 @@ Disadvantages: ## Installation and configuration -You can install the Chromium browser by downloading it from [the official download page](https://www.chromium.org/getting-involved/download-chromium). +You can install the Chromium browser by downloading it from [the official download page](https://www.chromium.org/getting-involved/download-chromium) (make sure to install a version older than 119). In order to run the Moodle App, we recommend that you launch the browser with a couple of arguments. These are necessary to disable some of the limitations that don't exist in the native application, and also prepare the development environment. @@ -46,6 +48,10 @@ chromium-browser --allow-file-access-from-files --disable-web-security --disable start chrome.exe --allow-file-access-from-files --disable-web-security --disable-site-isolation-trials --allow-running-insecure-content --no-referrers --unlimited-storage --auto-open-devtools-for-tabs --user-data-dir=~/.chromium-dev-data ``` +```bash title="MacOS" +open -a /Applications/Chromium.app --args --allow-file-access-from-files --disable-web-security --disable-site-isolation-trials --allow-running-insecure-content --no-referrers --unlimited-storage --auto-open-devtools-for-tabs --user-data-dir=~/.chromium-dev-data +``` + If you are using other operative system, check out [how to run chromium with flags](https://www.chromium.org/developers/how-tos/run-chromium-with-flags) in other environments. Depending on the version of your browser, you may get a warning message saying "You are using an unsupported command-line flag". This is expected and can safely be ignored (for development). diff --git a/general/app/development/setup/troubleshooting.md b/general/app/development/setup/troubleshooting.md index c0750c52b7..b10650b076 100644 --- a/general/app/development/setup/troubleshooting.md +++ b/general/app/development/setup/troubleshooting.md @@ -224,3 +224,7 @@ There will be a pause (a few minutes) while building everything. It should finis ` Then you can access it by running Chrome and connecting to localhost:8100. + +## `window.openDatabase` is not a function + +This error appears in browsers that don't support the [WebSQL](https://caniuse.com/?search=websql) API. We suggest using a [Chromium-based browser older than version 119](./app-in-browser.md). diff --git a/general/community/credits/thirdpartylibs.md b/general/community/credits/thirdpartylibs.md index 907ef23711..0082f8f41c 100644 --- a/general/community/credits/thirdpartylibs.md +++ b/general/community/credits/thirdpartylibs.md @@ -21,6 +21,27 @@ Provide a great search experience without the need for external, server-side, se - **License**: MIT - **URL**: [https://github.com/olivernn/lunr.js](https://github.com/olivernn/lunr.js) +### Assert + +- **Location**: admin/tool/mfa/factor/totp/extlib/Assert +- **Version**: 2.1 +- **License**: MIT +- **URL**: [https://github.com/beberlei/assert](https://github.com/beberlei/assert) + +### OTPHP + +- **Location**: admin/tool/mfa/factor/totp/extlib/OTPHP +- **Version**: 9.1.1 +- **License**: MIT +- **URL**: [https://github.com/Spomky-Labs/otphp](https://github.com/Spomky-Labs/otphp) + +### Constant-Time Encoding + +- **Location**: admin/tool/mfa/factor/totp/extlib/ParagonIE/ConstantTime +- **Version**: 2.1.1 +- **License**: MIT +- **URL**: [https://github.com/paragonie/constant_time_encoding](https://github.com/paragonie/constant_time_encoding) + ### jQuery EU Cookie Law popups An easy-to-install jQuery plugin to create EU Cookie Law popups and for GDPR compliance. @@ -130,7 +151,7 @@ JavaScript library to insulate apps from spec changes and prefix differences in Simple yet flexible JavaScript charting for designers & developers. - **Location**: lib/amd/src/chartjs-lazy.js -- **Version**: 4.2.1 (with Moodle customisations) +- **Version**: 4.4.0 (with Moodle customisations) - **License**: MIT - **URL**: [https://github.com/chartjs/Chart.js](https://github.com/chartjs/Chart.js) - **Copyright holders**: @@ -218,7 +239,7 @@ Beautify HTML code in Atto. CodeMirror is a versatile text editor implemented in JavaScript for the browser. - **Location**: lib/editor/atto/plugins/html/yui/src/codemirror -- **Version**: 5.65.12 +- **Version**: 5.65.15 - **License**: MIT - **URL**: [https://github.com/codemirror/codemirror5](https://github.com/codemirror/codemirror5) @@ -263,7 +284,7 @@ CodeMirror is a versatile text editor implemented in JavaScript for the browser. Library to parse easily data and sprite sheets for emoji. - **Location**: lib/emoji-data -- **Version**: 14.0.1 (with Moodle customisations) +- **Version**: 15.0.1 (with Moodle customisations) - **License**: MIT - **URL**: [https://github.com/iamcal/emoji-data/](https://github.com/iamcal/emoji-data/) - **Copyright holders**: @@ -394,7 +415,7 @@ Filters HTML. jQuery is a fast, small, and feature-rich JavaScript library widely used on moodle. - **Location**: lib/jquery -- **Version**: 3.6.4 +- **Version**: 3.7.1 - **License**: MIT - **URL**: [https://github.com/jquery/jquery](https://github.com/jquery/jquery) - **Copyright holders**: @@ -416,7 +437,7 @@ jQuery UI is a set of user interface interactions, effects, widgets, and themes A library used for building IMS-certified LTI 1.3 tool providers in PHP. - **Location**: lib/lti1p3 -- **Version**: 5.2.6 (with Moodle customisations) +- **Version**: 5.4.1 (with Moodle customisations) - **License**: Apache 2.0 - **URL**: [https://github.com/packbackbooks/lti-1-3-php-library](https://github.com/packbackbooks/lti-1-3-php-library) - **Copyright holders**: @@ -612,7 +633,7 @@ Class for sending email using either sendmail, PHP mail(), or SMTP. Methods are Library to read, write and create spreadsheet documents in PHP. - **Location**: lib/phpspreadsheet -- **Version**: 1.28.0 (with Moodle customisations) +- **Version**: 1.29.0 (with Moodle customisations) - **License**: MIT - **URL**: [https://github.com/PHPOffice/PhpSpreadsheet](https://github.com/PHPOffice/PhpSpreadsheet) @@ -791,6 +812,13 @@ URL syntax validation using PHP and regular expressions. - **Copyright holders**: - 2000 Rod Apeldoorn - rod(at)canowhoopass(dot)com +### WebAuthn + +- **Location**: lib/webauthn/src +- **Version**: 2.0.1 +- **License**: MIT +- **URL**: [https://github.com/lbuchs/WebAuthn](https://github.com/lbuchs/WebAuthn) + ### XHProf A Hierarchical Profiler for PHP. diff --git a/general/community/plugincontribution/checklist.md b/general/community/plugincontribution/checklist.md index 34400d8f84..46ac34361a 100644 --- a/general/community/plugincontribution/checklist.md +++ b/general/community/plugincontribution/checklist.md @@ -199,6 +199,8 @@ Examples of issues that will prevent your plugin from being approved: 1. There is no public and transparent issue tracker where the community members can leave feedback, report bugs and suggest improvements. 1. Your SQL fails to work on PostgreSQL even when working on MySQL. +1. [Namespace collisions](../../development/policies/codingstyle/frankenstyle.md). +1. Compliance with [security guidelines](../../development/policies/security/index.md). 1. It integrates with an external system and does not have the privacy API correctly implemented. 1. It is an activity module and does not have the backup and restore API implemented. diff --git a/general/contentguidelines.md b/general/contentguidelines.md new file mode 100644 index 0000000000..0d487ac979 --- /dev/null +++ b/general/contentguidelines.md @@ -0,0 +1,14 @@ +--- +title: The Moodle content guidelines +sidebar_label: Content guidelines +sidebar_position: 1 +tags: + - Content style guide + - UX Writing +--- + +The Moodle content guidelines are for UX writers, copywriters, marketers, developers, translators, and anyone else writing for Moodle. + +These guidelines provide recommendations on how to write effective, consistent, and reliable content for Moodle's products. + +By following these guidelines, you can help ensure that we're effective at communicating key messages to our users, and that we maintain consistency across all parts of the Moodle experience. diff --git a/general/contentguidelines/01-productwriting/_category_.yml b/general/contentguidelines/01-productwriting/_category_.yml new file mode 100644 index 0000000000..b7013b6e77 --- /dev/null +++ b/general/contentguidelines/01-productwriting/_category_.yml @@ -0,0 +1,3 @@ +label: Product writing guidelines +link: + type: generated-index diff --git a/general/contentguidelines/01-productwriting/confirm-msg.md b/general/contentguidelines/01-productwriting/confirm-msg.md new file mode 100644 index 0000000000..b704207c47 --- /dev/null +++ b/general/contentguidelines/01-productwriting/confirm-msg.md @@ -0,0 +1,183 @@ +--- +title: Confirmation messages +sidebar_position: 2 +tags: +- Content style guide +- UX Writing +--- +import {ValidExample, InvalidExample } from '@site/src/components'; + +Confirmation messages prompt people to confirm actions that have significant consequences or are difficult to undo. They can also help prevent errors or unexpected results by verifying user intent before proceeding with an action. + +Clear and concise confirmation messages help people feel more confident and in control of their actions within the Moodle products. + +## Related components + +[HTML modal](https://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/moodle/components/dom-modal/) + +## Basic guidelines + +- Address a single task. +- Ask a clear, specific question. +- Provide clear options to either confirm or cancel the action. +- Explain the consequences of the action so people can make an informed decision. + +## Content + +### Title + +The title or heading of a confirmation message should focus only on one task, and mention the specific action that the user wants to perform. + + + +**Remove grade?** + + + + + +**Confirm action?** + + + +Ask a clear, unambiguous question. + + + +**Delete question?** + + + + + +**Confirmation** + + + + + +**Send notification?** + + + + + +**Warning** + + + +Don't include articles like 'a', 'an' or 'the', so that the question is short and easy to scan. + +### Description + +The description should explain the consequences of the action and share additional details that enable people to make a confident decision. + + + +**Delete entry?** +This will delete the entry 'My first blog post'. + + + + + +**Delete entry?** +Are you sure you want to delete the blog post? + + + +Don't repeat information from the title. + + + +**Remove account 'Barbara Gardner'?** +This account and its data on the site [site name] will be removed from the app on this device. + + + + + +**Remove account 'Barbara Gardner'?** +Are you sure you want to remove this account? + + + +Save "Are you sure?" for actions that have very serious consequences. For example, actions that could prevent a course or activity from working properly, or deleting something that can't be retrieved from the recycle bin. + + + +**Delete tool?** +This tool is currently being used in at least one activity in your course. If you delete this tool, the activities that use it will no longer work. Are you sure you want to delete the tool? + + + + + +**Delete activity?** +Are you sure you want to delete the activity? + + + +### Calls to action + +Calls to action (CTAs) should be clear and simple, and offer a straightforward way out. + + + +**Delete downloaded data?** +Cancel | Delete + + + + + +**Delete downloaded data?** +Cancel | Continue + + + + + +**Delete downloaded data?** +No | Yes + + + +Use the same verb in both the title and the confirmation button to make the content more scannable and summarise outcomes. + + + +**Move** selected activities? +Cancel | **Move** + + + + + +**Move** selected activities? +Cancel | **Continue** + + + + + +**Delete** tool? +Cancel | **Remove** + + + +Avoid 'cancelling cancellations' + + + +**Cancel booking?** +Keep my booking | Cancel booking + + + + + +**Cancel subscription?** +Cancel | Confirm cancellation + + diff --git a/general/contentguidelines/01-productwriting/success-msg.md b/general/contentguidelines/01-productwriting/success-msg.md new file mode 100644 index 0000000000..ce512663dc --- /dev/null +++ b/general/contentguidelines/01-productwriting/success-msg.md @@ -0,0 +1,117 @@ +--- +title: Success messages +sidebar_position: 3 +tags: +- Content style guide +- UX Writing +--- +import {ValidExample, InvalidExample } from '@site/src/components'; + +Success messages tell users that they've completed a task or achieved a goal, or that an action within the system has been successfully completed. + +## Related components + +[Notification](https://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/moodle/components/notifications/) + +## Basic guidelines + +- Keep success messages short and scannable. +- Focus on what the user has achieved or the system has completed. +- Avoid technical jargon. +- Add a full stop at the end of success messages. + +## Content + +### Message + +Use the short form of passive instead of the full form. + + + +Changes saved. + + + + + +Your changes have been saved. + + + + + +Changes were saved. + + + +Use a verb that describes the action that has been completed successfully, especially if the success message is triggered by an action that the user took. + + + +Course created. + + + + + +The course has been added to your site. + + + + + +Tool deleted. + + + + + +The tool was removed. + + + +In general, avoid expressions like 'successfully' or 'successful'. + + + +Preset applied. + + + + + +The preset has been successfully applied. + + + +Don't repeat information from the title. + + + +Message sent. + + + + + +Message delivery successful. + + + +### Calls to action + +Use a call to action only if there are any next steps that users can take. For example, seeing something new they have created. + +Keep calls to action as short and actionable as you can. + + + +Message posted. You have 30 minutes to edit it. **See post**. + + + + + +Your message has been posted successfully. You have 30 mins to make any changes to it. + + diff --git a/general/contentstyleguide/01-voice/_category_.yml b/general/contentguidelines/02-styleguide/01-voice/_category_.yml similarity index 100% rename from general/contentstyleguide/01-voice/_category_.yml rename to general/contentguidelines/02-styleguide/01-voice/_category_.yml diff --git a/general/contentstyleguide/01-voice/contentprinciples.md b/general/contentguidelines/02-styleguide/01-voice/contentprinciples.md similarity index 100% rename from general/contentstyleguide/01-voice/contentprinciples.md rename to general/contentguidelines/02-styleguide/01-voice/contentprinciples.md diff --git a/general/contentstyleguide/01-voice/values.md b/general/contentguidelines/02-styleguide/01-voice/values.md similarity index 100% rename from general/contentstyleguide/01-voice/values.md rename to general/contentguidelines/02-styleguide/01-voice/values.md diff --git a/general/contentstyleguide/01-voice/voiceandtone.md b/general/contentguidelines/02-styleguide/01-voice/voiceandtone.md similarity index 100% rename from general/contentstyleguide/01-voice/voiceandtone.md rename to general/contentguidelines/02-styleguide/01-voice/voiceandtone.md diff --git a/general/contentstyleguide/01-voice/whoweare.md b/general/contentguidelines/02-styleguide/01-voice/whoweare.md similarity index 100% rename from general/contentstyleguide/01-voice/whoweare.md rename to general/contentguidelines/02-styleguide/01-voice/whoweare.md diff --git a/general/contentstyleguide/02-style/_category_.yml b/general/contentguidelines/02-styleguide/02-style/_category_.yml similarity index 100% rename from general/contentstyleguide/02-style/_category_.yml rename to general/contentguidelines/02-styleguide/02-style/_category_.yml diff --git a/general/contentstyleguide/02-style/grammar.md b/general/contentguidelines/02-styleguide/grammar.md similarity index 100% rename from general/contentstyleguide/02-style/grammar.md rename to general/contentguidelines/02-styleguide/grammar.md diff --git a/general/contentguidelines/02-styleguide/index.md b/general/contentguidelines/02-styleguide/index.md new file mode 100644 index 0000000000..e66cd0cd91 --- /dev/null +++ b/general/contentguidelines/02-styleguide/index.md @@ -0,0 +1,9 @@ +--- +title: Style guide +tags: +- Content style guide +- UX Writing +--- +import {ValidExample, InvalidExample } from '@site/src/components'; + +We use this guide to help us create a clear and consistent approach to the content we produce: from our website, marketing, and communications to the actual text in Moodle products. diff --git a/general/contentstyleguide/02-style/translation.md b/general/contentguidelines/02-styleguide/translation.md similarity index 100% rename from general/contentstyleguide/02-style/translation.md rename to general/contentguidelines/02-styleguide/translation.md diff --git a/general/contentstyleguide/02-style/wordlist.md b/general/contentguidelines/02-styleguide/wordlist.md similarity index 100% rename from general/contentstyleguide/02-style/wordlist.md rename to general/contentguidelines/02-styleguide/wordlist.md diff --git a/general/contentstyleguide.md b/general/contentstyleguide.md deleted file mode 100644 index 2c114259e4..0000000000 --- a/general/contentstyleguide.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: The Moodle content style guide -sidebar_label: Content style guide -sidebar_position: 1 -tags: - - Content style guide - - UX Writing ---- - -The Moodle content style guide is for UX writers, copywriters, marketers, developers, translators, and anyone else writing for Moodle. - -We use this guide to help us create a clear and consistent approach to the content we produce: from our website, marketing, and communications to the actual text in Moodle products. diff --git a/general/development/policies/accessibility.md b/general/development/policies/accessibility.md index def00ab7ba..c5a2f52930 100644 --- a/general/development/policies/accessibility.md +++ b/general/development/policies/accessibility.md @@ -6,6 +6,8 @@ tags: - Certification --- +import { ValidExample } from '@site/src/components'; + Moodle is designed to provide equal functionality and information to all people. This means that there should be no barriers for people regardless of disabilities, assistive technologies that are used, different screen sizes and different input devices (for example mouse, keyboard and touchscreen). ## Accessibility conformance @@ -121,7 +123,80 @@ See [the ARIA best practice advice on landmarks](https://www.w3.org/TR/wai-aria- All pages should have a unique title that describes the current page. -See [the WCAG 2.1 success criteria for web page titles](https://www.w3.org/TR/WCAG21/#page-titled) for further information. +Some tips for providing a meaningful page title: + +- The page title must be accurate and informative. +- If the page causes a _change of context_ (for example, a search functionality), it should describe the result or change of context to the user. +- It should be concise. +- If possible, it should uniquely identify the page. +- The most identifying information should come first. + +:::note change of context + +(not to be confused with Moodle's `\core\context` class and its implementations) + +According to the [WCAG 2.1 Understanding Docs](https://www.w3.org/WAI/WCAG21/Understanding/on-focus.html#dfn-changes-of-context), a change in context is a major change that, if made without user awareness, can disorient users who are not able to view the entire page simultaneously. It can include changes of user agent, viewport, focus, or content that changes the meaning of the web page. + +::: + +#### Example + +Consider that a student is on the submission page of an assignment activity called `Kinetics problem set 1` in the `Physics 101` course on the `Mount Orange School` Moodle site. + +Then a suitable page title for the page would be something like: + + + +The most unique identifying information first represented by the activity name and its sub-page, then followed by broader identifiers such as the course name and the site name. + +`Kinetics problem set 1: Submit assignment | Physics 101 | Mount Orange School` + + + + + +The most unique identifying information first represented by the name of the sub-page, followed by the activity name that the page belongs to, then followed by broader identifiers such as the course name and the site name. + +`Submit assignment | Kinetics problem set 1 | Physics 101 | Mount Orange School` + + + +#### Separating components of a page title + +When separating the components of the page tile, please use the `moodle_page::TITLE_SEPARATOR` constant. + + + +```php +[$course, $cm] = get_course_and_cm_from_cmid($id); +// Activity name and its sub-page as the unique identifying information. +$pagename = format_string($cm->name) . ': ' . get_string('view'); +// Course name. +$coursename = format_string($course->fullname); +// Set the page title, combining the activity page's name and course name using the title separator constant. +$PAGE->set_title($pagename . moodle_page::TITLE_SEPARATOR . $coursename); +``` + + + +#### Site name on the page title + +You should not add the name of the site when setting the page title using `$PAGE->set_title()`. The site name is automatically appended to the end of the page title in the correct format when using `$PAGE->set_title()`. + +:::info + +Administrators can use the `sitenameinititle` configuration setting to configure how this is shown in the title with possible options including: + +- the _full name_ of the site, for example, "Mount Orange School" +- the _short name_ of the site, for example: "MOS" + +This is automatically handled by `$PAGE->set_title()`. +::: + +#### Useful resources + +- [Understanding Success Criterion 2.4.2: Page Titled (Level A)](https://www.w3.org/WAI/WCAG21/Understanding/page-titled) +- [Technique G88: Providing descriptive titles for Web pages](https://www.w3.org/WAI/WCAG21/Techniques/general/G88) ### Advanced UX Widgets diff --git a/general/development/policies/codingstyle/index.md b/general/development/policies/codingstyle/index.md index f84f9de2d3..ba07bd1913 100644 --- a/general/development/policies/codingstyle/index.md +++ b/general/development/policies/codingstyle/index.md @@ -1769,9 +1769,9 @@ There are some tags that are only allowed within some contexts and not globally. - `@Given`, `@When`, `@Then`, within the [behat steps definitions](../../tools/behat/writing.md#writing-new-acceptance-test-step-definitions). - `@covers`, `@coversDefaultClass`, `@coversNothing`, `@uses` to better control coverage within [unit tests](https://docs.moodle.org/dev/Writing_PHPUnit_tests#Generators). - `@dataProvider` and `@testWith`, to provide example data and expectations, within [unit tests](https://docs.moodle.org/dev/Writing_PHPUnit_tests#Generators). -- `@depends`, to express dependencies between tests, where each producer returned data in passed to consumers. See [`@depends` examples](https://phpunit.readthedocs.io/en/9.5/writing-tests-for-phpunit.html#writing-tests-for-phpunit-examples-stacktest2-php) for more information. +- `@depends`, to express dependencies between tests, where each producer returned data in passed to consumers. See [`@depends` examples](https://docs.phpunit.de/en/9.6/writing-tests-for-phpunit.html#writing-tests-for-phpunit-examples-stacktest2-php) for more information. - `@group`, for easier collecting unit tests together, following the guidelines in the [PHPUnit MoodleDocs](../../tools/phpunit.md#using-the-group-annotation). -- `@requires`, to specify unit test requirements and skip if not fulfilled. See [`@requires` usages](https://phpunit.readthedocs.io/en/9.5/incomplete-and-skipped-tests.html#incomplete-and-skipped-tests-requires-tables-api) for more information. +- `@requires`, to specify unit test requirements and skip if not fulfilled. See [`@requires` usages](https://docs.phpunit.de/en/9.6/incomplete-and-skipped-tests.html#incomplete-and-skipped-tests-requires-tables-api) for more information. - `@runTestsInSeparateProcesses` and `@runInSeparateProcess`, to execute an individual test or a testcase in isolation. To be used only when strictly needed. ### Files diff --git a/general/development/policies/deprecation.md b/general/development/policies/deprecation.md index ccd09fba98..e642ea2e40 100644 --- a/general/development/policies/deprecation.md +++ b/general/development/policies/deprecation.md @@ -14,6 +14,8 @@ tags: ## Why is deprecation needed? +import { ValidExample, InvalidExample, TabItem, Tabs } from '@site/src/components'; + In an open source project, the end use of the codebase varies. People may have customisations and plugins that depend on a function that has been targeted for deprecation. Rather than simply removing a function, we must gracefully deprecate the function over a period covered by a number of released versions. ## What is Moodle's deprecation policy? @@ -93,29 +95,137 @@ Longer deprecation periods can be considered for functions that are widely used. ## Parameters deprecation -- The deprecated parameter should be renamed to `$unused` and it's default value changed to `null`. -- The respective parameter phpDoc should be updated stating the parameter has been deprecated since version X.X and should not be used any more. +Whilst it is possible to deprecate individual method parameters, care must be taken in doing so. -``` - @param null $unused This parameter has been deprecated since 4.0 and should not be used anymore. -``` +If a method is overridden then it is often not possible to change parameters. This includes changing any type hint, or adding a new default value. Additionally, adding a default value to any argument is only possible if all remaining arguments are optional too. -:::note +:::tip + +It is strongly advised to deprecate an entire method, rather than deprecating a single parameter. + +::: + +- Deprecated parameters **MUST** be retained, and **MUST NOT** be renamed +- The respective parameter phpDoc should be updated stating the parameter has been deprecated since version X.X and should not be used any more +- Update all calls to the affected function and either: + - converting to use named parameters, removing the deprecated parameter; or + - removing if at the end of a list of optional parameters. +- Add a mention to the corresponding `upgrade.txt` file, documenting that the deprecated parameter should not be used any more +- Add a mention to the [Developer Update notes](https://github.com/moodle/devdocs/blob/main/docs/devupdate.md), documenting that the deprecated parameter should not be used any more +- _Where possible_: + - If a type was previously specified it should be altered to be made nullable + - If the default value is not already `null`, then it should be updated to `null` + - If the default value was not already `null`, and a non-null value is provided, a debugging notice should be emitted +- Where it is not possible to make the the type nullable, consider deprecating the method and creating a new one with the updated parameters + +:::caution Changes to default values and types -Remember the phpDoc parameter type should also be updated to `null`. +The [Covariance and Contravariance rules for PHP](https://www.php.net/manual/en/language.oop5.variance.php) prevent changes to argument types and defaults when a class is extended and that method overridden. + +When deprecating a method which is _likely_ to be extended, you should strongly consider deprecating the entire method and creating a replacement method with the updated arguments instead. This includes all renderer methods. ::: -- Show a debugging message if that parameter is being provided in the function call: + + + + +```php +/** + * Greet a user and their pets. Remind them how old they are. + * + * @param string $name The name of the individual + * @param int $age The age of the individaul + * @param string[] $pets A list of pets that the individual has + * @return The greeting + */ +public function greet_person( + string $name, + int $age, + array $pets = [], +}: string { + return sprintf( + "A big, warm, welcome to %s who, at the grand old age of %d, has %d pets!", + $name, + $age, + count($pets), + ); +} +``` + + + +```php +/** + * Greet a user and their pets. + * + * @param string $name The name of the individual + * @param null|int $age This parameter has been deprecated since 4.0 and should not be used anymore. + * @param string[] $pets A list of pets that the individual has + */ +public function greet_person( + string $name, + null|int $age = null, + array $pets = [], +}: void { + if ($age !== null) { + debugging( + 'The age argument has been deprecated. Please remove it from your method calls.', + DEBUG_DEVELOPER, + ); + } + + return sprintf( + "A big, warm, welcome to %s who has %d pets!", + $name, + count($pets), + ); +} ``` - if ($unused !== null) { - debugging('Deprecated argument passed to ' . __FUNCTION__, DEBUG_DEVELOPER); - } + + + + +```php +/** + * Greet a user and their pets. + * + * @param string $name The name of the individual + * @param null|int $age This parameter has been deprecated since 4.0 and should not be used anymore. + * @param string[] $pets A list of pets that the individual has + */ +public function greet_person( + string $name, + int $age, + array $pets = [], +}: void { + debugging( + 'The `greet_person` method has been deprecated and replaced with `greet_person_with_pets`. ' . + 'Please update your method calls accordingly.', + DEBUG_DEVELOPER, + ); + + return $this->greet_person_with_pets( + name: $name, + pets: $pets, + ); +} ``` -- Update all calls to the affected function removing the deprecated parameter. -- Add a mention to corresponding `upgrade.txt` documenting the deprecated parameter should not be used any more. + + + + +:::note Deprecations for core methods in Moodle 4.1 and earlier + +Prior to support for PHP 8.0 in Moodle 4.2, the policy for parameter argument deprecation stated that deprecated parameters must be renamed to `$unused` or a similar name. + +This has been changed to no longer allow renaming of arguments because it can lead to fatal errors if the calling code makes use of named parameter arguments. + +Named parameter arguments are available from PHP 8.0 onwards. + +::: ## See also... diff --git a/general/development/policies/php.md b/general/development/policies/php.md index 14a36cb5f6..7b9214be55 100644 --- a/general/development/policies/php.md +++ b/general/development/policies/php.md @@ -49,6 +49,12 @@ You must be logged in to tracker to see issues in Epics. ## PHP supported versions +### PHP 8.2 + + + +PHP 8.2 **can be used with** Moodle 4.2.3, Moodle 4.3 and later releases. See MDL-76405 for details. + ### PHP 8.1 @@ -93,10 +99,6 @@ PHP 7.0 **can be used with** Moodle 3.0.1, Moodle 3.1 and later releases. It is ## PHP versions under development -### PHP 8.2 - -PHP 8.2 support **is currently being implemented** for Moodle 4.2.x, 4.3.0 and later releases. Hence it's still **incomplete and only for development purposes**. See MDL-76405 for details. - ### PHP 8.3 PHP 8.3 support **is currently being implemented**. We hope to make this available for Moodle 4.4 but this has not yet been confirmed and is subject to change. See MDL-76426 for details. diff --git a/general/development/tools/gha.md b/general/development/tools/gha.md index f539a4dab9..dec677cb31 100644 --- a/general/development/tools/gha.md +++ b/general/development/tools/gha.md @@ -42,7 +42,7 @@ And that's all, pretty nice, simple and effective. ### How do I configure the PHPUnit executions -Since Moodle 3.11.8 and 4.0.2, it's possible to configure the PHPUnit executions by creating a [GitHub repository secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository) named `phpunit_options`. Just setup its value to the options that you want to pass to PHPUnit and they will come into effect for all runs. For a list of [PHPUnit available options](https://phpunit.readthedocs.io/en/9.5/textui.html#command-line-options) use the `vendor/bin/phpunit --help` command. +Since Moodle 3.11.8 and 4.0.2, it's possible to configure the PHPUnit executions by creating a [GitHub repository secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository) named `phpunit_options`. Just setup its value to the options that you want to pass to PHPUnit and they will come into effect for all runs. For a list of [PHPUnit available options](https://docs.phpunit.de/en/9.6/textui.html#command-line-options) use the `vendor/bin/phpunit --help` command. ## Moodle plugins diff --git a/general/development/tools/phpcs.md b/general/development/tools/phpcs.md index 17c188be53..b9642d4f85 100644 --- a/general/development/tools/phpcs.md +++ b/general/development/tools/phpcs.md @@ -9,22 +9,25 @@ sidebar_position: 1 import { Since } from '@site/src/components'; -## Overview +[PHPCodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) is a tool used to analyse PHP code using a set of rules. In many cases these rules can be used to automatically fix the errors they identify. -This document describes the various code sniffing tools that Moodle recommends, their purpose, and their usage. +Moodle has two sets of published rule-sets intended to meet the [Moodle Coding Style](../policies/codingstyle/index.md), and identify any parts of the code do not conform to this style. These are: -[PHPCodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) is a tool used to analyse PHP code using a set of rules. In many cases these rules can be used to automatically fix the errors they identify. +- `moodle` - The standard ruleset which meets all variants of the coding style +- `moodle-extra` - The extended standard which includes recommended best practices -Moodle has published a ruleset intended to meet the [Moodle Coding Style](../policies/codingstyle/index.md), and identify any parts of the code do not conform to this style. +We recommend use of the `moodle-extra` standard, particularly when writing new code. ## Installation -It is recommend that both the phpcs scripts, and the Moodle ruleset, are installed globally using Composer: +The recommended method of installation is via the global composer command: ```console composer global require moodlehq/moodle-cs ``` +This ensures that you have a single copy of the standard used for all code. + ### Configuration @@ -33,9 +36,23 @@ A PHPCS configuration is included in the Moodle codebase and ensures that the co This can be further extended by generating an additional configuration to ignore all third-party libraries using the `grunt ignorefiles` command. See [grunt](./nodejs.md#grunt) for further information on using Grunt. -#### Community plugins, and older Moodle versions +If you would like to make use of the `moodle-extra` standard then you should create a `.phpcs.xml` file with the following content: -If you are developing your own plugin outside of the main Moodle directory, or you are working with an older version of Moodle, the easiest way to configure phpcs to use the Moodle ruleset is by creating a local `phpcs.xml.dist` configuration at the root directory of your repository with the following content: +```xml + + + + + +``` + +This will extend the standard configuration, and apply the extra standard on top of it. + +#### Moodle 3.10 and earlier + +The easiest way to have PHP CodeSniffer pick up your preferred style is via a local configuration file. + +You can create a file named `.phpcs.xml` with the following contents: ```xml @@ -44,48 +61,42 @@ If you are developing your own plugin outside of the main Moodle directory, or y ``` -If you do not wish to include this file in your repository, or you are using an older version of Moodle, then you should add this to your local gitignore files. On a Unix-like system this can be achieved with: +If you wish to use the `moodle-extra` coding style, then you can use the following content: -```console -echo phpcs.xml.dist >> .git/info/exclude +```xml + + + + ``` :::info -The `.git/info/exclude` file is a per-repository version of the `.gitignore` file. Whilst `.gitignore` is tracked within the Moodle codebase and a version is shipped with Moodle, the `.git/info/exclude` file is local to your git clone. - -See the [gitignore](https://git-scm.com/docs/gitignore) documentation for more information on the gitignore feature. +Third-party library code will not be ignored with these versions of Moodle. ::: -#### System-side default standard - -Although not recommended, you can configure the Moodle ruleset as the system-wide default for phpcs: - -```php -phpcs --config-set default_standard moodle -``` - -:::important Not recommended +:::tip Ignoring the file with Git -This approach is **not recommended** and is only preserved for reference. +We recommend configuring your code checkout to ignore the `.phpcs.xml` file by adding a local ignore record to `.git/info/exclude` ::: -## Moodle plugin - -Moodle includes a copy of the PHPCodeSniffer package, and the Moodle ruleset, as part of the [`moodle-local_codechecker`](https://github.com/moodlehq/moodle-local_codechecker) Moodle plugin. This makes the code checker available via a web-based interface for checking the syntax of a given file or folder. +#### Community plugins, and older Moodle versions -One way to install this plugin is using `git clone`: +If you are developing your own plugin outside of the main Moodle directory, or you are working with an older version of Moodle, the easiest way to configure phpcs to use the Moodle ruleset is by creating a local `phpcs.xml.dist` configuration at the root directory of your repository with the following content: -```console -git clone https://github.com/moodlehq/moodle-local_codechecker.git local/codechecker +```xml + + + + ``` -It is recommended that you add the plugin to your _local_ git ignore: +If you do not wish to include this file in your repository, or you are using an older version of Moodle, then you should add this to your local gitignore files. On a Unix-like system this can be achieved with: ```console -echo local/codechecker >> .git/info/exclude +echo phpcs.xml.dist >> .git/info/exclude ``` :::info @@ -96,23 +107,19 @@ See the [gitignore](https://git-scm.com/docs/gitignore) documentation for more i ::: -:::note - -If you are not installing the moodle ruleset globally, and are instead using the [`local_codechecker`](https://github.com/moodlehq/moodle-local_codechecker) plugin, then you _must_ also use the version of phpcs distributed in the plugin. - -This is located at `local/codechecker/phpcs/bin/phpcs`. +#### System-side default standard -::: +Although not recommended, you can configure the Moodle ruleset as the system-wide default for phpcs: -Once installed a new codechecker option will appear in the Site administration -> Development page. +```php +phpcs --config-set default_standard moodle +``` -This page allows for the code in a specified directory to be checked, for example if you wanted to check the code for the `shortanswer` question type you would enter +:::important Not recommended -``` -/question/type/shortanswer -``` +This approach is **not recommended** and is only preserved for reference. -You would then be presented with a list of the count of files processed and any warnings or errors. +::: ## Editor integrations diff --git a/general/development/tools/phpunit.md b/general/development/tools/phpunit.md index 7a0b89d5e8..8bfcb6c32f 100644 --- a/general/development/tools/phpunit.md +++ b/general/development/tools/phpunit.md @@ -56,9 +56,9 @@ The following table shows what PHPUnit version is installed in which Moodle vers | Moodle version | PHPUnit version | Links | | --- | --- |---------------------------------------------------------| -| Moodle 3.11 - 4.0 | PHPUnit 9.5 | [Documentation](https://phpunit.readthedocs.io/en/9.5/) | -| Moodle 3.10 | PHPUnit 8.5 | [Documentation](https://phpunit.readthedocs.io/en/8.5/) | -| Moodle 3.7 - 3.9 | PHPUnit 7.5 | [Documentation](https://phpunit.readthedocs.io/en/7.5/) | +| Moodle 3.11 - 4.0 | PHPUnit 9.5 | [Documentation](https://docs.phpunit.de/en/9.6/) | +| Moodle 3.10 | PHPUnit 8.5 | [Documentation](https://docs.phpunit.de/en/8.5/) | +| Moodle 3.7 - 3.9 | PHPUnit 7.5 | [Documentation](https://docs.phpunit.de/en/7.5/) | | Moodle 3.4 - 3.6 | PHPUnit 6.5 | [Documentation](https://phpunit.de/manual/6.5/en/) | | Moodle 3.2 - 3.3 | PHPUnit 5.5 | [Documentation](https://phpunit.de/manual/5.5/en/) | | Moodle 3.1 | PHPUnit 4.8.27 | [Documentation 4.8](https://phpunit.de/manual/4.8/en/) | @@ -277,7 +277,7 @@ define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://localhost/moodle-exttests'); ## Writing new tests -- read [official PHPUnit online documentation](http://www.phpunit.de/manual/current/en/) +- read [official PHPUnit online documentation](https://docs.phpunit.de/en/9.6/) - see [Writing PHPUnit tests](https://docs.moodle.org/dev/Writing_PHPUnit_tests) ## PHPUnit support in IDEs diff --git a/general/development/tools/xmldb.md b/general/development/tools/xmldb.md index 22ba8212c7..6abbac492d 100644 --- a/general/development/tools/xmldb.md +++ b/general/development/tools/xmldb.md @@ -76,7 +76,11 @@ Apart from the [Database Structures guidelines](https://docs.moodle.org/dev/Data 1. About names: 1. All lowercase names (tables, indexes, keys and fields). - 1. Table names and field names must use only a-z, 0-9 and _ chars. Max 28 characters. + 1. Table names and field names must use only a-z, 0-9 and _ chars. Max 53 characters for tables and 63 characters for fields (28 and 30 before Moodle 4.3). + + :::caution + If you are writing a plugin intended for older versions of Moodle then you must continue to use the lower limits of 28, and 30. + ::: 1. Key and index names under the XMLDB Files must be formed by concatenating the name of the fields present in the key/index with the '"-" (minus) character. 1. Primary key always must be named "primary" (this is one exception to the previous convention). 1. It's highly recommended to avoid [reserved words](https://docs.moodle.org/dev/XMLDB_reserved_words) completely. We know we have some of them now but they should be completely out for next releases. diff --git a/general/development/tracker/guide.md b/general/development/tracker/guide.md index d9b036e0d3..5db966ecdd 100644 --- a/general/development/tracker/guide.md +++ b/general/development/tracker/guide.md @@ -52,7 +52,7 @@ Once an issue has been created, the following additional fields are able to be c | Field | Values | Notes | |---|---|---| -| **Fixed Version/s** |
  • Prior to integration, this will be set to a backlog (a queue of development work), for example `Must fix for X`.
  • After integration, this will be set to the Moodle version the bug was fixed in, for example `4.0.1`.
|
  • This is usually set by an integrator.
  • Not to be confused with `Affected version`, which is used to define the Moodle version where the issue can be reproduced.
  • If you resolve the bug as anything but `Fixed` (`Cannot Reproduce`, `Won't Fix`, etc.) leave **Fix Version/s** blank.
  • **Fix version/s** are used to automatically build release notes (see the tabs on )
| +| **Fixed Version/s** |
  • Prior to integration, this will be blank or set to a backlog (a queue of development work), for example `Must fix for X`.
  • After integration, this will be set to the Moodle version(s) the issue was fixed in, for example `4.0.1`.
  • For more detailed information, look to the **Resolution** field below.
|
  • This is usually set by an integrator.
  • Not to be confused with `Affected version`, which is used to define the Moodle version where the issue can be reproduced.
  • If you resolve the bug as anything but `Fixed` and, sometimes, `Done` (like `Cannot Reproduce`, `Won't Fix`, etc.) leave **Fix Version/s** blank.
  • **Fix version/s** are used to automatically build release notes (see the tabs on )
| | **Priority** |
  • **Blocker**
    Blocks development or testing, prevents Moodle from running. Applicable to bugs only.
  • **Critical**
    Crashes server, loss of data, severe memory leak
  • **Major**
    Major loss of function, incorrect output
  • **Minor**
    Minor loss of function where workaround is possible
  • **Trivial**
    Cosmetic problem like misspelt words or misaligned text
|
  • When it is reported, the priority level represents the severity of a bug.
  • After being reported, the priority may be promoted by HQ developers and component leads as an issue escalates.
  • Other users wishing to influence the priority of issues should do so by voting for the issue.
  • The priority of new features and improvements should generally remain at the default (Minor) level.
| | **Reporter** | The person who logs the bug.
This field is automatically filled by Tracker. | | | **Assignee** | The person who will fix the issue. The assignee should be set when there is a definite intention to complete the issue. |
  • Developers or QA Testers can reassign issues.
  • Please note that even though a person may be assigned to an issue, this does not mean they are currently working on the issue, although they are likely to in future.
| @@ -76,7 +76,7 @@ Once an issue has been created, the following additional fields are able to be c | Field | Values | Notes | |---|---|---| -| **Resolution** |
  • **Fixed**
    Bug has been fixed; a code change has been integrated into Moodle code.
  • **Won't Fix**
    The problem described is an issue which will never be fixed. Specific reasons should be given.
  • **Not a bug**
    This issue is not a bug. The issue may have been logged in error. Use this code if the bug was fixed by another bug report or in some earlier Moodle version.
  • **Duplicate**
    The problem is a duplicate of an existing issue
  • **Incomplete**
    More information was needed to understand this bug, but it was not provided.
  • **Can't Reproduce**
    Attempts at reproduce the issue failed. If more information appears later, please open a new issue.
  • **Deferred**
    The resolution to this bug will be deferred to a later release or to a fix in a third-party plugin used in Moodle.
| This field is only displayed when resolving or closing a bug. | +| **Resolution** | Issues that may/must have the **Fixed versions** field filled:
  • **Fixed**
    Issue has been fixed; a code change has been integrated into Moodle code. It's **mandatory** to set the *Fixed versions* field for these issues.
  • **Done**
    Normally used for tasks, epics... issues that don't "own" code changes in Moodle, but still have required actions (planning, review, adjust some related system...). When relevant or clearly related with any release it's **recommended** to set the *Fixed versions* to them.
Issues that must not have the **Fixed versions** field filled:
  • **Won't Fix**
    The problem described is an issue which will never be fixed. Specific reasons should be given.
  • **Not a bug**
    This issue is not a bug. The issue may have been logged in error. Use this code if the bug was fixed by another bug report or in some earlier Moodle version.
  • **Duplicate**
    The problem is a duplicate of an existing issue
  • **Incomplete**
    More information was needed to understand this bug, but it was not provided.
  • **Can't Reproduce**
    Attempts at reproduce the issue failed. If more information appears later, please open a new issue.
  • **Deferred**
    The resolution to this bug will be deferred to a later release or to a fix in a third-party plugin used in Moodle.
| This field is only displayed when resolving or closing a bug. | ## See also diff --git a/general/projects/api/admin-tools.md b/general/projects/api/admin-tools.md new file mode 100644 index 0000000000..bf29c890bd --- /dev/null +++ b/general/projects/api/admin-tools.md @@ -0,0 +1,65 @@ +--- +title: Admin tools +tags: + - Plugins + - Admin +--- + +import { ProjectSummary } from '@site/src'; +import { Since } from '@site/src/components'; + + + +
+ + + +Admin tools are advanced plugins that are intended especially for site administrators, they are accessible via the admin site administration tree menu. Ideally most of the functionality in `/admin/` directory should be moved to separate plugins in the future. + +## Previous problems + +Before 2.2, tools for administrators were created as admin reports (because we did not have better pluggable place), placed directly into `/admin/` or `/local/ directory`. + +- Confusing `/admin/report/` or `/local/ plugins` +- No way to disable or remove or add custom admin tools +- The official distribution should not include local plugins by definition (`/local/qeupgradehelper`). + +## Benefits + +- Major cleanup in `/admin/` +- No need to abuse admin reports +- Contrib admin tools can be distributed easier +- It is possible to remove or replace core admin tools (no hardcoded links) + +## Upgrades + +How to migrate existing admin reports: + +1. Move all files to new `/admin/tool/yourplugin/` location +1. Update all links to admin tools `/admin/report/` to `/admin/tool/` +1. Rename/add language pack file with at least `pluginname` string +1. Update all language strings (use `tool_yourplugin` instead of `report_yourplugin`. Use [AMOS](https://docs.moodle.org/dev/Languages/AMOS) hints in commit message +1. Update all capability names +1. Create `db/install.php` migration script. Delete old settings and capabilities (see converted plugins for examples) +1. Grep the plugin codebase and look for any remaining `coursereport` occurrences +1. Update CSS selectors + +## FAQs + +- **Is it necessary to migrate existing admin reports?**
+Yes. Old admin reports directory is completely ignored. + +- **Is it difficult to migrate admin reports?**
+No, it usually takes less than an hour to migrate and test one admin tool. + +- **What is the difference between report and admin tool?**
+Report is a view of live or historical data, it may also contain export feature, reports usually do not modify data. Admin tools are intended mostly for administrators, they usually work only in system context. + +- **What is the difference between admin tool and local plugin?**
+Local plugin is everything else, it may be intended for non-admin users. Examples of local plugins: event handlers, web service/function definitions, shared library hacks, new lang strings used in core hacks, etc. + +## See also + +- [General report plugins](https://docs.moodle.org/dev/General_report_plugins) diff --git a/general/releases/2.2.md b/general/releases/2.2.md index 2d2c3b0233..19d6053830 100644 --- a/general/releases/2.2.md +++ b/general/releases/2.2.md @@ -52,7 +52,7 @@ All security issues that were fixed in 2.1.x and 2.0.x were also fixed in 2.2. #### New plugin types - [report - report](https://docs.moodle.org/dev/General_report_plugins) -- [admin/tool - tool](https://docs.moodle.org/dev/Admin_tools) +- [admin/tool - tool](../projects/api/admin-tools.md) - [mod/quiz/accessrule - quizaccess](https://docs.moodle.org/dev/Quiz_access_rules) #### Plugin API changes diff --git a/general/releases/3.1.md b/general/releases/3.1.md index 1edcabe9fb..fae570b1ac 100644 --- a/general/releases/3.1.md +++ b/general/releases/3.1.md @@ -200,7 +200,7 @@ There are no security issues included in this release, please refer to [Moodle 3 ### Smaller new things -- [MDL-51802](https://tracker.moodle.org/browse/MDL-51802) - Reusable element for inplace editing ([documentation](https://docs.moodle.org/dev/Inplace_editable)) +- [MDL-51802](https://tracker.moodle.org/browse/MDL-51802) - Reusable element for inplace editing ([documentation](/docs/apis/subsystems/output/inplace)) - [MDL-30811](https://tracker.moodle.org/browse/MDL-30811) - Introduce notification stack to moodle sessions ([documentation](https://docs.moodle.org/dev/Notifications)) - [MDL-52237](https://tracker.moodle.org/browse/MDL-52237) - Add a callback to inject nodes in the user profile navigation ([documentation](/docs/apis/core/navigation/#user-profile)) - [MDL-51324](https://tracker.moodle.org/browse/MDL-51324) - New course chooser element for moodleforms ([documentation](https://docs.moodle.org/dev/lib/formslib.php_Form_Definition#autocomplete)) diff --git a/general/releases/3.5.md b/general/releases/3.5.md index 8a90b1f315..e02616ae58 100644 --- a/general/releases/3.5.md +++ b/general/releases/3.5.md @@ -119,7 +119,7 @@ Note: Legacy browsers with known compatibility issues with Moodle 3.5: - [MDL-36941](https://tracker.moodle.org/browse/MDL-36941) - Create new tables for messaging - [MDL-61255](https://tracker.moodle.org/browse/MDL-61255) - Ad-hoc task to upgrade messages to merged table -See also [Message API#Changes in Moodle 3.5](https://docs.moodle.org/dev/Message_API#Changes_in_Moodle_3.5) +See also [Message API#Changes in Moodle 3.5](/docs/apis/core/message/#changes-in-moodle-3.5) ## Other Highlights @@ -176,7 +176,7 @@ Read lib/upgrade.txt to check for the deprecations and core API changes, make su - [lib/upgrade.txt](https://github.com/moodle/moodle/blob/v3.5.0/lib/upgrade.txt) changes to various core APIs, deprecations, functions removal - [calendar/upgrade.txt](https://github.com/moodle/moodle/blob/v3.5.0/calendar/upgrade.txt) changes to Calendar API - [search/upgrade.txt](https://github.com/moodle/moodle/blob/v3.5.0/search/upgrade.txt) changes to Global search API -- [message/upgrade.txt](https://github.com/moodle/moodle/blob/v3.5.0/message/upgrade.txt) changes to Messages API - See also [Message API#Changes in Moodle 3.5](https://docs.moodle.org/dev/Message_API#Changes_in_Moodle_3.5) +- [message/upgrade.txt](https://github.com/moodle/moodle/blob/v3.5.0/message/upgrade.txt) changes to Messages API - See also [Message API#Changes in Moodle 3.5](/docs/apis/core/message/#changes-in-moodle-3.5) - [course/upgrade.txt](https://github.com/moodle/moodle/blob/v3.5.0/course/upgrade.txt) changes to Course API **2. Check for changes in the API of your plugin type** diff --git a/general/releases/4.2.md b/general/releases/4.2.md index 96de72e0a8..acd8baf7a6 100644 --- a/general/releases/4.2.md +++ b/general/releases/4.2.md @@ -19,7 +19,7 @@ If you are upgrading from a previous version, please see [Upgrading](https://doc These are just the minimum supported versions. We recommend keeping all of your software and operating systems up-to-date. - Moodle upgrade: Moodle 3.11.8 or later. -- PHP version: minimum PHP 8.0.0 *Note: minimum PHP version has increased since Moodle 4.1*. PHP 8.1.x is supported too. See [PHP](../development/policies/php.md) for details. +- PHP version: minimum PHP 8.0.0 *Note: minimum PHP version has increased since Moodle 4.1*. PHP 8.2.x is supported too (since Moodle 4.2.3). See [PHP](../development/policies/php.md) for details. - PHP extension **sodium** is required. See [Environment - PHP extension sodium](https://docs.moodle.org/en/Environment_-_PHP_extension_sodium). - PHP extension **exif** is recommended. - PHP setting **max_input_vars** must be >= 5000. For further details, see [Environment - max input vars](https://docs.moodle.org/en/Environment_-_max_input_vars). diff --git a/general/releases/4.3.md b/general/releases/4.3.md index 042114dc1b..a2344735eb 100644 --- a/general/releases/4.3.md +++ b/general/releases/4.3.md @@ -19,7 +19,7 @@ If you are upgrading from a previous version, please see [Upgrading](https://doc These are just the minimum supported versions. We recommend keeping all of your software and operating systems up-to-date. - Moodle upgrade: Moodle 3.11.8 or later. -- PHP version: minimum PHP 8.0.0 *Note: minimum PHP version has increased since Moodle 4.1*. PHP 8.1.x is supported too. See [PHP](../development/policies/php.md) for details. +- PHP version: minimum PHP 8.0.0 *Note: minimum PHP version has increased since Moodle 4.1*. PHP 8.2.x is supported too. See [PHP](../development/policies/php.md) for details. - PHP extension **sodium** is required. See [Environment - PHP extension sodium](https://docs.moodle.org/en/Environment_-_PHP_extension_sodium). - PHP setting **max_input_vars** must be >= 5000. For further details, see [Environment - max input vars](https://docs.moodle.org/en/Environment_-_max_input_vars). - PHP variants: Only 64-bit versions of PHP are supported. *Note: Changed since 4.1*. @@ -36,6 +36,8 @@ Moodle supports the following database servers. Again, version numbers are just | [Microsoft SQL Server](http://www.microsoft.com/en-us/server-cloud/products/sql-server/) | 2017 | Latest | | [Oracle Database](http://www.oracle.com/us/products/database/overview/index.html) | 19 | Latest | +Note that, since Moodle 4.3, the maximum length for the database prefix (`$CFG->prefix`) is 10 characters. Installation or upgrade won't be possible with longer prefixes. + ## Client requirements ### Browser support diff --git a/sidebars/docs.js b/sidebars/docs.js index 3105a0101d..d795d16256 100644 --- a/sidebars/docs.js +++ b/sidebars/docs.js @@ -50,6 +50,12 @@ const sidebars = { }, }, + { + label: 'Content guidelines', + type: 'link', + href: '/general/contentguidelines', + }, + { label: 'Developer update', type: 'doc', diff --git a/sidebars/general.js b/sidebars/general.js index a420d6f322..7be549bd21 100644 --- a/sidebars/general.js +++ b/sidebars/general.js @@ -152,19 +152,19 @@ const sidebars = { }, }, ], - contentstyleguide: [ + contentguidelines: [ { - label: 'Content style guide', + label: 'Content guidelines', type: 'category', items: [ { type: 'autogenerated', - dirName: 'contentstyleguide', + dirName: 'contentguidelines', }, ], link: { type: 'doc', - id: 'contentstyleguide', + id: 'contentguidelines', }, }, ], diff --git a/versioned_docs/version-4.1/apis.md b/versioned_docs/version-4.1/apis.md index bbcd7fca7b..9045fe5289 100644 --- a/versioned_docs/version-4.1/apis.md +++ b/versioned_docs/version-4.1/apis.md @@ -173,7 +173,7 @@ The [Rating API](https://docs.moodle.org/dev/Rating_API) lets you create AJAX ra ### Report builder API (reportbuilder) -The [Report builder API](https://docs.moodle.org/dev/Report_builder_API) allows you to create reports in your plugin, as well as providing custom reporting data which users can use to build their own reports. +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) @@ -213,7 +213,7 @@ The [https://docs.moodle.org/dev/OpenBadges_User_Documentation Badges] user docu ### Custom fields API (customfield) -The [Custom fields API](https://docs.moodle.org/dev/Custom_fields_API) allows you to configure and add custom fields for different entities +The [Custom fields API](../../docs/apis/core/customfields/index.md) allows you to configure and add custom fields for different entities ## Activity module APIs diff --git a/versioned_docs/version-4.1/apis/plugintypes/antivirus/index.mdx b/versioned_docs/version-4.1/apis/plugintypes/antivirus/index.mdx index dc9d920541..c28e2d0276 100644 --- a/versioned_docs/version-4.1/apis/plugintypes/antivirus/index.mdx +++ b/versioned_docs/version-4.1/apis/plugintypes/antivirus/index.mdx @@ -109,6 +109,6 @@ Writing unit tests is strongly encouraged as it can help to identify bugs, or ch 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://phpunit.de/manual/current/en/test-doubles.html). +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.1/apis/plugintypes/repository/_examples/lib.php b/versioned_docs/version-4.1/apis/plugintypes/repository/_examples/lib.php index 30346d3054..366cb2711d 100644 --- a/versioned_docs/version-4.1/apis/plugintypes/repository/_examples/lib.php +++ b/versioned_docs/version-4.1/apis/plugintypes/repository/_examples/lib.php @@ -12,7 +12,7 @@ class repository_pluginname extends repository { * * @param string $encodedpath * @param string $page - * @return array the list of files, including meta infomation + * @return array the list of files, including meta information */ public function get_listing($encodedpath = '', $page = '') { // This methods diff --git a/versioned_docs/version-4.1/apis/plugintypes/repository/index.md b/versioned_docs/version-4.1/apis/plugintypes/repository/index.md index a71418fb7e..c902c44865 100644 --- a/versioned_docs/version-4.1/apis/plugintypes/repository/index.md +++ b/versioned_docs/version-4.1/apis/plugintypes/repository/index.md @@ -192,7 +192,7 @@ function supported_filetypes() { A system-wide instance of a repository is created when it is enabled. It is also possible to support both course, and user specific repositories.. This can be achieved by setting the `enablecourseinstances` and `enableuserinstances` options. There are three ways that this can be done: 1. Define **$string\['enablecourseinstances'\]** and **$string\['enableuserinstances'\]** in your plugin's language file. You can check an example in the [filesystem repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/filesystem/lang/en/repository_filesystem.php). -2. The plugin must provide a **get_instance_option_names** method which returns at least one instance option name. This method defined the specific instances options, if none instance atrtribute is needed, the system will not allow the plguin to define course and user instances. Note, you must not define the form fields for these options in the **type_config_form()** function. For example, [filesystem repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/filesystem/lib.php#L439). +2. The plugin must provide a **get_instance_option_names** method which returns at least one instance option name. This method defined the specific instances options, if none instance attribute is needed, the system will not allow the plugin to define course and user instances. Note, you must not define the form fields for these options in the **type_config_form()** function. For example, [filesystem repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/filesystem/lib.php#L439). 3. Several 'core' repositories use the **db/install.php** to create the original repository instance by constructing an instance of the **repository_type** class. The options can be defined in the array passed as the second parameter to the constructor. For example [Wikipedia repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/wikimedia/db/install.php). ### Developer-defined API @@ -457,7 +457,7 @@ This function will return a list of files to be displayed to the user, the list * * @param string $encodedpath * @param string $page - * @return array the list of files, including meta infomation + * @return array the list of files, including meta information */ public function get_listing($encodedpath = '', $page = '') { // This methods diff --git a/versioned_docs/version-4.2/apis.md b/versioned_docs/version-4.2/apis.md index bbcd7fca7b..9045fe5289 100644 --- a/versioned_docs/version-4.2/apis.md +++ b/versioned_docs/version-4.2/apis.md @@ -173,7 +173,7 @@ The [Rating API](https://docs.moodle.org/dev/Rating_API) lets you create AJAX ra ### Report builder API (reportbuilder) -The [Report builder API](https://docs.moodle.org/dev/Report_builder_API) allows you to create reports in your plugin, as well as providing custom reporting data which users can use to build their own reports. +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) @@ -213,7 +213,7 @@ The [https://docs.moodle.org/dev/OpenBadges_User_Documentation Badges] user docu ### Custom fields API (customfield) -The [Custom fields API](https://docs.moodle.org/dev/Custom_fields_API) allows you to configure and add custom fields for different entities +The [Custom fields API](../../docs/apis/core/customfields/index.md) allows you to configure and add custom fields for different entities ## Activity module APIs diff --git a/versioned_docs/version-4.2/apis/plugintypes/antivirus/index.mdx b/versioned_docs/version-4.2/apis/plugintypes/antivirus/index.mdx index dc9d920541..c28e2d0276 100644 --- a/versioned_docs/version-4.2/apis/plugintypes/antivirus/index.mdx +++ b/versioned_docs/version-4.2/apis/plugintypes/antivirus/index.mdx @@ -109,6 +109,6 @@ Writing unit tests is strongly encouraged as it can help to identify bugs, or ch 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://phpunit.de/manual/current/en/test-doubles.html). +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/repository/_examples/lib.php b/versioned_docs/version-4.2/apis/plugintypes/repository/_examples/lib.php index 30346d3054..366cb2711d 100644 --- a/versioned_docs/version-4.2/apis/plugintypes/repository/_examples/lib.php +++ b/versioned_docs/version-4.2/apis/plugintypes/repository/_examples/lib.php @@ -12,7 +12,7 @@ class repository_pluginname extends repository { * * @param string $encodedpath * @param string $page - * @return array the list of files, including meta infomation + * @return array the list of files, including meta information */ public function get_listing($encodedpath = '', $page = '') { // This methods diff --git a/versioned_docs/version-4.2/apis/plugintypes/repository/index.md b/versioned_docs/version-4.2/apis/plugintypes/repository/index.md index a71418fb7e..c902c44865 100644 --- a/versioned_docs/version-4.2/apis/plugintypes/repository/index.md +++ b/versioned_docs/version-4.2/apis/plugintypes/repository/index.md @@ -192,7 +192,7 @@ function supported_filetypes() { A system-wide instance of a repository is created when it is enabled. It is also possible to support both course, and user specific repositories.. This can be achieved by setting the `enablecourseinstances` and `enableuserinstances` options. There are three ways that this can be done: 1. Define **$string\['enablecourseinstances'\]** and **$string\['enableuserinstances'\]** in your plugin's language file. You can check an example in the [filesystem repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/filesystem/lang/en/repository_filesystem.php). -2. The plugin must provide a **get_instance_option_names** method which returns at least one instance option name. This method defined the specific instances options, if none instance atrtribute is needed, the system will not allow the plguin to define course and user instances. Note, you must not define the form fields for these options in the **type_config_form()** function. For example, [filesystem repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/filesystem/lib.php#L439). +2. The plugin must provide a **get_instance_option_names** method which returns at least one instance option name. This method defined the specific instances options, if none instance attribute is needed, the system will not allow the plugin to define course and user instances. Note, you must not define the form fields for these options in the **type_config_form()** function. For example, [filesystem repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/filesystem/lib.php#L439). 3. Several 'core' repositories use the **db/install.php** to create the original repository instance by constructing an instance of the **repository_type** class. The options can be defined in the array passed as the second parameter to the constructor. For example [Wikipedia repository](https://github.com/moodle/moodle/blob/v4.0.0/repository/wikimedia/db/install.php). ### Developer-defined API @@ -457,7 +457,7 @@ This function will return a list of files to be displayed to the user, the list * * @param string $encodedpath * @param string $page - * @return array the list of files, including meta infomation + * @return array the list of files, including meta information */ public function get_listing($encodedpath = '', $page = '') { // This methods