<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Peterd17</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Peterd17"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Peterd17"/>
	<updated>2026-10-03T02:00:02Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61920</id>
		<title>Moodle 4.0 developer update</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61920"/>
		<updated>2022-04-01T01:04:56Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Theme updates: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page highlights the important changes that are coming in Moodle 4.0 for developers. Including how the UX improvements impact custom themes, relevant API changes, and what you can do as developer to prepare for the 4.0 release.&lt;br /&gt;
== Navigation changes ==&lt;br /&gt;
The core Navigation API has been left mostly untouched. The callbacks to all navigation callbacks remains unchanged and will be called as part of the regular &#039;navigation&#039; and &#039;settingsnav&#039; initialisation. Some new core classes have been created and exist within a new namespace &#039;core/navigation&#039; and serves as conduit to rearrange, cherry-pick existing navigation nodes from the navigation/settingsnav trees and display within the respective navigation type. As such, it is highly recommended to provide unique keys for custom navigation nodes as this helps in the cherry-picking / rearranging process within the new classes.&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
The primary navigation(the navbar) apart from the existing content will now display links to the Dashboard, My Courses, Site Admin and Course search, by default. You can still add items to the navbar via the &#039;custom menu&#039; option. This will be displayed within the &#039;More&#039; menu. We have transitioned the menus to be rendered via templates - refer user_menu.mustache. The lang menu has been moved to reside within the user menu.&lt;br /&gt;
==== Customising the primary navigation ====&lt;br /&gt;
Not yet implemented but we are looking at allowing the full addition and removal of any of the primary navigation tabs in the boost theme config file.&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
The main content area shows tabs for secondary navigation with a maximum of 5 items being rendered in this ‘more’ menu. A new UI component has been created to render menus like this. Files:&lt;br /&gt;
 /lib/templates/moremenu.mustache&lt;br /&gt;
==== Adding items to the navigation ====&lt;br /&gt;
The secondary navigation pulls information mainly from the settings navigation node from each context. Any plugin that implements the existing navigation hooks will have their items added to the secondary navigation.&lt;br /&gt;
Existing navigation hooks:&lt;br /&gt;
* {module}_extend_navigation&lt;br /&gt;
* {local}_extend_navigation&lt;br /&gt;
* {report}_report_extend_navigation&lt;br /&gt;
* {plugin}_extend_navigation_course&lt;br /&gt;
* {plugin}_extend_navigation_category_settings&lt;br /&gt;
==== Changing the order of tabs ====&lt;br /&gt;
Apart from the previously mentioned functions, you can also create a custom secondary class as mentioned earlier. This will automatically be picked by getter and used to render the secondary nav within the activity. E.g. mod_assign/local/views/secondary. Note: This is currently only possible on an activity and block level.&lt;br /&gt;
=== Tertiary navigation ===&lt;br /&gt;
We&#039;ve moved action buttons to the top of the page. We would encourage you to do the same.&lt;br /&gt;
If you have any buttons on an activity page that go to another page, or open a form (or similar), then we encourage you to move them from the body of your activity page to the top. All of the core activities have been updated to follow this pattern. Please take a look to see how you can format your activity in a similar fashion. There is no API here. You are welcome to create the buttons and display them as you wish in this top area.&lt;br /&gt;
=== New API functions ===&lt;br /&gt;
==== Page API ====&lt;br /&gt;
* Magic getters to fetch the primary and secondary navs and the primary output.&lt;br /&gt;
* The secondarynav magic getter also checks whether a custom secondary class has been defined within the module&#039;s local\views directory. Use this if you want to deviate from the standard secondary nav structure/order.&lt;br /&gt;
&lt;br /&gt;
* set_secondarynav - Force override the secondary navigation class&lt;br /&gt;
&lt;br /&gt;
* set_secondary_navigation - Sets the ‘_hassecondarynavigation’ and optionally the ‘_hastablistsecondarynavigation’ to indicate whether a page should render the secondary navigation, and if the secondary navigation should be rendered and behave with a tablist ARIA role (as opposed to its default which is being rendered with a menubar ARIA role).&lt;br /&gt;
==== Navigationlib ====&lt;br /&gt;
* set_show_in_secondary_navigation - whether or not a node should be displayed in the secondary nav. Accepts a single boolean argument&lt;br /&gt;
* set_force_into_more_menu- whether or not to force a node into the &#039;More&#039; menu. Accepts a single boolean argument&lt;br /&gt;
==== The activity header class ====&lt;br /&gt;
There is a new activity header class that handles the display of information common to activities. 3rd party activities are not required to explicitly output this information as part of rendering individual pages.&lt;br /&gt;
&lt;br /&gt;
The common information that are currently handled by the class are:&lt;br /&gt;
* title&lt;br /&gt;
* description&lt;br /&gt;
* completion information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As part of the update it was required that the initial information to be displayed by the class be toggable at a theme and layout level. Taking this into account the following theme level configurable exists:&lt;br /&gt;
* activityheaderconfig =&amp;gt; An array that currently only enforces &#039;notitle&#039; but can be expanded in the future NOTE: Boost has this set as true by default &#039;options&#039;&lt;br /&gt;
The following layout level options that can be defined:&lt;br /&gt;
* noactivityheader - to remove the header in this specific layout.&lt;br /&gt;
* activityheader - An array that enforces the following options:&lt;br /&gt;
** notitle&lt;br /&gt;
** nocompletion&lt;br /&gt;
** nodescription&lt;br /&gt;
The class has a page level getter which you can use to fetch the current version of the class. The base state is initialised within the constructor with the completion information only fetched when data is exported for the template.&lt;br /&gt;
&lt;br /&gt;
The class has setters for the following variables which can be leveraged to modify the header for a particular page in the format set_{variable_name}:&lt;br /&gt;
* hidecompletion&lt;br /&gt;
* description&lt;br /&gt;
* title&lt;br /&gt;
Alternately, bulk operations can also be done by passing the above variables in an array to &#039;set_attrs&#039; which in turn calls the setters.&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note: Any updates to the activityheader needs to be performed before the call to $OUTPUT-&amp;gt;header&#039;&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
===== Theme updates =====&lt;br /&gt;
With the changes in boost to incorporate the primary and secondary navigation, 3rd party themes would need to account for the following in their templates:&lt;br /&gt;
* To leverage the activity_header, it&#039;s data needs to be exported and included into the base template :&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
   {{&amp;gt; core/activity_header}}&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;** headercontent being the array element that contains the exported activity_header data&lt;br /&gt;
* It is recommended to transition towards the secondary/tertiary navigation hierarchy to reduce user cognitive load and with a logical separation of components&lt;br /&gt;
** Secondary navigation can be added to the templates by following the example https://github.com/moodle/moodle/blob/master/theme/boost/templates/columns2.mustache#L64-L68 This leverages the secondary navigation class to generate it&#039;s content.&lt;br /&gt;
* Flat navigation classes have been marked for deprecation. Themes that leverage the flat_navigation will need to make the following changes in their plugins in order to use it&lt;br /&gt;
** Account for the additional changes [[Moodle 4.0 developer update#Theme changes]]&lt;br /&gt;
** Indicate that they do not implement secondary navigation via the page&#039;s &amp;quot;set_secondary_navigation&amp;quot; function. It is recommended to set this within the root layout file e.g. columns2&lt;br /&gt;
** Initialise the flat navigation by introducing the following in the root layout file(if not existent)&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$nav = $PAGE-&amp;gt;flatnav;&lt;br /&gt;
$templatecontext[&#039;firstcollectionlabel&#039;] = $nav-&amp;gt;get_collectionlabel();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* In order to reintroduce the settings cog in the templates, you can introduce the following: &amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;region-main-settings-menu&amp;quot; class=&amp;quot;d-print-none {{#hasblocks}}has-blocks{{/hasblocks}}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div&amp;gt; {{{ output.region_main_settings_menu }}} &amp;lt;/div&amp;gt;            &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===== Accessibility notes =====&lt;br /&gt;
The jump to ‘maincontent’ div is now rendered within the activity header when within an activity context&lt;br /&gt;
== Component library ==&lt;br /&gt;
Each Moodle installation now ships with a Moodle User Interface (UI) Component library, a documentation system used to describe all the Bootstrap components and the custom Moodle components. The component Library is a helper tool for developers when creating user interfaces, a testing tool for theme developers and a documentation tool for core developers. The ultimate goal of having a component library is to encourage developers to create consistent user interfaces to improve Moodle’s overall user experience.&lt;br /&gt;
&lt;br /&gt;
The library contains pages with documentation about User Interface components. It contains details on how to use the component, what variations are available and the JavaScript events / options are associated with the component.&lt;br /&gt;
&lt;br /&gt;
When writing on these pages it is possible to render core mustache templates using some custom syntax like this:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; mustache template=&amp;quot;core/notification_error&amp;quot; &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; /mustache &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also call core JavaScript or use HTML examples where the html code and the rendered result are visible in the Component Library. For more info visit the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-templates/ Moodle templates] page or the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-javascript/ Moodle JavaScript] page.&lt;br /&gt;
&lt;br /&gt;
Each page in the library uses the current css from the default theme in your Moodle installation, if you have multiple themes installed and enabled the setting &amp;quot;Allow theme changes on url&amp;quot;, the component library will have a theme selector option.&lt;br /&gt;
&lt;br /&gt;
A hosted version of the Component Library can be found here. http://componentlibrary.moodle.com&lt;br /&gt;
=== Enabling the Component Library ===&lt;br /&gt;
Component library pages are written in the markdown language. These pages need to be compiled to HTML pages before the Component Library is visible. To compile the pages the server running Moodle needs to have the [[Javascript Modules#Install%20NVM%20and%20Node|JavaScript developer tools installed]] (nodeJs and Grunt)&lt;br /&gt;
&lt;br /&gt;
If your server meets all requirements you can enable the library running&lt;br /&gt;
 $ npm install&lt;br /&gt;
 $ grunt componentlibrary&lt;br /&gt;
Further installation instructions can be found in the Component Library itself.&lt;br /&gt;
=== Documenting new UI Components ===&lt;br /&gt;
There are no set rules for adding new pages in the component library yet. These rules will need to be written and adopted in the integration process for Moodle code.&lt;br /&gt;
&lt;br /&gt;
As a guideline for making this rules consideration are:&lt;br /&gt;
&lt;br /&gt;
The component library is not about single use components, for example the Moodle grade book (a huge component with many custom features). Or about very common components like buttons, these are already covered by the Bootstrap section of the component library.&lt;br /&gt;
&lt;br /&gt;
New features should be build keeping in mind the UI part needs to be customisable and if possible (and making sense) reusable. And example would be the new page drawers that we are introducing for the Navigation project. Or the custom primary navigation menus where overflowing items are pushed into a More section.&lt;br /&gt;
== Theme changes ==&lt;br /&gt;
=== Edit switch ===&lt;br /&gt;
On theme boost the “Turn editing on” and “Customise this page” buttons have been replaced by an edit switch in the top navbar. Theme Classic will keep using the old buttons. Child themes can choose to use the edit switch if the theme config.php is using this variable&lt;br /&gt;
 $THEME-&amp;gt;haseditswitch = true;&lt;br /&gt;
The languague menu, which used to be rendered in place of the custom menu has moved to the user dropdown when the user is logged in. If not logged in it will be placed next to the search / notification / messaging icon in the top navbar.&lt;br /&gt;
=== Login page ===&lt;br /&gt;
The login page has been redesigned and allows the admin to configure a background image for the login page only in the theme settings page. This change is available in both Boost and Classic. The login page still has all the features with an improved layout. &lt;br /&gt;
=== The page footer ===&lt;br /&gt;
In large screens, the page footer button is only visible when clicking a help button at the bottom right of the screen.&lt;br /&gt;
=== User initials as profile picture placeholder ===&lt;br /&gt;
If users do not upload a profile picture the user initials are displayed on a rounded gray background as a placeholder picture in the top navbar or any other page using a placeholder image. This change will be available in both Boost and Classic. &lt;br /&gt;
&lt;br /&gt;
With the introduction of this placeholder image the full username will no longer be displayed in the top navbar.&lt;br /&gt;
=== Removal of back to top link ===&lt;br /&gt;
The &amp;quot;back to top&amp;quot; link will be removed for theme boost since the new course index reduced the dependence on page scrolling. Also, the new footer is positioned where this component used to be.&lt;br /&gt;
=== Styling changes ===&lt;br /&gt;
By default rounded edges will be used for UI components, for the page header and main content area the borders will be removed. &lt;br /&gt;
=== New layout page ===&lt;br /&gt;
Theme boost now uses the drawers.php layout for the course index and blocks.&lt;br /&gt;
== Question bank changes ==&lt;br /&gt;
There was a big project to deliver [[Question bank improvements for Moodle 4.0]] which added a new plugin type for adding features to the question banks, tracking the version history for each question as it is edited (question table has been split into &amp;lt;code&amp;gt;question&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;question_versions&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_bank_entries&amp;lt;/code&amp;gt;), and tracking where each question is going to be used, with new tables &amp;lt;code&amp;gt;question_references&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_set_references&amp;lt;/code&amp;gt;. This work was done in Epic MDL-70329 if you want to track down the details of any of the core changes.&lt;br /&gt;
=== Question type plugins ===&lt;br /&gt;
Amazingly, we (Safat and colleagues at Catalyst AU) managed to implement this without breaking most question type plugins.&lt;br /&gt;
&lt;br /&gt;
However, the changes to the question bank, and the other Moodle 4.0 changes, probably broke the Behat tests for your plugin. To help with fixing that, MDL-74130 adds navigation to key question type pages (Preview and Edit for a question, and standard question bank pages like the bank itself, import and export) which should let you fix your test efficiently, and in a way that will work in all Moodle versions since 3.9.&lt;br /&gt;
&lt;br /&gt;
The &#039;most&#039; in the first paragraph here is becuase more advance question types may require more effort to fix. (For example qtype_combined which creates multi-part qusetions like the core qtype_multianswer; or qtype_pmatch or qtype_stack, which store additional data - questions tests - alongside the question itseld. How should that work with versionning?) But, if you have not done weird things like that, you are probably safe. If you find anything else that causes problems, please list it here.&lt;br /&gt;
&lt;br /&gt;
The same thing should apply to question behaviour and question import/export format plugings: no significant changes required (probably just fixing the Behat tests because of the navigation changes).&lt;br /&gt;
=== New plugin type: qbank plugins ===&lt;br /&gt;
This is not something that will cause problems for people upgrading from 3.x. Rather, it is an exciting possibility you can explore once you have survived process of upgrading to 4.0. There is a whole new plugin type which you can create to add new features to the question bank. For example extra columns, new actions and bulk actions, and so on. See [[Question_bank_plugins]].&lt;br /&gt;
=== Activities that use questions ===&lt;br /&gt;
The probable bad news is if you have an activity module which uses questions. So far, the only activity which has been fixed is mod_quiz in Moodle core, so we don&#039;t yet have a good picture of what fixes will be necessary in other activities. Work is about to start fixing [https://github.com/studentquiz/moodle-mod_studentquiz mod_studentquiz], so watching that should give more clues. As we do that, we will try to update this section of this page. Other help writing the information required here would also be greatly appreciated.&lt;br /&gt;
== The course format system ==&lt;br /&gt;
Most of the logic for rendering and editing a course has been moved to a new subsystem called courseformat. The subsystem is located in &amp;quot;course/format&amp;quot; folder so it includes all the format plugins inside. The methods and modules which are distributed between the course and the course/format folders are now rearranged or refactored to be aligned with the current Moodle coding style.&lt;br /&gt;
=== Mandatory renderer in course formats ===&lt;br /&gt;
Now format plugins renderer is not optional anymore. Legacy formats without a renderer will get a deprecation message but it will continue working however, they should create a new renderer as soon as possible. The section-based format can do it by extending the provided core_courseformat\output\section_renderer class which includes all the necessary methods.&lt;br /&gt;
=== New format base class ===&lt;br /&gt;
The old base_format class (which all plugins extend) is now renamed as core_courseformat\base. The new class provides all the functionally of the previous base_format but it has been refactored to be used as a centralized source of truth for the course rendering. Legacy formats should extend the new class to avoid the deprecation message.&lt;br /&gt;
&lt;br /&gt;
Now, the plugin format class provides information such as:&lt;br /&gt;
* If the page is displaying a single or multiple section&lt;br /&gt;
* Give access to other related format objects like the modinfo, the course record, maximum number of sections...&lt;br /&gt;
* If the format is compatible with features like course index, reactive components, ajax...&lt;br /&gt;
* Other format specifics like the page title, the default section name, default blocks...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The format instance is now the main object output components will use to render a course (see next section for more information).&lt;br /&gt;
=== New course output classes and mustache files ===&lt;br /&gt;
Traditionally, section-based course formats uses print_single_section_page and print_multiple_section_page to render the course content. In Moodle 4.0 most of the course rendering methods are migrated to output components and mustache templates. The old methods will get deprecation messages if they use the old renderer methods.&lt;br /&gt;
&lt;br /&gt;
This is an example of a format rendering a course:&amp;lt;syntaxhighlight lang=&amp;quot;php-brief&amp;quot;&amp;gt;&lt;br /&gt;
// Get the course format instance.&lt;br /&gt;
$format = course_get_format($course);&lt;br /&gt;
&lt;br /&gt;
// Get the specific format renderer.&lt;br /&gt;
$renderer = $format-&amp;gt;get_renderer($PAGE);&lt;br /&gt;
&lt;br /&gt;
if (!empty($displaysection)) {&lt;br /&gt;
    // Setup the format instance to display a single section.&lt;br /&gt;
    $format-&amp;gt;set_section_number($displaysection);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Create the ouptut instance and render it.&lt;br /&gt;
$outputclass = $format-&amp;gt;get_output_classname(&#039;content&#039;);&lt;br /&gt;
$widget = new $outputclass($format);&lt;br /&gt;
&lt;br /&gt;
echo $renderer-&amp;gt;render($widget);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Format plugins are free to use its own output classes to render a course, or they could override the existing output classes by providing their own implementation. For example, the default output for &amp;quot;content&amp;quot; (as in the previous example) is &amp;quot;core_courseformat\output\local\|content&amp;quot;, however, if the plugin has a &amp;quot;format_XXX\output\courseformat\content&amp;quot; class, the $format-&amp;gt;class the get_output_class will return the overridden one.&lt;br /&gt;
Another important update on course rendering is that now all course structure is rendered using mustache templates instead of the original html_writer methods. Now themes are able to override the course format by providing alternative versions of the mustache files. All core course templates are located in &amp;quot;course/format/templates&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All course format output classes implements the new named_templatable interface, which allows the class to define its own template path using the &amp;quot;get_template_name&amp;quot; method. This new interface in combination with [[Templates#Blocks|mustache blocks]] allows the format plugins to provide alternative templates to render the course.&lt;br /&gt;
&lt;br /&gt;
All the new output classes and a guide on how to migrate the current third-party plugins will be available soon.&lt;br /&gt;
=== Course editor javascript modules and frontend components ===&lt;br /&gt;
The majority of the javascript logic related to the course editing is replaced by AMD modules. Because this is a major change in the way courses are edited and rendered, by default format plugins will continue using the previous YUI modules for now. However, formats can start using the new libraries overriding the &amp;quot;$format-&amp;gt;supports_components()&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Some Moodle 4.0 new features are only available for courses using the new editor library:&lt;br /&gt;
* Edit the course via the course index&lt;br /&gt;
* Creating sections without reloading the course page&lt;br /&gt;
* The new move section/activity modal&lt;br /&gt;
* Native browser drag&amp;amp;drop implementation&lt;br /&gt;
The new course editor uses a component-based reactive pattern to keep track of the course changes. The pattern highlights are:&lt;br /&gt;
* The main AMD module &amp;quot;core_crouseformat\courseeditor&amp;quot; maintains a data structure called state.&lt;br /&gt;
* Each UI element is implemented as a Component that observes the course state data and reacts to any data change&lt;br /&gt;
* When any reactive component needs to modify the course, it asks the course editor to execute a mutation. Mutations encapsulate all web services calls and alter the course state data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The reactive library documentation, as well as the format plugin migration guide, will be available soon.&lt;br /&gt;
=== Other course related 4.0 changes ===&lt;br /&gt;
Two new web services have been added:&lt;br /&gt;
* core_courseformat_get_state: user by the new javascript course editor to get the current course state data (containing the list of sections, activities, and other course-related data)&lt;br /&gt;
* core_courseformat_update_course: to alter the current course content. Each call returns the parts of the course state altered by the action&lt;br /&gt;
== Behat changes ==&lt;br /&gt;
=== New steps ===&lt;br /&gt;
Moodle 4.0 introduces some new behat steps.&lt;br /&gt;
&lt;br /&gt;
Sometimes you want to create a bulk number of activities. In that case you can use:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
:count :entitytype exist with the following data:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Given 100 &amp;quot;mod_lti &amp;gt; tool types&amp;quot; exist with the following data:&lt;br /&gt;
  |name        |Test tool [count]                  |&lt;br /&gt;
  |description |Example description [count]        |&lt;br /&gt;
  |baseurl     |https://www.example.com/tool[count]|&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dynamic (AJAX) tabs is a new feature contributed to Moodle 4.0 by the Workplace team (MDL-71943). You can use the following step to navigate between the tabs.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on the &amp;quot;tab title&amp;quot; dynamic tab&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To make sure that edit mode is (or is not) available on the current page, the following steps can be used.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And edit mode should be available on the current page&lt;br /&gt;
And edit mode should not be available on the current page&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are new aliases for the existing steps &amp;lt;code&amp;gt;I turn editing mode on&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;I turn editing mode off&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I switch editing mode on&lt;br /&gt;
And I switch editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to the existing step to go to a course with editing mode on, we now have the following step to do the same but with editing mode being off.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I am on &amp;quot;course full name&amp;quot; course homepage with editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step is similar to the old &amp;lt;code&amp;gt;following &amp;quot;link string&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&amp;lt;/code&amp;gt; step, with more flexibility.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;Download&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;Starter&amp;quot; &amp;quot;table_row&amp;quot; should download between &amp;quot;0&amp;quot; and &amp;quot;5000&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to hover the mouse over the trigger area.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over the &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step enables an installed plugin.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;plugin name&amp;quot; &amp;quot;plugin type&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;course_summary&amp;quot; &amp;quot;block&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following is a special variation of &#039;I click on &amp;quot;&amp;lt;page name&amp;gt;&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;page&amp;quot; &amp;quot;region&amp;quot;&#039;. It first checks to see if we are on the given page via the breadcrumb. If not we then attempt to follow the link name given.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I follow the breadcrumb &amp;quot;page name&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use the following step to ensure a node is active in the navbar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Node&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;My courses&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to navigate to a given node in the primary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select &amp;quot;Node&amp;quot; from primary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check whether an item exists in the user menu or not.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the user menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Language&amp;quot; &amp;quot;link&amp;quot; should exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check if a submenu of the user menu is shown, and if an item exists or does not exist in a given user submenu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I follow &amp;quot;Language&amp;quot; in the user menu&lt;br /&gt;
Then I should see &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English (pirate) &amp;amp;lrm;(en_ar)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add enrolment methods to courses you can use the following new step. The data that you provide in the next lines are used to fill the enrolment method form.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;enrolment method&amp;quot; in &amp;quot;course identifier&amp;quot; with:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I add &amp;quot;Self enrolment&amp;quot; enrolment method in &amp;quot;Course 1&amp;quot; with:&lt;br /&gt;
  | Custom instance name     | Test student enrolment |&lt;br /&gt;
  | Enrolment key            | moodle_rules           |&lt;br /&gt;
  | Use group enrolment keys | Yes                    |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are 3 new steps specific to the calendar component. These steps can be used to hover over a day in the mini-calendar or the full calendar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the full calendar page&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the mini-calendar block&lt;br /&gt;
And I hover over today in the mini-calendar block&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some new steps are added to question bank to be able to add comment to questions, verify the existence of a comment, and deleting comments form questions. Please note that the steps for adding comments only write the comment text in the comment field. You still need to click on the &amp;quot;Add comment&amp;quot; button to save the comment.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question preview&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question preview&lt;br /&gt;
And I should see &amp;quot;number of comments&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;number of comments&amp;quot; on the row on the comments column&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;Question bank&amp;quot; in current page administration&lt;br /&gt;
And I should see &amp;quot;0&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;0&amp;quot; on the row on the comments column&lt;br /&gt;
And I add &amp;quot;test comment 01&amp;quot; comment to question&lt;br /&gt;
And I click on &amp;quot;Add comment&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Close&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I should see &amp;quot;1&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;1&amp;quot; on the row on the comments column&lt;br /&gt;
And I delete &amp;quot;test comment 01&amp;quot; comment from question&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar to the steps for comments, the following steps are to verify the number of a question&#039;s usage and to click on it in order to open the question usage modal.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
And I click &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new steps are related to bulk actions in the question bank UI.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should not see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on &amp;quot;First question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Second question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;With selected&amp;quot; &amp;quot;button&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Delete&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;Confirm&amp;quot; &amp;quot;dialogue&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/en/Report_builder Report builder] is a new feature contributed to Moodle 4.0 by the Workplace team. The following new step is added to Moodle 4.0 to select an action from the action menu in the list of custom reports table.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I press &amp;quot;action&amp;quot; action in the &amp;quot;report name&amp;quot; report row&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There&#039;s another step related to the report builder to set a column&#039;s aggregation in the report editor.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;column title&amp;quot; column aggregation to &amp;quot;aggregation method&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;First name&amp;quot; column aggregation to &amp;quot;Comma separated values&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step needs to be used in scenarios that involve testing BigBlueButton. For this to work, you need to have a [https://github.com/moodlehq/bigbluebutton_mock BigBlueButton Mock API Server] and set &amp;lt;code&amp;gt;TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER&amp;lt;/code&amp;gt; to point to that in config.php.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And a BigBlueButton mock server is configured&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step replicates receiving a callback from the BigBlueButton server indicating the recordings for meetings are ready for viewing.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And the BigBlueButtonBN server has sent recording ready notifications&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are specific to the lesson activity. Note that in 4.0, some links (such as the &amp;quot;edit&amp;quot; and the &amp;quot;grade essays&amp;quot; links) are replaced by buttons, so you need to update your old steps with the new ones.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I edit the lesson&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;A new step is added to be used in lesson activities to edit them. This step navigates the user to the lesson edit page.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I grade lesson essays&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;It&#039;s a new step to go to the &amp;quot;Grade essays&amp;quot; page of the lesson we are currently in.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select edit type &amp;quot;edit type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Select the lesson edit type when we are in the the lesson&#039;s edit page. &amp;quot;edit type&amp;quot; can either be &amp;quot;Collapsed&amp;quot; or &amp;quot;Expanded&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new step can be used to navigate to the exports page in the course gradebook and select the specified export type from the grade exports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;export option&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;XML file&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similarly, there&#039;s a new step to navigate to the imports page in the course gradebook and select the specified import type from the grade imports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;import option&amp;quot; import page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Boost steps ===&lt;br /&gt;
In addition to the steps listed in the previous section, there are also some Boost specific steps coming with Moodle 4.0. These steps only work in Boost or Boost child themes, so you need to make sure they are not used in scenarios that may be run by non-Boost themes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step checks whether a node is active in the secondary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see :name is active in secondary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Boost theme shows the language selector menu in the primary navigation when not logged in, and within the user menu when logged in. The following steps are to check if the primary navigation includes the language selector menu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And language selector menu should exist in the navbar&lt;br /&gt;
And language selector menu should not exist in the navbar&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the following steps can be used to check whether an item exists in the language selector menu in the Boost theme.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the language selector menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Modified steps ===&lt;br /&gt;
The step &amp;lt;code&amp;gt;I change the (window|viewport) size to &amp;quot;size&amp;quot;&amp;lt;/code&amp;gt; now supports 2 new values for the size argument. The size argument now accepts &amp;lt;code&amp;gt;mobile&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;tablet&amp;lt;/code&amp;gt; values in addition to &amp;lt;code&amp;gt;small&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;medium&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;large&amp;lt;/code&amp;gt;.&lt;br /&gt;
=== Removed steps ===&lt;br /&gt;
Some behat steps are removed or replaced with new steps.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a result of some design changes, hidden or restricted activities are no longer dimmed. Therefore the step&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be dimmed&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;is now removed.&lt;br /&gt;
Depending on what you were using that step for, you may be able to use these steps:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Label name&amp;quot; label should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Activity or resource name&amp;quot;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;region-main&amp;quot; &amp;quot;region&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Other things to consider ===&lt;br /&gt;
To make behat tests more readable and easy to maintain, it is recommended to use the most direct steps to get what the test needs. It is highly recommended to use&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
instead of navigating to the activity via&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
Now that [https://docs.moodle.org/dev/Prototypes#Course_creation_improvements Course index] is integrated these behat steps&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
will fail using Boost theme.&lt;br /&gt;
&lt;br /&gt;
The reason for it is that the drawer used in Boost is hiding the course index. So when the test is trying to follow an &amp;quot;Activity name&amp;quot; link, it finds two different links:&lt;br /&gt;
* one in the course index&lt;br /&gt;
* another one in the course main content.&lt;br /&gt;
But the first one, the one in the course index, is hidden by the drawer, and the test fails.&lt;br /&gt;
&lt;br /&gt;
However the recommended behat steps&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
Old behat steps that may now fail can be updated to the new steps.&lt;br /&gt;
For example:&lt;br /&gt;
 And I am on the &amp;quot;Test assignment name&amp;quot; &amp;quot;assign activity&amp;quot; page logged in as teacher1&lt;br /&gt;
instead of:&lt;br /&gt;
 When I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
 And I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 And I follow &amp;quot;Test assignment name&amp;quot;&lt;br /&gt;
Or for settings, instead of:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I follow &amp;quot;Test choice name&amp;quot;&lt;br /&gt;
And I navigate to &amp;quot;Edit settings&amp;quot; in current page administration&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Use:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I am on the &amp;quot;Test choice name&amp;quot; &amp;quot;choice activity editing&amp;quot; page&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are also similar stream-lined navigation steps for accessing question bank pages. See MDL-74130.&lt;br /&gt;
== Other ==&lt;br /&gt;
=== Core plugins review ===&lt;br /&gt;
A few plugins from core Moodle LMS which are no longer or hardly used have been removed and, if appropriate, added to the Moodle plugins directory.&lt;br /&gt;
&lt;br /&gt;
More information about this project, the list of plugins to be removed and the process to follow for keeping them before upgrading to 4.0 can be found in the [[Core plugins review]] page.&lt;br /&gt;
=== Core blocks cleanup ===&lt;br /&gt;
In the &amp;quot;Add a block&amp;quot; menu, the list of blocks was really long. A few changes have been done to reduce this list.&lt;br /&gt;
&lt;br /&gt;
More information about this project can be found in the [[Add a block cleanup]] page.&lt;br /&gt;
=== Site admin presets plugin ===&lt;br /&gt;
The third-party plugin [https://moodle.org/plugins/block_admin_presets Admin presets], created by David Monllaó and maintained by developers from [https://pimenko.com/ Pimenko] has been adapted and integrated into Moodle 4.0. It stores settings and plugins status (enabled/disabled) in what&#039;s called &amp;quot;presets&amp;quot; to let admins quickly switch between different configurations.&lt;br /&gt;
&lt;br /&gt;
More information about this project can be found in the [[Site admin presets|Site admin presets plugin]] page.&lt;br /&gt;
=== JavaScript browser support changes ===&lt;br /&gt;
From Moodle 4.0, Internet Explorer is no longer supported. See MDL-73915 and MDLSITE-6109 for further information on this change.&lt;br /&gt;
&lt;br /&gt;
This change means that changes built on 4.0 onwards (including the master branch) will be different to older versions of Moodle.&lt;br /&gt;
&lt;br /&gt;
For plugin developers supporting multiple versions of Moodle using a single plugin version, the compiled javascript files are backwards compatible and will _work_ on all supported versions, however if you run the `grunt` command on multiple versions you will see unbuilt changes. Running grunt on all versions of Moodle is not necessary and this check can be safely disabled for Moodle versions 3.9 - 4.0, as long as only at least you run `grunt` against at least one version of Moodle.&lt;br /&gt;
&lt;br /&gt;
If you need to support Internet Explorer and do not wish to fork your plugin for Moodle 4.0 onwards, then it is recommended that you run `grunt` on an older version of Moodle.&lt;br /&gt;
=== The course index element ===&lt;br /&gt;
The new course index feature can be themed using a set of scss variables. Use them to change the look and feel instead of adding custom css&lt;br /&gt;
 /theme/boost/scss/moodle/courseindex.scss&lt;br /&gt;
With the introduction of the course index component, the previous and next links shown underneath each activity are no longer needed and they will be removed.&lt;br /&gt;
=== Activity icons ===&lt;br /&gt;
The icons used for activities have been redesigned and updated for all core moodle activities.&lt;br /&gt;
&lt;br /&gt;
When viewing the new icons in a file manager, for example for the quiz activity, you will see a simple black monochrome icon with a transparent background.&lt;br /&gt;
&lt;br /&gt;
On the course page, or in the activity chooser, the icon will display as a white icon on a coloured background. Styling of the icons on the coursepage is controlled by the css in theme/boost/scss/moodle/icons.scss.&lt;br /&gt;
&lt;br /&gt;
The background colour for activity icons is set using a new variable in function [modname]_supports(). The quiz activity is of type assessment, so in function quiz_supports() there is a new line defining the purpose:&lt;br /&gt;
 case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_ASSESSMENT;&lt;br /&gt;
Available purposes are:&lt;br /&gt;
* MOD_PURPOSE_COMMUNICATION&lt;br /&gt;
* MOD_PURPOSE_ASSESSMENT&lt;br /&gt;
* MOD_PURPOSE_COLLABORATION&lt;br /&gt;
* MOD_PURPOSE_CONTENT&lt;br /&gt;
* MOD_PURPOSE_ADMINISTRATION&lt;br /&gt;
* MOD_PURPOSE_INTERFACE&lt;br /&gt;
The background colours linked to these purposes are set in theme/boost/scss/moodle/variables.scss&lt;br /&gt;
 $activity-icon-colors: map-merge(&lt;br /&gt;
     (&lt;br /&gt;
         &amp;quot;administration&amp;quot;: #5d63f6,&lt;br /&gt;
         &amp;quot;assessment&amp;quot;: #eb66a2,&lt;br /&gt;
         &amp;quot;collaboration&amp;quot;: #f7634d,&lt;br /&gt;
         &amp;quot;communication&amp;quot;: #11a676,&lt;br /&gt;
         &amp;quot;content&amp;quot;: #399be2,&lt;br /&gt;
         &amp;quot;interface&amp;quot;: #a378ff&lt;br /&gt;
     ),&lt;br /&gt;
     $activity-icon-colors&lt;br /&gt;
 );&lt;br /&gt;
If activity plugins do not define FEATURE_MOD_PURPOSE the activity icon will be rendered against a light grey background. There is no requirement to define the purpose of activity plugins, it will only affect the icon styling.&lt;br /&gt;
&lt;br /&gt;
Plugins implementing the variable FEATURE_MOD_PURPOSE are only supported on Moodle 4.0 and newer.&lt;br /&gt;
&lt;br /&gt;
Customising the activity icon can be done in an alternative way. For example using the styles.css in mod/[pluginname/styles.css&lt;br /&gt;
&lt;br /&gt;
In the example below the activity plugin developer chooses to keep the coloured icon for the activity and render it as large as the coloured background on the core activities&lt;br /&gt;
 .modicon_subcourse.activityiconcontainer {&lt;br /&gt;
     background-color: transparent;&lt;br /&gt;
     padding: 0;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 .modicon_subcourse.activityiconcontainer img {&lt;br /&gt;
     width: 50px;&lt;br /&gt;
     height: 50px;&lt;br /&gt;
 }&lt;br /&gt;
To customize all icon colours use this scss array and add it to the ‘Raw initial SCSS’ in the theme Boost advanced settings page. The complete array of icon background colours can be overridden using the ‘Raw initial SCSS’ in the theme settings page. The example below changes the colours of each activity type.&lt;br /&gt;
 $activity-icon-colors: (&lt;br /&gt;
     &amp;quot;administration&amp;quot;: #5D63F6,&lt;br /&gt;
     &amp;quot;assessment&amp;quot;: #11A676,&lt;br /&gt;
     &amp;quot;collaboration&amp;quot;: #EB66A2,&lt;br /&gt;
     &amp;quot;communication&amp;quot;: #F7634D,&lt;br /&gt;
     &amp;quot;content&amp;quot;: #399BE2,&lt;br /&gt;
     &amp;quot;interface&amp;quot;: #A378FF&lt;br /&gt;
 )&lt;br /&gt;
== I&#039;m a developer, what do I need to know? ==&lt;br /&gt;
This section is a quick checklist of the areas in this document that you should consult when updating your plugin.&lt;br /&gt;
=== Modules ===&lt;br /&gt;
If you are a module developer (activity / resources) then you need to review the following updates and changes:&lt;br /&gt;
* If using settings, reformat to work with the secondary navigation. We have significantly changed the way that settings are shown. Settings added to the course and activity administration branch of the navigation are now by default shown in the secondary navigation. You will most likely find them in the more section of the secondary navigation. Please avoid creating settings in containers (a parent navigation node with children). These settings will still be shown, but this goes against the pattern that we are trying to establish for navigation around the site. If you have a lot of settings, consider creating a specific page to handle your additional settings.&lt;br /&gt;
** The order of the items in the secondary navigation may not be to your liking. This can be changed. See [[Moodle_4.0_developer_update#Changing_the_order_of_tabs|changing the order of tabs]]&lt;br /&gt;
* Update my behat tests to use new steps for site navigation. See [[Moodle_4.0_developer_update#Behat_changes|new behat steps]].&lt;br /&gt;
* Update my module to use the new activity_header API. See [[Moodle_4.0_developer_update#The_activity_header_class|the activity header]].&lt;br /&gt;
* Update my pages to make it work with the general format of the tertiary navigation. See [[Moodle_4.0_developer_update#Tertiary_navigation|the tertiary navigation]].&lt;br /&gt;
* Update my activity icon to use the API and set a purpose. See [[Moodle_4.0_developer_update#Activity_icons|activity icons]].&lt;br /&gt;
=== Themes ===&lt;br /&gt;
If you are a theme developer then you may want to consider the following:&lt;br /&gt;
* Take a look at the [[Moodle_4.0_developer_update#Navigation_changes|new navigation]] and decide if you want to incorporate this into your theme.&lt;br /&gt;
** A new layout ([[Moodle_4.0_developer_update#New_layout_page|drawers]])&lt;br /&gt;
** An [[Moodle_4.0_developer_update#Edit_switch|edit switch]]&lt;br /&gt;
** The [[Moodle_4.0_developer_update#The_course_index_element|course index]]&lt;br /&gt;
* Use of the flat nav&lt;br /&gt;
* New Site administration page and layout&lt;br /&gt;
* Course settings and how they are displayed&lt;br /&gt;
=== Course format ===&lt;br /&gt;
There have been a lot of changes made to the course format. Most in the process of moving the course format away from using the old rendering system and towards templates.&lt;br /&gt;
We recommend the following sections be read carefully:&lt;br /&gt;
# [[Moodle_4.0_developer_update#The_course_format_system|The course format]]. There have been a lot of deprecations and reading this section is critical in understanding the changes made.&lt;br /&gt;
# Consider moving the rendering of your content over to the [[Templates|template system]].&lt;br /&gt;
=== Other plugins ===&lt;br /&gt;
# Are you adding settings? See the [[Moodle_4.0_developer_update#Adding_items_to_the_navigation|secondary nav]] for adding items to this navigation bar.&lt;br /&gt;
# Have a look at [[Moodle_4.0_developer_update#Secondary_navigation|secondary]] and [[Moodle_4.0_developer_update#Tertiary_navigation|tertiary]] navigation changes in general if you have a plugin that has multiple pages to navigate around.&lt;br /&gt;
# Do you have behat tests? Check the new [[Moodle_4.0_developer_update#Behat_changes|behat changes]].&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61889</id>
		<title>Moodle 4.0 developer update</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61889"/>
		<updated>2022-03-23T01:21:50Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Theme updates: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 4.0}}This page highlights the important changes that are coming in Moodle 4.0 for developers. Including how the UX improvements impact custom themes, relevant API changes, and what you can do as developer to prepare for the 4.0 release.&lt;br /&gt;
== Navigation changes ==&lt;br /&gt;
The core Navigation API has been left mostly untouched. The callbacks to all navigation callbacks remains unchanged and will be called as part of the regular &#039;navigation&#039; and &#039;settingsnav&#039; initialisation. Some new core classes have been created and exist within a new namespace &#039;core/navigation&#039; and serves as conduit to rearrange, cherry-pick existing navigation nodes from the navigation/settingsnav trees and display within the respective navigation type. As such, it is highly recommended to provide unique keys for custom navigation nodes as this helps in the cherry-picking / rearranging process within the new classes.&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
The primary navigation(the navbar) apart from the existing content will now display links to the Dashboard, My Courses, Site Admin and Course search, by default. You can still add items to the navbar via the &#039;custom menu&#039; option. This will be displayed within the &#039;More&#039; menu. We have transitioned the menus to be rendered via templates - refer user_menu.mustache. The lang menu has been moved to reside within the user menu.&lt;br /&gt;
==== Customising the primary navigation ====&lt;br /&gt;
Not yet implemented but we are looking at allowing the full addition and removal of any of the primary navigation tabs in the boost theme config file.&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
The main content area shows tabs for secondary navigation with a maximum of 5 items being rendered in this ‘more’ menu. A new UI component has been created to render menus like this. Files:&lt;br /&gt;
 /lib/templates/moremenu.mustache&lt;br /&gt;
==== Adding items to the navigation ====&lt;br /&gt;
The secondary navigation pulls information mainly from the settings navigation node from each context. Any plugin that implements the existing navigation hooks will have their items added to the secondary navigation.&lt;br /&gt;
Existing navigation hooks:&lt;br /&gt;
* {module}_extend_navigation&lt;br /&gt;
* {local}_extend_navigation&lt;br /&gt;
* {report}_report_extend_navigation&lt;br /&gt;
* {plugin}_extend_navigation_course&lt;br /&gt;
* {plugin}_extend_navigation_category_settings&lt;br /&gt;
==== Changing the order of tabs ====&lt;br /&gt;
Apart from the previously mentioned functions, you can also create a custom secondary class as mentioned earlier. This will automatically be picked by getter and used to render the secondary nav within the activity. E.g. mod_assign/local/views/secondary. Note: This is currently only possible on an activity and block level.&lt;br /&gt;
=== Tertiary navigation ===&lt;br /&gt;
We&#039;ve moved action buttons to the top of the page. We would encourage you to do the same.&lt;br /&gt;
If you have any buttons on an activity page that go to another page, or open a form (or similar), then we encourage you to move them from the body of your activity page to the top. All of the core activities have been updated to follow this pattern. Please take a look to see how you can format your activity in a similar fashion. There is no API here. You are welcome to create the buttons and display them as you wish in this top area.&lt;br /&gt;
=== New API functions ===&lt;br /&gt;
==== Page API ====&lt;br /&gt;
* Magic getters to fetch the primary and secondary navs and the primary output.&lt;br /&gt;
* The secondarynav magic getter also checks whether a custom secondary class has been defined within the module&#039;s local\views directory. Use this if you want to deviate from the standard secondary nav structure/order.&lt;br /&gt;
&lt;br /&gt;
* set_secondarynav - Force override the secondary navigation class&lt;br /&gt;
&lt;br /&gt;
* set_secondary_navigation - Sets the ‘_hassecondarynavigation’ and optionally the ‘_hastablistsecondarynavigation’ to indicate whether a page should render the secondary navigation, and if the secondary navigation should be rendered and behave with a tablist ARIA role (as opposed to its default which is being rendered with a menubar ARIA role).&lt;br /&gt;
==== Navigationlib ====&lt;br /&gt;
* set_show_in_secondary_navigation - whether or not a node should be displayed in the secondary nav. Accepts a single boolean argument&lt;br /&gt;
* set_force_into_more_menu- whether or not to force a node into the &#039;More&#039; menu. Accepts a single boolean argument&lt;br /&gt;
==== The activity header class ====&lt;br /&gt;
There is a new activity header class that handles the display of information common to activities. 3rd party activities are not required to explicitly output this information as part of rendering individual pages.&lt;br /&gt;
&lt;br /&gt;
The common information that are currently handled by the class are:&lt;br /&gt;
* title&lt;br /&gt;
* description&lt;br /&gt;
* completion information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As part of the update it was required that the initial information to be displayed by the class be toggable at a theme and layout level. Taking this into account the following theme level configurable exists:&lt;br /&gt;
* activityheaderconfig =&amp;gt; An array that currently only enforces &#039;notitle&#039; but can be expanded in the future NOTE: Boost has this set as true by default &#039;options&#039;&lt;br /&gt;
The following layout level options that can be defined:&lt;br /&gt;
* noactivityheader - to remove the header in this specific layout.&lt;br /&gt;
* activityheader - An array that enforces the following options:&lt;br /&gt;
** notitle&lt;br /&gt;
** nocompletion&lt;br /&gt;
** nodescription&lt;br /&gt;
The class has a page level getter which you can use to fetch the current version of the class. The base state is initialised within the constructor with the completion information only fetched when data is exported for the template.&lt;br /&gt;
&lt;br /&gt;
The class has setters for the following variables which can be leveraged to modify the header for a particular page in the format set_{variable_name}:&lt;br /&gt;
* hidecompletion&lt;br /&gt;
* description&lt;br /&gt;
* title&lt;br /&gt;
Alternately, bulk operations can also be done by passing the above variables in an array to &#039;set_attrs&#039; which in turn calls the setters.&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note: Any updates to the activityheader needs to be performed before the call to $OUTPUT-&amp;gt;header&#039;&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
===== Theme updates: =====&lt;br /&gt;
With the changes in boost to incorporate the primary and secondary navigation, 3rd party themes would need to account for the following in their templates:&lt;br /&gt;
* To leverage the activity_header, it&#039;s data needs to be exported and included into the base template :&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
   {{&amp;gt; core/activity_header}}&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;** headercontent being the array element that contains the exported activity_header data&lt;br /&gt;
* It is recommended to transition towards the secondary/tertiary navigation hierarchy to reduce user cognitive load and with a logical separation of components&lt;br /&gt;
** Secondary navigation can be added to the templates by following the example https://github.com/moodle/moodle/blob/master/theme/boost/templates/columns2.mustache#L64-L68 This leverages the secondary navigation class to generate it&#039;s content.&lt;br /&gt;
* Flat navigation classes have been marked for deprecation. Themes that leverage the flat_navigation will need to make the following changes in their plugins in order to use it&lt;br /&gt;
** Account for the additional changes [[Moodle 4.0 developer update#Theme changes]]&lt;br /&gt;
** Indicate that they do not implement secondary navigation via the page&#039;s &amp;quot;set_secondary_navigation&amp;quot; function. It is recommended to set this within the root layout file e.g. columns2&lt;br /&gt;
** Initialise the flat navigation by introducing the following in the root layout file(if not existent)&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$nav = $PAGE-&amp;gt;flatnav;&lt;br /&gt;
$templatecontext[&#039;firstcollectionlabel&#039;] = $nav-&amp;gt;get_collectionlabel();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* In order to reintroduce the settings cog in the templates, you can introduce the following: &amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;region-main-settings-menu&amp;quot; class=&amp;quot;d-print-none {{#hasblocks}}has-blocks{{/hasblocks}}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div&amp;gt; {{{ output.region_main_settings_menu }}} &amp;lt;/div&amp;gt;            &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Accessibility notes: =====&lt;br /&gt;
The jump to ‘maincontent’ div is now rendered within the activity header when within an activity context&lt;br /&gt;
== Component library ==&lt;br /&gt;
Each Moodle installation now ships with a Moodle User Interface (UI) Component library, a documentation system used to describe all the Bootstrap components and the custom Moodle components. The component Library is a helper tool for developers when creating user interfaces, a testing tool for theme developers and a documentation tool for core developers. The ultimate goal of having a component library is to encourage developers to create consistent user interfaces to improve Moodle’s overall user experience.&lt;br /&gt;
&lt;br /&gt;
The library contains pages with documentation about User Interface components. It contains details on how to use the component, what variations are available and the JavaScript events / options are associated with the component.&lt;br /&gt;
&lt;br /&gt;
When writing on these pages it is possible to render core mustache templates using some custom syntax like this:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; mustache template=&amp;quot;core/notification_error&amp;quot; &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; /mustache &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also call core JavaScript or use HTML examples where the html code and the rendered result are visible in the Component Library. For more info visit the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-templates/ Moodle templates] page or the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-javascript/ Moodle JavaScript] page.&lt;br /&gt;
&lt;br /&gt;
Each page in the library uses the current css from the default theme in your Moodle installation, if you have multiple themes installed and enabled the setting &amp;quot;Allow theme changes on url&amp;quot;, the component library will have a theme selector option.&lt;br /&gt;
&lt;br /&gt;
A hosted version of the Component Library can be found here. http://componentlibrary.moodle.com&lt;br /&gt;
=== Enabling the Component Library ===&lt;br /&gt;
Component library pages are written in the markdown language. These pages need to be compiled to HTML pages before the Component Library is visible. To compile the pages the server running Moodle needs to have the [[Javascript Modules#Install%20NVM%20and%20Node|JavaScript developer tools installed]] (nodeJs and Grunt)&lt;br /&gt;
&lt;br /&gt;
If your server meets all requirements you can enable the library running&lt;br /&gt;
 $ npm install&lt;br /&gt;
 $ grunt componentlibrary&lt;br /&gt;
Further installation instructions can be found in the Component Library itself.&lt;br /&gt;
=== Documenting new UI Components ===&lt;br /&gt;
There are no set rules for adding new pages in the component library yet. These rules will need to be written and adopted in the integration process for Moodle code.&lt;br /&gt;
&lt;br /&gt;
As a guideline for making this rules consideration are:&lt;br /&gt;
&lt;br /&gt;
The component library is not about single use components, for example the Moodle grade book (a huge component with many custom features). Or about very common components like buttons, these are already covered by the Bootstrap section of the component library.&lt;br /&gt;
&lt;br /&gt;
New features should be build keeping in mind the UI part needs to be customisable and if possible (and making sense) reusable. And example would be the new page drawers that we are introducing for the Navigation project. Or the custom primary navigation menus where overflowing items are pushed into a More section.&lt;br /&gt;
== Theme changes ==&lt;br /&gt;
=== Edit switch ===&lt;br /&gt;
On theme boost the “Turn editing on” and “Customise this page” buttons have been replaced by an edit switch in the top navbar. Theme Classic will keep using the old buttons. Child themes can choose to use the edit switch if the theme config.php is using this variable&lt;br /&gt;
 $THEME-&amp;gt;haseditswitch = true;&lt;br /&gt;
The languague menu, which used to be rendered in place of the custom menu has moved to the user dropdown when the user is logged in. If not logged in it will be placed next to the search / notification / messaging icon in the top navbar.&lt;br /&gt;
=== Login page ===&lt;br /&gt;
The login page has been redesigned and allows the admin to configure a background image for the login page only in the theme settings page. This change is available in both Boost and Classic. The login page still has all the features with an improved layout. &lt;br /&gt;
=== The page footer ===&lt;br /&gt;
In large screens, the page footer button is only visible when clicking a help button at the bottom right of the screen.&lt;br /&gt;
=== User initials as profile picture placeholder ===&lt;br /&gt;
If users do not upload a profile picture the user initials are displayed on a rounded gray background as a placeholder picture in the top navbar or any other page using a placeholder image. This change will be available in both Boost and Classic. &lt;br /&gt;
&lt;br /&gt;
With the introduction of this placeholder image the full username will no longer be displayed in the top navbar.&lt;br /&gt;
=== Removal of back to top link ===&lt;br /&gt;
The &amp;quot;back to top&amp;quot; link will be removed for theme boost since the new course index reduced the dependence on page scrolling. Also, the new footer is positioned where this component used to be.&lt;br /&gt;
=== Styling changes ===&lt;br /&gt;
By default rounded edges will be used for UI components, for the page header and main content area the borders will be removed. &lt;br /&gt;
=== New layout page ===&lt;br /&gt;
Theme boost now uses the drawers.php layout for the course index and blocks.&lt;br /&gt;
== Question bank changes ==&lt;br /&gt;
There was a big project to deliver [[Question bank improvements for Moodle 4.0]] which added a new plugin type for adding features to the question banks, tracking the version history for each question as it is edited (question table has been split into &amp;lt;code&amp;gt;question&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;question_versions&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_bank_entries&amp;lt;/code&amp;gt;), and tracking where each question is going to be used, with new tables &amp;lt;code&amp;gt;question_references&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_set_references&amp;lt;/code&amp;gt;. This work was done in Epic MDL-70329 if you want to track down the details of any of the core changes.&lt;br /&gt;
=== Question type plugins ===&lt;br /&gt;
Amazingly, we (Safat and colleagues at Catalyst AU) managed to implement this without breaking most question type plugins.&lt;br /&gt;
&lt;br /&gt;
However, the changes to the question bank, and the other Moodle 4.0 changes, probably broke the Behat tests for your plugin. To help with fixing that, MDL-74130 adds navigation to key question type pages (Preview and Edit for a question, and standard question bank pages like the bank itself, import and export) which should let you fix your test efficiently, and in a way that will work in all Moodle versions since 3.9.&lt;br /&gt;
&lt;br /&gt;
The &#039;most&#039; in the first paragraph here is becuase more advance question types may require more effort to fix. (For example qtype_combined which creates multi-part qusetions like the core qtype_multianswer; or qtype_pmatch or qtype_stack, which store additional data - questions tests - alongside the question itseld. How should that work with versionning?) But, if you have not done weird things like that, you are probably safe. If you find anything else that causes problems, please list it here.&lt;br /&gt;
&lt;br /&gt;
The same thing should apply to question behaviour and question import/export format plugings: no significant changes required (probably just fixing the Behat tests because of the navigation changes).&lt;br /&gt;
=== New plugin type: qbank plugins ===&lt;br /&gt;
This is not something that will cause problems for people upgrading from 3.x. Rather, it is an exciting possibility you can explore once you have survived process of upgrading to 4.0. There is a whole new plugin type which you can create to add new features to the question bank. For example extra columns, new actions and bulk actions, and so on. See [[Question_bank_plugins]].&lt;br /&gt;
=== Activities that use questions ===&lt;br /&gt;
The probable bad news is if you have an activity module which uses questions. So far, the only activity which has been fixed is mod_quiz in Moodle core, so we don&#039;t yet have a good picture of what fixes will be necessary in other activities. Work is about to start fixing [https://github.com/studentquiz/moodle-mod_studentquiz mod_studentquiz], so watching that should give more clues. As we do that, we will try to update this section of this page. Other help writing the information required here would also be greatly appreciated.&lt;br /&gt;
== The course format system ==&lt;br /&gt;
Most of the logic for rendering and editing a course has been moved to a new subsystem called courseformat. The subsystem is located in &amp;quot;course/format&amp;quot; folder so it includes all the format plugins inside. The methods and modules which are distributed between the course and the course/format folders are now rearranged or refactored to be aligned with the current Moodle coding style.&lt;br /&gt;
=== Mandatory renderer in course formats ===&lt;br /&gt;
Now format plugins renderer is not optional anymore. Legacy formats without a renderer will get a deprecation message but it will continue working however, they should create a new renderer as soon as possible. The section-based format can do it by extending the provided core_courseformat\output\section_renderer class which includes all the necessary methods.&lt;br /&gt;
=== New format base class ===&lt;br /&gt;
The old base_format class (which all plugins extend) is now renamed as core_courseformat\base. The new class provides all the functionally of the previous base_format but it has been refactored to be used as a centralized source of truth for the course rendering. Legacy formats should extend the new class to avoid the deprecation message.&lt;br /&gt;
&lt;br /&gt;
Now, the plugin format class provides information such as:&lt;br /&gt;
* If the page is displaying a single or multiple section&lt;br /&gt;
* Give access to other related format objects like the modinfo, the course record, maximum number of sections...&lt;br /&gt;
* If the format is compatible with features like course index, reactive components, ajax...&lt;br /&gt;
* Other format specifics like the page title, the default section name, default blocks...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The format instance is now the main object output components will use to render a course (see next section for more information).&lt;br /&gt;
=== New course output classes and mustache files ===&lt;br /&gt;
Traditionally, section-based course formats uses print_single_section_page and print_multiple_section_page to render the course content. In Moodle 4.0 most of the course rendering methods are migrated to output components and mustache templates. The old methods will get deprecation messages if they use the old renderer methods.&lt;br /&gt;
&lt;br /&gt;
This is an example of a format rendering a course:&amp;lt;syntaxhighlight lang=&amp;quot;php-brief&amp;quot;&amp;gt;&lt;br /&gt;
// Get the course format instance.&lt;br /&gt;
$format = course_get_format($course);&lt;br /&gt;
&lt;br /&gt;
// Get the specific format renderer.&lt;br /&gt;
$renderer = $format-&amp;gt;get_renderer($PAGE);&lt;br /&gt;
&lt;br /&gt;
if (!empty($displaysection)) {&lt;br /&gt;
    // Setup the format instance to display a single section.&lt;br /&gt;
    $format-&amp;gt;set_section_number($displaysection);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Create the ouptut instance and render it.&lt;br /&gt;
$outputclass = $format-&amp;gt;get_output_classname(&#039;content&#039;);&lt;br /&gt;
$widget = new $outputclass($format);&lt;br /&gt;
&lt;br /&gt;
echo $renderer-&amp;gt;render($widget);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Format plugins are free to use its own output classes to render a course, or they could override the existing output classes by providing their own implementation. For example, the default output for &amp;quot;content&amp;quot; (as in the previous example) is &amp;quot;core_courseformat\output\local\|content&amp;quot;, however, if the plugin has a &amp;quot;format_XXX\output\courseformat\content&amp;quot; class, the $format-&amp;gt;class the get_output_class will return the overridden one.&lt;br /&gt;
Another important update on course rendering is that now all course structure is rendered using mustache templates instead of the original html_writer methods. Now themes are able to override the course format by providing alternative versions of the mustache files. All core course templates are located in &amp;quot;course/format/templates&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All the new output classes and a guide on how to migrate the current third-party plugins will be available soon.&lt;br /&gt;
=== Course editor javascript modules and frontend components ===&lt;br /&gt;
The majority of the javascript logic related to the course editing is replaced by AMD modules. Because this is a major change in the way courses are edited and rendered, by default format plugins will continue using the previous YUI modules for now. However, formats can start using the new libraries overriding the &amp;quot;$format-&amp;gt;supports_components()&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Some Moodle 4.0 new features are only available for courses using the new editor library:&lt;br /&gt;
* Edit the course via the course index&lt;br /&gt;
* Creating sections without reloading the course page&lt;br /&gt;
* The new move section/activity modal&lt;br /&gt;
* Native browser drag&amp;amp;drop implementation&lt;br /&gt;
The new course editor uses a component-based reactive pattern to keep track of the course changes. The pattern highlights are:&lt;br /&gt;
* The main AMD module &amp;quot;core_crouseformat\courseeditor&amp;quot; maintains a data structure called state.&lt;br /&gt;
* Each UI element is implemented as a Component that observes the course state data and reacts to any data change&lt;br /&gt;
* When any reactive component needs to modify the course, it asks the course editor to execute a mutation. Mutations encapsulate all web services calls and alter the course state data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The reactive library documentation, as well as the format plugin migration guide, will be available soon.&lt;br /&gt;
=== Other course related 4.0 changes ===&lt;br /&gt;
Two new web services have been added:&lt;br /&gt;
* core_courseformat_get_state: user by the new javascript course editor to get the current course state data (containing the list of sections, activities, and other course-related data)&lt;br /&gt;
* core_courseformat_update_course: to alter the current course content. Each call returns the parts of the course state altered by the action&lt;br /&gt;
== Behat changes ==&lt;br /&gt;
=== New steps ===&lt;br /&gt;
Moodle 4.0 introduces some new behat steps.&lt;br /&gt;
&lt;br /&gt;
Sometimes you want to create a bulk number of activities. In that case you can use:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
:count :entitytype exist with the following data:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Given 100 &amp;quot;mod_lti &amp;gt; tool types&amp;quot; exist with the following data:&lt;br /&gt;
  |name        |Test tool [count]                  |&lt;br /&gt;
  |description |Example description [count]        |&lt;br /&gt;
  |baseurl     |https://www.example.com/tool[count]|&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dynamic (AJAX) tabs is a new feature contributed to Moodle 4.0 by the Workplace team (MDL-71943). You can use the following step to navigate between the tabs.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on the &amp;quot;tab title&amp;quot; dynamic tab&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To make sure that edit mode is (or is not) available on the current page, the following steps can be used.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And edit mode should be available on the current page&lt;br /&gt;
And edit mode should not be available on the current page&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are new aliases for the existing steps &amp;lt;code&amp;gt;I turn editing mode on&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;I turn editing mode off&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I switch editing mode on&lt;br /&gt;
And I switch editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to the existing step to go to a course with editing mode on, we now have the following step to do the same but with editing mode being off.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I am on &amp;quot;course full name&amp;quot; course homepage with editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step is similar to the old &amp;lt;code&amp;gt;following &amp;quot;link string&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&amp;lt;/code&amp;gt; step, with more flexibility.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;Download&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;Starter&amp;quot; &amp;quot;table_row&amp;quot; should download between &amp;quot;0&amp;quot; and &amp;quot;5000&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to hover the mouse over the trigger area.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over the &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step enables an installed plugin.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;plugin name&amp;quot; &amp;quot;plugin type&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;course_summary&amp;quot; &amp;quot;block&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following is a special variation of &#039;I click on &amp;quot;&amp;lt;page name&amp;gt;&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;page&amp;quot; &amp;quot;region&amp;quot;&#039;. It first checks to see if we are on the given page via the breadcrumb. If not we then attempt to follow the link name given.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I follow the breadcrumb &amp;quot;page name&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use the following step to ensure a node is active in the navbar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Node&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;My courses&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to navigate to a given node in the primary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select &amp;quot;Node&amp;quot; from primary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check whether an item exists in the user menu or not.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the user menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Language&amp;quot; &amp;quot;link&amp;quot; should exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check if a submenu of the user menu is shown, and if an item exists or does not exist in a given user submenu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I follow &amp;quot;Language&amp;quot; in the user menu&lt;br /&gt;
Then I should see &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English (pirate) &amp;amp;lrm;(en_ar)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add enrolment methods to courses you can use the following new step. The data that you provide in the next lines are used to fill the enrolment method form.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;enrolment method&amp;quot; in &amp;quot;course identifier&amp;quot; with:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I add &amp;quot;Self enrolment&amp;quot; enrolment method in &amp;quot;Course 1&amp;quot; with:&lt;br /&gt;
  | Custom instance name     | Test student enrolment |&lt;br /&gt;
  | Enrolment key            | moodle_rules           |&lt;br /&gt;
  | Use group enrolment keys | Yes                    |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are 3 new steps specific to the calendar component. These steps can be used to hover over a day in the mini-calendar or the full calendar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the full calendar page&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the mini-calendar block&lt;br /&gt;
And I hover over today in the mini-calendar block&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some new steps are added to question bank to be able to add comment to questions, verify the existence of a comment, and deleting comments form questions. Please note that the steps for adding comments only write the comment text in the comment field. You still need to click on the &amp;quot;Add comment&amp;quot; button to save the comment.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question preview&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question preview&lt;br /&gt;
And I should see &amp;quot;number of comments&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;number of comments&amp;quot; on the row on the comments column&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;Question bank&amp;quot; in current page administration&lt;br /&gt;
And I should see &amp;quot;0&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;0&amp;quot; on the row on the comments column&lt;br /&gt;
And I add &amp;quot;test comment 01&amp;quot; comment to question&lt;br /&gt;
And I click on &amp;quot;Add comment&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Close&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I should see &amp;quot;1&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;1&amp;quot; on the row on the comments column&lt;br /&gt;
And I delete &amp;quot;test comment 01&amp;quot; comment from question&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar to the steps for comments, the following steps are to verify the number of a question&#039;s usage and to click on it in order to open the question usage modal.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
And I click &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new steps are related to bulk actions in the question bank UI.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should not see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on &amp;quot;First question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Second question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;With selected&amp;quot; &amp;quot;button&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Delete&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;Confirm&amp;quot; &amp;quot;dialogue&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/en/Report_builder Report builder] is a new feature contributed to Moodle 4.0 by the Workplace team. The following new step is added to Moodle 4.0 to select an action from the action menu in the list of custom reports table.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I press &amp;quot;action&amp;quot; action in the &amp;quot;report name&amp;quot; report row&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There&#039;s another step related to the report builder to set a column&#039;s aggregation in the report editor.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;column title&amp;quot; column aggregation to &amp;quot;aggregation method&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;First name&amp;quot; column aggregation to &amp;quot;Comma separated values&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step needs to be used in scenarios that involve testing BigBlueButton. For this to work, you need to have a [https://github.com/moodlehq/bigbluebutton_mock BigBlueButton Mock API Server] and set &amp;lt;code&amp;gt;TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER&amp;lt;/code&amp;gt; to point to that in config.php.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And a BigBlueButton mock server is configured&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step replicates receiving a callback from the BigBlueButton server indicating the recordings for meetings are ready for viewing.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And the BigBlueButtonBN server has sent recording ready notifications&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are specific to the lesson activity. Note that in 4.0, some links (such as the &amp;quot;edit&amp;quot; and the &amp;quot;grade essays&amp;quot; links) are replaced by buttons, so you need to update your old steps with the new ones.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I edit the lesson&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;A new step is added to be used in lesson activities to edit them. This step navigates the user to the lesson edit page.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I grade lesson essays&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;It&#039;s a new step to go to the &amp;quot;Grade essays&amp;quot; page of the lesson we are currently in.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select edit type &amp;quot;edit type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Select the lesson edit type when we are in the the lesson&#039;s edit page. &amp;quot;edit type&amp;quot; can either be &amp;quot;Collapsed&amp;quot; or &amp;quot;Expanded&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new step can be used to navigate to the exports page in the course gradebook and select the specified export type from the grade exports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;export option&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;XML file&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similarly, there&#039;s a new step to navigate to the imports page in the course gradebook and select the specified import type from the grade imports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;import option&amp;quot; import page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Boost steps ===&lt;br /&gt;
In addition to the steps listed in the previous section, there are also some Boost specific steps coming with Moodle 4.0. These steps only work in Boost or Boost child themes, so you need to make sure they are not used in scenarios that may be run by non-Boost themes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step checks whether a node is active in the secondary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see :name is active in secondary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Boost theme shows the language selector menu in the primary navigation when not logged in, and within the user menu when logged in. The following steps are to check if the primary navigation includes the language selector menu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And language selector menu should exist in the navbar&lt;br /&gt;
And language selector menu should not exist in the navbar&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the following steps can be used to check whether an item exists in the language selector menu in the Boost theme.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the language selector menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Modified steps ===&lt;br /&gt;
The step &amp;lt;code&amp;gt;I change the (window|viewport) size to &amp;quot;size&amp;quot;&amp;lt;/code&amp;gt; now supports 2 new values for the size argument. The size argument now accepts &amp;lt;code&amp;gt;mobile&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;tablet&amp;lt;/code&amp;gt; values in addition to &amp;lt;code&amp;gt;small&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;medium&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;large&amp;lt;/code&amp;gt;.&lt;br /&gt;
=== Removed steps ===&lt;br /&gt;
Some behat steps are removed or replaced with new steps.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a result of some design changes, hidden or restricted activities are no longer dimmed. Therefore the step&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be dimmed&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;is now removed.&lt;br /&gt;
Depending on what you were using that step for, you may be able to use these steps:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Label name&amp;quot; label should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Activity or resource name&amp;quot;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;region-main&amp;quot; &amp;quot;region&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Other things to consider ===&lt;br /&gt;
To make behat tests more readable and easy to maintain, it is recommended to use the most direct steps to get what the test needs. It is highly recommended to use&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
instead of navigating to the activity via&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
Now that [https://docs.moodle.org/dev/Prototypes#Course_creation_improvements Course index] is integrated these behat steps&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
will fail using Boost theme.&lt;br /&gt;
&lt;br /&gt;
The reason for it is that the drawer used in Boost is hiding the course index. So when the test is trying to follow an &amp;quot;Activity name&amp;quot; link, it finds two different links:&lt;br /&gt;
* one in the course index&lt;br /&gt;
* another one in the course main content.&lt;br /&gt;
But the first one, the one in the course index, is hidden by the drawer, and the test fails.&lt;br /&gt;
&lt;br /&gt;
However the recommended behat steps&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
Old behat steps that may now fail can be updated to the new steps.&lt;br /&gt;
For example:&lt;br /&gt;
 And I am on the &amp;quot;Test assignment name&amp;quot; &amp;quot;assign activity&amp;quot; page logged in as teacher1&lt;br /&gt;
instead of:&lt;br /&gt;
 When I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
 And I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 And I follow &amp;quot;Test assignment name&amp;quot;&lt;br /&gt;
Or for settings, instead of:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I follow &amp;quot;Test choice name&amp;quot;&lt;br /&gt;
And I navigate to &amp;quot;Edit settings&amp;quot; in current page administration&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Use:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I am on the &amp;quot;Test choice name&amp;quot; &amp;quot;choice activity editing&amp;quot; page&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are also similar stream-lined navigation steps for accessing question bank pages. See MDL-74130.&lt;br /&gt;
== Other ==&lt;br /&gt;
=== Core plugins review ===&lt;br /&gt;
A few plugins from core Moodle LMS which are no longer or hardly used have been removed and, if appropriate, added to the Moodle plugins directory.&lt;br /&gt;
&lt;br /&gt;
More information about this project, the list of plugins to be removed and the process to follow for keeping them before upgrading to 4.0 can be found in the [[Core plugins review]] page.&lt;br /&gt;
=== Core blocks cleanup ===&lt;br /&gt;
In the &amp;quot;Add a block&amp;quot; menu, the list of blocks was really long. A few changes have been done to reduce this list.&lt;br /&gt;
&lt;br /&gt;
More information about this project can be found in the [[Add a block cleanup]] page.&lt;br /&gt;
=== Site admin presets plugin ===&lt;br /&gt;
The third-party plugin [https://moodle.org/plugins/block_admin_presets Admin presets], created by David Monllaó and maintained by developers from [https://pimenko.com/ Pimenko] has been adapted and integrated into Moodle 4.0. It stores settings and plugins status (enabled/disabled) in what&#039;s called &amp;quot;presets&amp;quot; to let admins quickly switch between different configurations.&lt;br /&gt;
&lt;br /&gt;
More information about this project can be found in the [[Site admin presets|Site admin presets plugin]] page.&lt;br /&gt;
=== JavaScript browser support changes ===&lt;br /&gt;
From Moodle 4.0, Internet Explorer is no longer supported. See MDL-73915 and MDLSITE-6109 for further information on this change.&lt;br /&gt;
&lt;br /&gt;
This change means that changes built on 4.0 onwards (including the master branch) will be different to older versions of Moodle.&lt;br /&gt;
&lt;br /&gt;
For plugin developers supporting multiple versions of Moodle using a single plugin version, the compiled javascript files are backwards compatible and will _work_ on all supported versions, however if you run the `grunt` command on multiple versions you will see unbuilt changes. Running grunt on all versions of Moodle is not necessary and this check can be safely disabled for Moodle versions 3.9 - 4.0, as long as only at least you run `grunt` against at least one version of Moodle.&lt;br /&gt;
&lt;br /&gt;
If you need to support Internet Explorer and do not wish to fork your plugin for Moodle 4.0 onwards, then it is recommended that you run `grunt` on an older version of Moodle.&lt;br /&gt;
=== The course index element ===&lt;br /&gt;
The new course index feature can be themed using a set of scss variables. Use them to change the look and feel instead of adding custom css&lt;br /&gt;
 /theme/boost/scss/moodle/courseindex.scss&lt;br /&gt;
With the introduction of the course index component, the previous and next links shown underneath each activity are no longer needed and they will be removed.&lt;br /&gt;
=== Activity icons ===&lt;br /&gt;
The icons used for activities have been redesigned and updated for all core moodle activities.&lt;br /&gt;
&lt;br /&gt;
When viewing the new icons in a file manager, for example for the quiz activity, you will see a simple black monochrome icon with a transparent background.&lt;br /&gt;
&lt;br /&gt;
On the course page, or in the activity chooser, the icon will display as a white icon on a coloured background. Styling of the icons on the coursepage is controlled by the css in theme/boost/scss/moodle/icons.scss.&lt;br /&gt;
&lt;br /&gt;
The background colour for activity icons is set using a new variable in function [modname]_supports(). The quiz activity is of type assessment, so in function quiz_supports() there is a new line defining the purpose:&lt;br /&gt;
 case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_ASSESSMENT;&lt;br /&gt;
Available purposes are:&lt;br /&gt;
* MOD_PURPOSE_COMMUNICATION&lt;br /&gt;
* MOD_PURPOSE_ASSESSMENT&lt;br /&gt;
* MOD_PURPOSE_COLLABORATION&lt;br /&gt;
* MOD_PURPOSE_CONTENT&lt;br /&gt;
* MOD_PURPOSE_ADMINISTRATION&lt;br /&gt;
* MOD_PURPOSE_INTERFACE&lt;br /&gt;
The background colours linked to these purposes are set in theme/boost/scss/moodle/variables.scss&lt;br /&gt;
 $activity-icon-colors: map-merge(&lt;br /&gt;
     (&lt;br /&gt;
         &amp;quot;administration&amp;quot;: #5d63f6,&lt;br /&gt;
         &amp;quot;assessment&amp;quot;: #eb66a2,&lt;br /&gt;
         &amp;quot;collaboration&amp;quot;: #f7634d,&lt;br /&gt;
         &amp;quot;communication&amp;quot;: #11a676,&lt;br /&gt;
         &amp;quot;content&amp;quot;: #399be2,&lt;br /&gt;
         &amp;quot;interface&amp;quot;: #a378ff&lt;br /&gt;
     ),&lt;br /&gt;
     $activity-icon-colors&lt;br /&gt;
 );&lt;br /&gt;
If activity plugins do not define FEATURE_MOD_PURPOSE the activity icon will be rendered against a light grey background. There is no requirement to define the purpose of activity plugins, it will only affect the icon styling.&lt;br /&gt;
&lt;br /&gt;
Plugins implementing the variable FEATURE_MOD_PURPOSE are only supported on Moodle 4.0 and newer.&lt;br /&gt;
&lt;br /&gt;
Customising the activity icon can be done in an alternative way. For example using the styles.css in mod/[pluginname/styles.css&lt;br /&gt;
&lt;br /&gt;
In the example below the activity plugin developer chooses to keep the coloured icon for the activity and render it as large as the coloured background on the core activities&lt;br /&gt;
 .modicon_subcourse.activityiconcontainer {&lt;br /&gt;
     background-color: transparent;&lt;br /&gt;
     padding: 0;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 .modicon_subcourse.activityiconcontainer img {&lt;br /&gt;
     width: 50px;&lt;br /&gt;
     height: 50px;&lt;br /&gt;
 }&lt;br /&gt;
To customize all icon colours use this scss array and add it to the ‘Raw initial SCSS’ in the theme Boost advanced settings page. The complete array of icon background colours can be overridden using the ‘Raw initial SCSS’ in the theme settings page. The example below changes the colours of each activity type.&lt;br /&gt;
 $activity-icon-colors: (&lt;br /&gt;
     &amp;quot;administration&amp;quot;: #5D63F6,&lt;br /&gt;
     &amp;quot;assessment&amp;quot;: #11A676,&lt;br /&gt;
     &amp;quot;collaboration&amp;quot;: #EB66A2,&lt;br /&gt;
     &amp;quot;communication&amp;quot;: #F7634D,&lt;br /&gt;
     &amp;quot;content&amp;quot;: #399BE2,&lt;br /&gt;
     &amp;quot;interface&amp;quot;: #A378FF&lt;br /&gt;
 )&lt;br /&gt;
== I&#039;m a developer, what do I need to know? ==&lt;br /&gt;
This section is a quick checklist of the areas in this document that you should consult when updating your plugin.&lt;br /&gt;
=== Modules ===&lt;br /&gt;
If you are a module developer (activity / resources) then you need to review the following updates and changes:&lt;br /&gt;
* If using settings, reformat to work with the secondary navigation. We have significantly changed the way that settings are shown. Settings added to the course and activity administration branch of the navigation are now by default shown in the secondary navigation. You will most likely find them in the more section of the secondary navigation. Please avoid creating settings in containers (a parent navigation node with children). These settings will still be shown, but this goes against the pattern that we are trying to establish for navigation around the site. If you have a lot of settings, consider creating a specific page to handle your additional settings.&lt;br /&gt;
** The order of the items in the secondary navigation may not be to your liking. This can be changed. See [[Moodle_4.0_developer_update#Changing_the_order_of_tabs|changing the order of tabs]]&lt;br /&gt;
* Update my behat tests to use new steps for site navigation. See [[Moodle_4.0_developer_update#Behat_changes|new behat steps]].&lt;br /&gt;
* Update my module to use the new activity_header API. See [[Moodle_4.0_developer_update#The_activity_header_class|the activity header]].&lt;br /&gt;
* Update my pages to make it work with the general format of the tertiary navigation. See [[Moodle_4.0_developer_update#Tertiary_navigation|the tertiary navigation]].&lt;br /&gt;
* Update my activity icon to use the API and set a purpose. See [[Moodle_4.0_developer_update#Activity_icons|activity icons]].&lt;br /&gt;
=== Themes ===&lt;br /&gt;
If you are a theme developer then you may want to consider the following:&lt;br /&gt;
* Take a look at the [[Moodle_4.0_developer_update#Navigation_changes|new navigation]] and decide if you want to incorporate this into your theme.&lt;br /&gt;
** A new layout ([[Moodle_4.0_developer_update#New_layout_page|drawers]])&lt;br /&gt;
** An [[Moodle_4.0_developer_update#Edit_switch|edit switch]]&lt;br /&gt;
** The [[Moodle_4.0_developer_update#The_course_index_element|course index]]&lt;br /&gt;
* Use of the flat nav&lt;br /&gt;
* New Site administration page and layout&lt;br /&gt;
* Course settings and how they are displayed&lt;br /&gt;
=== Course format ===&lt;br /&gt;
There have been a lot of changes made to the course format. Most in the process of moving the course format away from using the old rendering system and towards templates.&lt;br /&gt;
We recommend the following sections be read carefully:&lt;br /&gt;
# [[Moodle_4.0_developer_update#The_course_format_system|The course format]]. There have been a lot of deprecations and reading this section is critical in understanding the changes made.&lt;br /&gt;
# Consider moving the rendering of your content over to the [[Templates|template system]].&lt;br /&gt;
=== Other plugins ===&lt;br /&gt;
# Are you adding settings? See the [[Moodle_4.0_developer_update#Adding_items_to_the_navigation|secondary nav]] for adding items to this navigation bar.&lt;br /&gt;
# Have a look at [[Moodle_4.0_developer_update#Secondary_navigation|secondary]] and [[Moodle_4.0_developer_update#Tertiary_navigation|tertiary]] navigation changes in general if you have a plugin that has multiple pages to navigate around.&lt;br /&gt;
# Do you have behat tests? Check the new [[Moodle_4.0_developer_update#Behat_changes|behat changes]].&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61879</id>
		<title>Moodle 4.0 developer update</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61879"/>
		<updated>2022-03-21T23:41:41Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Theme updates: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 4.0}}This page highlights the important changes that are coming in Moodle 4.0 for developers. Including how the UX improvements impact custom themes, relevant API changes, and what you can do as developer to prepare for the 4.0 release.&lt;br /&gt;
== Navigation changes ==&lt;br /&gt;
The core Navigation API has been left mostly untouched. The callbacks to all navigation callbacks remains unchanged and will be called as part of the regular &#039;navigation&#039; and &#039;settingsnav&#039; initialisation. Some new core classes have been created and exist within a new namespace &#039;core/navigation&#039; and serves as conduit to rearrange, cherry-pick existing navigation nodes from the navigation/settingsnav trees and display within the respective navigation type. As such, it is highly recommended to provide unique keys for custom navigation nodes as this helps in the cherry-picking / rearranging process within the new classes.&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
The primary navigation(the navbar) apart from the existing content will now display links to the Dashboard, My Courses, Site Admin and Course search, by default. You can still add items to the navbar via the &#039;custom menu&#039; option. This will be displayed within the &#039;More&#039; menu. We have transitioned the menus to be rendered via templates - refer user_menu.mustache. The lang menu has been moved to reside within the user menu.&lt;br /&gt;
==== Customising the primary navigation ====&lt;br /&gt;
Not yet implemented but we are looking at allowing the full addition and removal of any of the primary navigation tabs in the boost theme config file.&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
The main content area shows tabs for secondary navigation with a maximum of 5 items being rendered in this ‘more’ menu. A new UI component has been created to render menus like this. Files:&lt;br /&gt;
 /lib/templates/moremenu.mustache&lt;br /&gt;
==== Adding items to the navigation ====&lt;br /&gt;
The secondary navigation pulls information mainly from the settings navigation node from each context. Any plugin that implements the existing navigation hooks will have their items added to the secondary navigation.&lt;br /&gt;
Existing navigation hooks:&lt;br /&gt;
* {module}_extend_navigation&lt;br /&gt;
* {local}_extend_navigation&lt;br /&gt;
* {report}_report_extend_navigation&lt;br /&gt;
* {plugin}_extend_navigation_course&lt;br /&gt;
* {plugin}_extend_navigation_category_settings&lt;br /&gt;
==== Changing the order of tabs ====&lt;br /&gt;
Apart from the previously mentioned functions, you can also create a custom secondary class as mentioned earlier. This will automatically be picked by getter and used to render the secondary nav within the activity. E.g. mod_assign/local/views/secondary. Note: This is currently only possible on an activity and block level.&lt;br /&gt;
=== Tertiary navigation ===&lt;br /&gt;
We&#039;ve moved action buttons to the top of the page. We would encourage you to do the same.&lt;br /&gt;
If you have any buttons on an activity page that go to another page, or open a form (or similar), then we encourage you to move them from the body of your activity page to the top. All of the core activities have been updated to follow this pattern. Please take a look to see how you can format your activity in a similar fashion. There is no API here. You are welcome to create the buttons and display them as you wish in this top area.&lt;br /&gt;
=== New API functions ===&lt;br /&gt;
==== Page API ====&lt;br /&gt;
* Magic getters to fetch the primary and secondary navs and the primary output.&lt;br /&gt;
* The secondarynav magic getter also checks whether a custom secondary class has been defined within the module&#039;s local\views directory. Use this if you want to deviate from the standard secondary nav structure/order.&lt;br /&gt;
&lt;br /&gt;
* set_secondarynav - Force override the secondary navigation class&lt;br /&gt;
&lt;br /&gt;
* set_secondary_navigation - Sets the ‘_hassecondarynavigation’ and optionally the ‘_hastablistsecondarynavigation’ to indicate whether a page should render the secondary navigation, and if the secondary navigation should be rendered and behave with a tablist ARIA role (as opposed to its default which is being rendered with a menubar ARIA role).&lt;br /&gt;
==== Navigationlib ====&lt;br /&gt;
* set_show_in_secondary_navigation - whether or not a node should be displayed in the secondary nav. Accepts a single boolean argument&lt;br /&gt;
* set_force_into_more_menu- whether or not to force a node into the &#039;More&#039; menu. Accepts a single boolean argument&lt;br /&gt;
==== The activity header class ====&lt;br /&gt;
There is a new activity header class that handles the display of information common to activities. 3rd party activities are not required to explicitly output this information as part of rendering individual pages.&lt;br /&gt;
&lt;br /&gt;
The common information that are currently handled by the class are:&lt;br /&gt;
* title&lt;br /&gt;
* description&lt;br /&gt;
* completion information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As part of the update it was required that the initial information to be displayed by the class be toggable at a theme and layout level. Taking this into account the following theme level configurable exists:&lt;br /&gt;
* activityheaderconfig =&amp;gt; An array that currently only enforces &#039;notitle&#039; but can be expanded in the future NOTE: Boost has this set as true by default &#039;options&#039;&lt;br /&gt;
The following layout level options that can be defined:&lt;br /&gt;
* noactivityheader - to remove the header in this specific layout.&lt;br /&gt;
* activityheader - An array that enforces the following options:&lt;br /&gt;
** notitle&lt;br /&gt;
** nocompletion&lt;br /&gt;
** nodescription&lt;br /&gt;
The class has a page level getter which you can use to fetch the current version of the class. The base state is initialised within the constructor with the completion information only fetched when data is exported for the template.&lt;br /&gt;
&lt;br /&gt;
The class has setters for the following variables which can be leveraged to modify the header for a particular page in the format set_{variable_name}:&lt;br /&gt;
* hidecompletion&lt;br /&gt;
* description&lt;br /&gt;
* title&lt;br /&gt;
Alternately, bulk operations can also be done by passing the above variables in an array to &#039;set_attrs&#039; which in turn calls the setters.&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note: Any updates to the activityheader needs to be performed before the call to $OUTPUT-&amp;gt;header&#039;&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
===== Theme updates: =====&lt;br /&gt;
With the changes in boost to incorporate the primary and secondary navigation, 3rd party themes would need to account for the following in their templates:&lt;br /&gt;
* To leverage the activity_header, it&#039;s data needs to be exported and included into the base template :&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
   {{&amp;gt; core/activity_header}}&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;** headercontent being the array element that contains the exported activity_header data&lt;br /&gt;
* It is recommended to transition towards the secondary/tertiary navigation hierarchy to reduce user cognitive load and with a logical separation of components&lt;br /&gt;
** Secondary navigation can be added to the templates by following the example https://github.com/moodle/moodle/blob/master/theme/boost/templates/columns2.mustache#L64-L68 This leverages the secondary navigation class to generate it&#039;s content.&lt;br /&gt;
* Themes that leverage the flat_navigation will still function with the additional caveat of the additional [[Moodle 4.0 developer update#Theme changes]]&lt;br /&gt;
** The themes should indicate that they do not implement secondary navigation via the page&#039;s &amp;quot;set_secondary_navigation&amp;quot; function. It is recommended to set this within the root layout file e.g. columns2&lt;br /&gt;
* In order to reintroduce the settings cog in the templates, you can introduce the following: &amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;region-main-settings-menu&amp;quot; class=&amp;quot;d-print-none {{#hasblocks}}has-blocks{{/hasblocks}}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div&amp;gt; {{{ output.region_main_settings_menu }}} &amp;lt;/div&amp;gt;            &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &lt;br /&gt;
===== Accessibility notes: =====&lt;br /&gt;
The jump to ‘maincontent’ div is now rendered within the activity header when within an activity context&lt;br /&gt;
== Component library ==&lt;br /&gt;
Each Moodle installation now ships with a Moodle User Interface (UI) Component library, a documentation system used to describe all the Bootstrap components and the custom Moodle components. The component Library is a helper tool for developers when creating user interfaces, a testing tool for theme developers and a documentation tool for core developers. The ultimate goal of having a component library is to encourage developers to create consistent user interfaces to improve Moodle’s overall user experience.&lt;br /&gt;
&lt;br /&gt;
The library contains pages with documentation about User Interface components. It contains details on how to use the component, what variations are available and the JavaScript events / options are associated with the component.&lt;br /&gt;
&lt;br /&gt;
When writing on these pages it is possible to render core mustache templates using some custom syntax like this:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; mustache template=&amp;quot;core/notification_error&amp;quot; &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; /mustache &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also call core JavaScript or use HTML examples where the html code and the rendered result are visible in the Component Library. For more info visit the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-templates/ Moodle templates] page or the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-javascript/ Moodle JavaScript] page.&lt;br /&gt;
&lt;br /&gt;
Each page in the library uses the current css from the default theme in your Moodle installation, if you have multiple themes installed and enabled the setting &amp;quot;Allow theme changes on url&amp;quot;, the component library will have a theme selector option.&lt;br /&gt;
&lt;br /&gt;
A hosted version of the Component Library can be found here. http://componentlibrary.moodle.com&lt;br /&gt;
=== Enabling the Component Library ===&lt;br /&gt;
Component library pages are written in the markdown language. These pages need to be compiled to HTML pages before the Component Library is visible. To compile the pages the server running Moodle needs to have the [[Javascript Modules#Install%20NVM%20and%20Node|JavaScript developer tools installed]] (nodeJs and Grunt)&lt;br /&gt;
&lt;br /&gt;
If your server meets all requirements you can enable the library running&lt;br /&gt;
 $ npm install&lt;br /&gt;
 $ grunt componentlibrary&lt;br /&gt;
Further installation instructions can be found in the Component Library itself.&lt;br /&gt;
=== Documenting new UI Components ===&lt;br /&gt;
There are no set rules for adding new pages in the component library yet. These rules will need to be written and adopted in the integration process for Moodle code.&lt;br /&gt;
&lt;br /&gt;
As a guideline for making this rules consideration are:&lt;br /&gt;
&lt;br /&gt;
The component library is not about single use components, for example the Moodle grade book (a huge component with many custom features). Or about very common components like buttons, these are already covered by the Bootstrap section of the component library.&lt;br /&gt;
&lt;br /&gt;
New features should be build keeping in mind the UI part needs to be customisable and if possible (and making sense) reusable. And example would be the new page drawers that we are introducing for the Navigation project. Or the custom primary navigation menus where overflowing items are pushed into a More section.&lt;br /&gt;
== Theme changes ==&lt;br /&gt;
=== Edit switch ===&lt;br /&gt;
On theme boost the “Turn editing on” and “Customise this page” buttons have been replaced by an edit switch in the top navbar. Theme Classic will keep using the old buttons. Child themes can choose to use the edit switch if the theme config.php is using this variable&lt;br /&gt;
 $THEME-&amp;gt;haseditswitch = true;&lt;br /&gt;
The languague menu, which used to be rendered in place of the custom menu has moved to the user dropdown when the user is logged in. If not logged in it will be placed next to the search / notification / messaging icon in the top navbar.&lt;br /&gt;
=== Login page ===&lt;br /&gt;
The login page has been redesigned and allows the admin to configure a background image for the login page only in the theme settings page. This change is available in both Boost and Classic. The login page still has all the features with an improved layout. &lt;br /&gt;
=== The page footer ===&lt;br /&gt;
In large screens, the page footer button is only visible when clicking a help button at the bottom right of the screen.&lt;br /&gt;
=== User initials as profile picture placeholder ===&lt;br /&gt;
If users do not upload a profile picture the user initials are displayed on a rounded gray background as a placeholder picture in the top navbar or any other page using a placeholder image. This change will be available in both Boost and Classic. &lt;br /&gt;
&lt;br /&gt;
With the introduction of this placeholder image the full username will no longer be displayed in the top navbar.&lt;br /&gt;
=== Removal of back to top link ===&lt;br /&gt;
The &amp;quot;back to top&amp;quot; link will be removed for theme boost since the new course index reduced the dependence on page scrolling. Also, the new footer is positioned where this component used to be.&lt;br /&gt;
=== Styling changes ===&lt;br /&gt;
By default rounded edges will be used for UI components, for the page header and main content area the borders will be removed. &lt;br /&gt;
=== New layout page ===&lt;br /&gt;
Theme boost now uses the drawers.php layout for the course index and blocks.&lt;br /&gt;
== Question bank changes ==&lt;br /&gt;
There was a big project to deliver [[Question bank improvements for Moodle 4.0]] which added a new plugin type for adding features to the question banks, tracking the version history for each question as it is edited (question table has been split into &amp;lt;code&amp;gt;question&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;question_versions&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_bank_entries&amp;lt;/code&amp;gt;), and tracking where each question is going to be used, with new tables &amp;lt;code&amp;gt;question_references&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_set_references&amp;lt;/code&amp;gt;. This work was done in Epic MDL-70329 if you want to track down the details of any of the core changes.&lt;br /&gt;
=== Question type plugins ===&lt;br /&gt;
Amazingly, we (Safat and colleagues at Catalyst AU) managed to implement this without breaking most question type plugins.&lt;br /&gt;
&lt;br /&gt;
However, the changes to the question bank, and the other Moodle 4.0 changes, probably broke the Behat tests for your plugin. To help with fixing that, MDL-74130 adds navigation to key question type pages (Preview and Edit for a question, and standard question bank pages like the bank itself, import and export) which should let you fix your test efficiently, and in a way that will work in all Moodle versions since 3.9.&lt;br /&gt;
&lt;br /&gt;
The &#039;most&#039; in the first paragraph here is becuase more advance question types may require more effort to fix. (For example qtype_combined which creates multi-part qusetions like the core qtype_multianswer; or qtype_pmatch or qtype_stack, which store additional data - questions tests - alongside the question itseld. How should that work with versionning?) But, if you have not done weird things like that, you are probably safe. If you find anything else that causes problems, please list it here.&lt;br /&gt;
&lt;br /&gt;
The same thing should apply to question behaviour and question import/export format plugings: no significant changes required (probably just fixing the Behat tests because of the navigation changes).&lt;br /&gt;
=== New plugin type: qbank plugins ===&lt;br /&gt;
This is not something that will cause problems for people upgrading from 3.x. Rather, it is an exciting possibility you can explore once you have survived process of upgrading to 4.0. There is a whole new plugin type which you can create to add new features to the question bank. For example extra columns, new actions and bulk actions, and so on. See [[Question_bank_plugins]].&lt;br /&gt;
=== Activities that use questions ===&lt;br /&gt;
The probable bad news is if you have an activity module which uses questions. So far, the only activity which has been fixed is mod_quiz in Moodle core, so we don&#039;t yet have a good picture of what fixes will be necessary in other activities. Work is about to start fixing [https://github.com/studentquiz/moodle-mod_studentquiz mod_studentquiz], so watching that should give more clues. As we do that, we will try to update this section of this page. Other help writing the information required here would also be greatly appreciated.&lt;br /&gt;
== The course format system ==&lt;br /&gt;
Most of the logic for rendering and editing a course has been moved to a new subsystem called courseformat. The subsystem is located in &amp;quot;course/format&amp;quot; folder so it includes all the format plugins inside. The methods and modules which are distributed between the course and the course/format folders are now rearranged or refactored to be aligned with the current Moodle coding style.&lt;br /&gt;
=== Mandatory renderer in course formats ===&lt;br /&gt;
Now format plugins renderer is not optional anymore. Legacy formats without a renderer will get a deprecation message but it will continue working however, they should create a new renderer as soon as possible. The section-based format can do it by extending the provided core_courseformat\output\section_renderer class which includes all the necessary methods.&lt;br /&gt;
=== New format base class ===&lt;br /&gt;
The old base_format class (which all plugins extend) is now renamed as core_courseformat\base. The new class provides all the functionally of the previous base_format but it has been refactored to be used as a centralized source of truth for the course rendering. Legacy formats should extend the new class to avoid the deprecation message.&lt;br /&gt;
&lt;br /&gt;
Now, the plugin format class provides information such as:&lt;br /&gt;
* If the page is displaying a single or multiple section&lt;br /&gt;
* Give access to other related format objects like the modinfo, the course record, maximum number of sections...&lt;br /&gt;
* If the format is compatible with features like course index, reactive components, ajax...&lt;br /&gt;
* Other format specifics like the page title, the default section name, default blocks...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The format instance is now the main object output components will use to render a course (see next section for more information).&lt;br /&gt;
=== New course output classes and mustache files ===&lt;br /&gt;
Traditionally, section-based course formats uses print_single_section_page and print_multiple_section_page to render the course content. In Moodle 4.0 most of the course rendering methods are migrated to output components and mustache templates. The old methods will get deprecation messages if they use the old renderer methods.&lt;br /&gt;
&lt;br /&gt;
This is an example of a format rendering a course:&amp;lt;syntaxhighlight lang=&amp;quot;php-brief&amp;quot;&amp;gt;&lt;br /&gt;
// Get the course format instance.&lt;br /&gt;
$format = course_get_format($course);&lt;br /&gt;
&lt;br /&gt;
// Get the specific format renderer.&lt;br /&gt;
$renderer = $format-&amp;gt;get_renderer($PAGE);&lt;br /&gt;
&lt;br /&gt;
if (!empty($displaysection)) {&lt;br /&gt;
    // Setup the format instance to display a single section.&lt;br /&gt;
    $format-&amp;gt;set_section_number($displaysection);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Create the ouptut instance and render it.&lt;br /&gt;
$outputclass = $format-&amp;gt;get_output_classname(&#039;content&#039;);&lt;br /&gt;
$widget = new $outputclass($format);&lt;br /&gt;
&lt;br /&gt;
echo $renderer-&amp;gt;render($widget);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Format plugins are free to use its own output classes to render a course, or they could override the existing output classes by providing their own implementation. For example, the default output for &amp;quot;content&amp;quot; (as in the previous example) is &amp;quot;core_courseformat\output\local\|content&amp;quot;, however, if the plugin has a &amp;quot;format_XXX\output\courseformat\content&amp;quot; class, the $format-&amp;gt;class the get_output_class will return the overridden one.&lt;br /&gt;
Another important update on course rendering is that now all course structure is rendered using mustache templates instead of the original html_writer methods. Now themes are able to override the course format by providing alternative versions of the mustache files. All core course templates are located in &amp;quot;course/format/templates&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All the new output classes and a guide on how to migrate the current third-party plugins will be available soon.&lt;br /&gt;
=== Course editor javascript modules and frontend components ===&lt;br /&gt;
The majority of the javascript logic related to the course editing is replaced by AMD modules. Because this is a major change in the way courses are edited and rendered, by default format plugins will continue using the previous YUI modules for now. However, formats can start using the new libraries overriding the &amp;quot;$format-&amp;gt;supports_components()&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Some Moodle 4.0 new features are only available for courses using the new editor library:&lt;br /&gt;
* Edit the course via the course index&lt;br /&gt;
* Creating sections without reloading the course page&lt;br /&gt;
* The new move section/activity modal&lt;br /&gt;
* Native browser drag&amp;amp;drop implementation&lt;br /&gt;
The new course editor uses a component-based reactive pattern to keep track of the course changes. The pattern highlights are:&lt;br /&gt;
* The main AMD module &amp;quot;core_crouseformat\courseeditor&amp;quot; maintains a data structure called state.&lt;br /&gt;
* Each UI element is implemented as a Component that observes the course state data and reacts to any data change&lt;br /&gt;
* When any reactive component needs to modify the course, it asks the course editor to execute a mutation. Mutations encapsulate all web services calls and alter the course state data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The reactive library documentation, as well as the format plugin migration guide, will be available soon.&lt;br /&gt;
=== Other course related 4.0 changes ===&lt;br /&gt;
Two new web services have been added:&lt;br /&gt;
* core_courseformat_get_state: user by the new javascript course editor to get the current course state data (containing the list of sections, activities, and other course-related data)&lt;br /&gt;
* core_courseformat_update_course: to alter the current course content. Each call returns the parts of the course state altered by the action&lt;br /&gt;
== Behat changes ==&lt;br /&gt;
=== New steps ===&lt;br /&gt;
Moodle 4.0 introduces some new behat steps.&lt;br /&gt;
&lt;br /&gt;
Sometimes you want to create a bulk number of activities. In that case you can use:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
:count :entitytype exist with the following data:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Given 100 &amp;quot;mod_lti &amp;gt; tool types&amp;quot; exist with the following data:&lt;br /&gt;
  |name        |Test tool [count]                  |&lt;br /&gt;
  |description |Example description [count]        |&lt;br /&gt;
  |baseurl     |https://www.example.com/tool[count]|&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dynamic (AJAX) tabs is a new feature contributed to Moodle 4.0 by the Workplace team (MDL-71943). You can use the following step to navigate between the tabs.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on the &amp;quot;tab title&amp;quot; dynamic tab&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To make sure that edit mode is (or is not) available on the current page, the following steps can be used.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And edit mode should be available on the current page&lt;br /&gt;
And edit mode should not be available on the current page&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are new aliases for the existing steps &amp;lt;code&amp;gt;I turn editing mode on&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;I turn editing mode off&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I switch editing mode on&lt;br /&gt;
And I switch editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to the existing step to go to a course with editing mode on, we now have the following step to do the same but with editing mode being off.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I am on &amp;quot;course full name&amp;quot; course homepage with editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step is similar to the old &amp;lt;code&amp;gt;following &amp;quot;link string&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&amp;lt;/code&amp;gt; step, with more flexibility.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;Download&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;Starter&amp;quot; &amp;quot;table_row&amp;quot; should download between &amp;quot;0&amp;quot; and &amp;quot;5000&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to hover the mouse over the trigger area.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over the &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step enables an installed plugin.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;plugin name&amp;quot; &amp;quot;plugin type&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;course_summary&amp;quot; &amp;quot;block&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following is a special variation of &#039;I click on &amp;quot;&amp;lt;page name&amp;gt;&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;page&amp;quot; &amp;quot;region&amp;quot;&#039;. It first checks to see if we are on the given page via the breadcrumb. If not we then attempt to follow the link name given.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I follow the breadcrumb &amp;quot;page name&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use the following step to ensure a node is active in the navbar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Node&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;My courses&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to navigate to a given node in the primary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select &amp;quot;Node&amp;quot; from primary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check whether an item exists in the user menu or not.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the user menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Language&amp;quot; &amp;quot;link&amp;quot; should exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check if a submenu of the user menu is shown, and if an item exists or does not exist in a given user submenu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I follow &amp;quot;Language&amp;quot; in the user menu&lt;br /&gt;
Then I should see &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English (pirate) &amp;amp;lrm;(en_ar)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add enrolment methods to courses you can use the following new step. The data that you provide in the next lines are used to fill the enrolment method form.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;enrolment method&amp;quot; in &amp;quot;course identifier&amp;quot; with:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I add &amp;quot;Self enrolment&amp;quot; enrolment method in &amp;quot;Course 1&amp;quot; with:&lt;br /&gt;
  | Custom instance name     | Test student enrolment |&lt;br /&gt;
  | Enrolment key            | moodle_rules           |&lt;br /&gt;
  | Use group enrolment keys | Yes                    |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are 3 new steps specific to the calendar component. These steps can be used to hover over a day in the mini-calendar or the full calendar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the full calendar page&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the mini-calendar block&lt;br /&gt;
And I hover over today in the mini-calendar block&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some new steps are added to question bank to be able to add comment to questions, verify the existence of a comment, and deleting comments form questions. Please note that the steps for adding comments only write the comment text in the comment field. You still need to click on the &amp;quot;Add comment&amp;quot; button to save the comment.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question preview&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question preview&lt;br /&gt;
And I should see &amp;quot;number of comments&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;number of comments&amp;quot; on the row on the comments column&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;Question bank&amp;quot; in current page administration&lt;br /&gt;
And I should see &amp;quot;0&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;0&amp;quot; on the row on the comments column&lt;br /&gt;
And I add &amp;quot;test comment 01&amp;quot; comment to question&lt;br /&gt;
And I click on &amp;quot;Add comment&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Close&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I should see &amp;quot;1&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;1&amp;quot; on the row on the comments column&lt;br /&gt;
And I delete &amp;quot;test comment 01&amp;quot; comment from question&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar to the steps for comments, the following steps are to verify the number of a question&#039;s usage and to click on it in order to open the question usage modal.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
And I click &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new steps are related to bulk actions in the question bank UI.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should not see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on &amp;quot;First question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Second question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;With selected&amp;quot; &amp;quot;button&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Delete&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;Confirm&amp;quot; &amp;quot;dialogue&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/en/Report_builder Report builder] is a new feature contributed to Moodle 4.0 by the Workplace team. The following new step is added to Moodle 4.0 to select an action from the action menu in the list of custom reports table.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I press &amp;quot;action&amp;quot; action in the &amp;quot;report name&amp;quot; report row&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There&#039;s another step related to the report builder to set a column&#039;s aggregation in the report editor.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;column title&amp;quot; column aggregation to &amp;quot;aggregation method&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;First name&amp;quot; column aggregation to &amp;quot;Comma separated values&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step needs to be used in scenarios that involve testing BigBlueButton. For this to work, you need to have a [https://github.com/moodlehq/bigbluebutton_mock BigBlueButton Mock API Server] and set &amp;lt;code&amp;gt;TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER&amp;lt;/code&amp;gt; to point to that in config.php.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And a BigBlueButton mock server is configured&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step replicates receiving a callback from the BigBlueButton server indicating the recordings for meetings are ready for viewing.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And the BigBlueButtonBN server has sent recording ready notifications&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are specific to the lesson activity. Note that in 4.0, some links (such as the &amp;quot;edit&amp;quot; and the &amp;quot;grade essays&amp;quot; links) are replaced by buttons, so you need to update your old steps with the new ones.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I edit the lesson&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;A new step is added to be used in lesson activities to edit them. This step navigates the user to the lesson edit page.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I grade lesson essays&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;It&#039;s a new step to go to the &amp;quot;Grade essays&amp;quot; page of the lesson we are currently in.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select edit type &amp;quot;edit type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Select the lesson edit type when we are in the the lesson&#039;s edit page. &amp;quot;edit type&amp;quot; can either be &amp;quot;Collapsed&amp;quot; or &amp;quot;Expanded&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new step can be used to navigate to the exports page in the course gradebook and select the specified export type from the grade exports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;export option&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;XML file&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similarly, there&#039;s a new step to navigate to the imports page in the course gradebook and select the specified import type from the grade imports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;import option&amp;quot; import page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Boost steps ===&lt;br /&gt;
In addition to the steps listed in the previous section, there are also some Boost specific steps coming with Moodle 4.0. These steps only work in Boost or Boost child themes, so you need to make sure they are not used in scenarios that may be run by non-Boost themes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step checks whether a node is active in the secondary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see :name is active in secondary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Boost theme shows the language selector menu in the primary navigation when not logged in, and within the user menu when logged in. The following steps are to check if the primary navigation includes the language selector menu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And language selector menu should exist in the navbar&lt;br /&gt;
And language selector menu should not exist in the navbar&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the following steps can be used to check whether an item exists in the language selector menu in the Boost theme.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the language selector menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Modified steps ===&lt;br /&gt;
The step &amp;lt;code&amp;gt;I change the (window|viewport) size to &amp;quot;size&amp;quot;&amp;lt;/code&amp;gt; now supports 2 new values for the size argument. The size argument now accepts &amp;lt;code&amp;gt;mobile&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;tablet&amp;lt;/code&amp;gt; values in addition to &amp;lt;code&amp;gt;small&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;medium&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;large&amp;lt;/code&amp;gt;.&lt;br /&gt;
=== Removed steps ===&lt;br /&gt;
Some behat steps are removed or replaced with new steps.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a result of some design changes, hidden or restricted activities are no longer dimmed. Therefore the step&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be dimmed&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;is now removed.&lt;br /&gt;
Depending on what you were using that step for, you may be able to use these steps:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Label name&amp;quot; label should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Activity or resource name&amp;quot;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;region-main&amp;quot; &amp;quot;region&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Other things to consider ===&lt;br /&gt;
To make behat tests more readable and easy to maintain, it is recommended to use the most direct steps to get what the test needs. It is highly recommended to use&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
instead of navigating to the activity via&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
Now that [https://docs.moodle.org/dev/Prototypes#Course_creation_improvements Course index] is integrated these behat steps&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
will fail using Boost theme.&lt;br /&gt;
&lt;br /&gt;
The reason for it is that the drawer used in Boost is hiding the course index. So when the test is trying to follow an &amp;quot;Activity name&amp;quot; link, it finds two different links:&lt;br /&gt;
* one in the course index&lt;br /&gt;
* another one in the course main content.&lt;br /&gt;
But the first one, the one in the course index, is hidden by the drawer, and the test fails.&lt;br /&gt;
&lt;br /&gt;
However the recommended behat steps&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
Old behat steps that may now fail can be updated to the new steps.&lt;br /&gt;
For example:&lt;br /&gt;
 And I am on the &amp;quot;Test assignment name&amp;quot; &amp;quot;assign activity&amp;quot; page logged in as teacher1&lt;br /&gt;
instead of:&lt;br /&gt;
 When I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
 And I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 And I follow &amp;quot;Test assignment name&amp;quot;&lt;br /&gt;
Or for settings, instead of:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I follow &amp;quot;Test choice name&amp;quot;&lt;br /&gt;
And I navigate to &amp;quot;Edit settings&amp;quot; in current page administration&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Use:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I am on the &amp;quot;Test choice name&amp;quot; &amp;quot;choice activity editing&amp;quot; page&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are also similar stream-lined navigation steps for accessing question bank pages. See MDL-74130.&lt;br /&gt;
== Other ==&lt;br /&gt;
=== Core plugins review ===&lt;br /&gt;
A few plugins from core Moodle LMS which are no longer or hardly used have been removed and, if appropriate, added to the Moodle plugins directory.&lt;br /&gt;
&lt;br /&gt;
More information about this project, the list of plugins to be removed and the process to follow for keeping them before upgrading to 4.0 can be found in the [[Core plugins review]] page.&lt;br /&gt;
=== Site admin presets plugin ===&lt;br /&gt;
The third-party plugin [https://moodle.org/plugins/block_admin_presets Admin presets], created by David Monllaó and maintained by developers from [https://pimenko.com/ Pimenko] has been adapted and integrated into Moodle 4.0. It stores settings and plugins status (enabled/disabled) in what&#039;s called &amp;quot;presets&amp;quot; to let admins quickly switch between different configurations.&lt;br /&gt;
&lt;br /&gt;
More information about this project can be found in the [[Site admin presets|Site admin presets plugin]] page.&lt;br /&gt;
=== JavaScript browser support changes ===&lt;br /&gt;
From Moodle 4.0, Internet Explorer is no longer supported. See MDL-73915 and MDLSITE-6109 for further information on this change.&lt;br /&gt;
&lt;br /&gt;
This change means that changes built on 4.0 onwards (including the master branch) will be different to older versions of Moodle.&lt;br /&gt;
&lt;br /&gt;
For plugin developers supporting multiple versions of Moodle using a single plugin version, the compiled javascript files are backwards compatible and will _work_ on all supported versions, however if you run the `grunt` command on multiple versions you will see unbuilt changes. Running grunt on all versions of Moodle is not necessary and this check can be safely disabled for Moodle versions 3.9 - 4.0, as long as only at least you run `grunt` against at least one version of Moodle.&lt;br /&gt;
&lt;br /&gt;
If you need to support Internet Explorer and do not wish to fork your plugin for Moodle 4.0 onwards, then it is recommended that you run `grunt` on an older version of Moodle.&lt;br /&gt;
=== The course index element ===&lt;br /&gt;
The new course index feature can be themed using a set of scss variables. Use them to change the look and feel instead of adding custom css&lt;br /&gt;
 /theme/boost/scss/moodle/courseindex.scss&lt;br /&gt;
With the introduction of the course index component, the previous and next links shown underneath each activity are no longer needed and they will be removed.&lt;br /&gt;
=== Activity icons ===&lt;br /&gt;
The icons used for activities have been redesigned and updated for all core moodle activities.&lt;br /&gt;
&lt;br /&gt;
When viewing the new icons in a file manager, for example for the quiz activity, you will see a simple black monochrome icon with a transparent background.&lt;br /&gt;
&lt;br /&gt;
On the course page, or in the activity chooser, the icon will display as a white icon on a coloured background. Styling of the icons on the coursepage is controlled by the css in theme/boost/scss/moodle/icons.scss.&lt;br /&gt;
&lt;br /&gt;
The background colour for activity icons is set using a new variable in function [modname]_supports(). The quiz activity is of type assessment, so in function quiz_supports() there is a new line defining the purpose:&lt;br /&gt;
 case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_ASSESSMENT;&lt;br /&gt;
Available purposes are:&lt;br /&gt;
* MOD_PURPOSE_COMMUNICATION&lt;br /&gt;
* MOD_PURPOSE_ASSESSMENT&lt;br /&gt;
* MOD_PURPOSE_COLLABORATION&lt;br /&gt;
* MOD_PURPOSE_CONTENT&lt;br /&gt;
* MOD_PURPOSE_ADMINISTRATION&lt;br /&gt;
* MOD_PURPOSE_INTERFACE&lt;br /&gt;
The background colours linked to these purposes are set in theme/boost/scss/moodle/variables.scss&lt;br /&gt;
 $activity-icon-colors: map-merge(&lt;br /&gt;
     (&lt;br /&gt;
         &amp;quot;administration&amp;quot;: #5d63f6,&lt;br /&gt;
         &amp;quot;assessment&amp;quot;: #eb66a2,&lt;br /&gt;
         &amp;quot;collaboration&amp;quot;: #f7634d,&lt;br /&gt;
         &amp;quot;communication&amp;quot;: #11a676,&lt;br /&gt;
         &amp;quot;content&amp;quot;: #399be2,&lt;br /&gt;
         &amp;quot;interface&amp;quot;: #a378ff&lt;br /&gt;
     ),&lt;br /&gt;
     $activity-icon-colors&lt;br /&gt;
 );&lt;br /&gt;
If activity plugins do not define FEATURE_MOD_PURPOSE the activity icon will be rendered against a light grey background. There is no requirement to define the purpose of activity plugins, it will only affect the icon styling.&lt;br /&gt;
&lt;br /&gt;
Plugins implementing the variable FEATURE_MOD_PURPOSE are only supported on Moodle 4.0 and newer.&lt;br /&gt;
&lt;br /&gt;
Customising the activity icon can be done in an alternative way. For example using the styles.css in mod/[pluginname/styles.css&lt;br /&gt;
&lt;br /&gt;
In the example below the activity plugin developer chooses to keep the coloured icon for the activity and render it as large as the coloured background on the core activities&lt;br /&gt;
 .modicon_subcourse.activityiconcontainer {&lt;br /&gt;
     background-color: transparent;&lt;br /&gt;
     padding: 0;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 .modicon_subcourse.activityiconcontainer img {&lt;br /&gt;
     width: 50px;&lt;br /&gt;
     height: 50px;&lt;br /&gt;
 }&lt;br /&gt;
To customize all icon colours use this scss array and add it to the ‘Raw initial SCSS’ in the theme Boost advanced settings page. The complete array of icon background colours can be overridden using the ‘Raw initial SCSS’ in the theme settings page. The example below changes the colours of each activity type.&lt;br /&gt;
 $activity-icon-colors: (&lt;br /&gt;
     &amp;quot;administration&amp;quot;: #5D63F6,&lt;br /&gt;
     &amp;quot;assessment&amp;quot;: #11A676,&lt;br /&gt;
     &amp;quot;collaboration&amp;quot;: #EB66A2,&lt;br /&gt;
     &amp;quot;communication&amp;quot;: #F7634D,&lt;br /&gt;
     &amp;quot;content&amp;quot;: #399BE2,&lt;br /&gt;
     &amp;quot;interface&amp;quot;: #A378FF&lt;br /&gt;
 )&lt;br /&gt;
== I&#039;m a developer, what do I need to know? ==&lt;br /&gt;
This section is a quick checklist of the areas in this document that you should consult when updating your plugin.&lt;br /&gt;
=== Modules ===&lt;br /&gt;
If you are a module developer (activity / resources) then you need to review the following updates and changes:&lt;br /&gt;
* If using settings, reformat to work with the secondary navigation. We have significantly changed the way that settings are shown. Settings added to the course and activity administration branch of the navigation are now by default shown in the secondary navigation. You will most likely find them in the more section of the secondary navigation. Please avoid creating settings in containers (a parent navigation node with children). These settings will still be shown, but this goes against the pattern that we are trying to establish for navigation around the site. If you have a lot of settings, consider creating a specific page to handle your additional settings.&lt;br /&gt;
** The order of the items in the secondary navigation may not be to your liking. This can be changed. See [[Moodle_4.0_developer_update#Changing_the_order_of_tabs|changing the order of tabs]]&lt;br /&gt;
* Update my behat tests to use new steps for site navigation. See [[Moodle_4.0_developer_update#Behat_changes|new behat steps]].&lt;br /&gt;
* Update my module to use the new activity_header API. See [[Moodle_4.0_developer_update#The_activity_header_class|the activity header]].&lt;br /&gt;
* Update my pages to make it work with the general format of the tertiary navigation. See [[Moodle_4.0_developer_update#Tertiary_navigation|the tertiary navigation]].&lt;br /&gt;
* Update my activity icon to use the API and set a purpose. See [[Moodle_4.0_developer_update#Activity_icons|activity icons]].&lt;br /&gt;
=== Themes ===&lt;br /&gt;
If you are a theme developer then you may want to consider the following:&lt;br /&gt;
* Take a look at the [[Moodle_4.0_developer_update#Navigation_changes|new navigation]] and decide if you want to incorporate this into your theme.&lt;br /&gt;
** A new layout ([[Moodle_4.0_developer_update#New_layout_page|drawers]])&lt;br /&gt;
** An [[Moodle_4.0_developer_update#Edit_switch|edit switch]]&lt;br /&gt;
** The [[Moodle_4.0_developer_update#The_course_index_element|course index]]&lt;br /&gt;
* Use of the flat nav&lt;br /&gt;
* New Site administration page and layout&lt;br /&gt;
* Course settings and how they are displayed&lt;br /&gt;
=== Course format ===&lt;br /&gt;
There have been a lot of changes made to the course format. Most in the process of moving the course format away from using the old rendering system and towards templates.&lt;br /&gt;
We recommend the following sections be read carefully:&lt;br /&gt;
# [[Moodle_4.0_developer_update#The_course_format_system|The course format]]. There have been a lot of deprecations and reading this section is critical in understanding the changes made.&lt;br /&gt;
# Consider moving the rendering of your content over to the [[Templates|template system]].&lt;br /&gt;
=== Other plugins ===&lt;br /&gt;
# Are you adding settings? See the [[Moodle_4.0_developer_update#Adding_items_to_the_navigation|secondary nav]] for adding items to this navigation bar.&lt;br /&gt;
# Have a look at [[Moodle_4.0_developer_update#Secondary_navigation|secondary]] and [[Moodle_4.0_developer_update#Tertiary_navigation|tertiary]] navigation changes in general if you have a plugin that has multiple pages to navigate around.&lt;br /&gt;
# Do you have behat tests? Check the new [[Moodle_4.0_developer_update#Behat_changes|behat changes]].&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61876</id>
		<title>Moodle 4.0 developer update</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61876"/>
		<updated>2022-03-21T07:08:42Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Theme updates: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 4.0}}This page highlights the important changes that are coming in Moodle 4.0 for developers. Including how the UX improvements impact custom themes, relevant API changes, and what you can do as developer to prepare for the 4.0 release.&lt;br /&gt;
== Navigation changes ==&lt;br /&gt;
The core Navigation API has been left mostly untouched. The callbacks to all navigation callbacks remains unchanged and will be called as part of the regular &#039;navigation&#039; and &#039;settingsnav&#039; initialisation. Some new core classes have been created and exist within a new namespace &#039;core/navigation&#039; and serves as conduit to rearrange, cherry-pick existing navigation nodes from the navigation/settingsnav trees and display within the respective navigation type. As such, it is highly recommended to provide unique keys for custom navigation nodes as this helps in the cherry-picking / rearranging process within the new classes.&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
The primary navigation(the navbar) apart from the existing content will now display links to the Dashboard, My Courses, Site Admin and Course search, by default. You can still add items to the navbar via the &#039;custom menu&#039; option. This will be displayed within the &#039;More&#039; menu. We have transitioned the menus to be rendered via templates - refer user_menu.mustache. The lang menu has been moved to reside within the user menu.&lt;br /&gt;
==== Customising the primary navigation ====&lt;br /&gt;
Not yet implemented but we are looking at allowing the full addition and removal of any of the primary navigation tabs in the boost theme config file.&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
The main content area shows tabs for secondary navigation with a maximum of 5 items being rendered in this ‘more’ menu. A new UI component has been created to render menus like this. Files:&lt;br /&gt;
 /lib/templates/moremenu.mustache&lt;br /&gt;
==== Adding items to the navigation ====&lt;br /&gt;
The secondary navigation pulls information mainly from the settings navigation node from each context. Any plugin that implements the existing navigation hooks will have their items added to the secondary navigation.&lt;br /&gt;
Existing navigation hooks:&lt;br /&gt;
* {module}_extend_navigation&lt;br /&gt;
* {local}_extend_navigation&lt;br /&gt;
* {report}_report_extend_navigation&lt;br /&gt;
* {plugin}_extend_navigation_course&lt;br /&gt;
* {plugin}_extend_navigation_category_settings&lt;br /&gt;
==== Changing the order of tabs ====&lt;br /&gt;
Apart from the previously mentioned functions, you can also create a custom secondary class as mentioned earlier. This will automatically be picked by getter and used to render the secondary nav within the activity. E.g. mod_assign/local/views/secondary. Note: This is currently only possible on an activity and block level.&lt;br /&gt;
=== Tertiary navigation ===&lt;br /&gt;
We&#039;ve moved action buttons to the top of the page. We would encourage you to do the same.&lt;br /&gt;
If you have any buttons on an activity page that go to another page, or open a form (or similar), then we encourage you to move them from the body of your activity page to the top. All of the core activities have been updated to follow this pattern. Please take a look to see how you can format your activity in a similar fashion. There is no API here. You are welcome to create the buttons and display them as you wish in this top area.&lt;br /&gt;
=== New API functions ===&lt;br /&gt;
==== Page API ====&lt;br /&gt;
* Magic getters to fetch the primary and secondary navs and the primary output.&lt;br /&gt;
* The secondarynav magic getter also checks whether a custom secondary class has been defined within the module&#039;s local\views directory. Use this if you want to deviate from the standard secondary nav structure/order.&lt;br /&gt;
&lt;br /&gt;
* set_secondarynav - Force override the secondary navigation class&lt;br /&gt;
&lt;br /&gt;
* set_secondary_navigation - Sets the ‘_hassecondarynavigation’ and optionally the ‘_hastablistsecondarynavigation’ to indicate whether a page should render the secondary navigation, and if the secondary navigation should be rendered and behave with a tablist ARIA role (as opposed to its default which is being rendered with a menubar ARIA role).&lt;br /&gt;
==== Navigationlib ====&lt;br /&gt;
* set_show_in_secondary_navigation - whether or not a node should be displayed in the secondary nav. Accepts a single boolean argument&lt;br /&gt;
* set_force_into_more_menu- whether or not to force a node into the &#039;More&#039; menu. Accepts a single boolean argument&lt;br /&gt;
==== The activity header class ====&lt;br /&gt;
There is a new activity header class that handles the display of information common to activities. 3rd party activities are not required to explicitly output this information as part of rendering individual pages.&lt;br /&gt;
&lt;br /&gt;
The common information that are currently handled by the class are:&lt;br /&gt;
* title&lt;br /&gt;
* description&lt;br /&gt;
* completion information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As part of the update it was required that the initial information to be displayed by the class be toggable at a theme and layout level. Taking this into account the following theme level configurable exists:&lt;br /&gt;
* activityheaderconfig =&amp;gt; An array that currently only enforces &#039;notitle&#039; but can be expanded in the future NOTE: Boost has this set as true by default &#039;options&#039;&lt;br /&gt;
The following layout level options that can be defined:&lt;br /&gt;
* noactivityheader - to remove the header in this specific layout.&lt;br /&gt;
* activityheader - An array that enforces the following options:&lt;br /&gt;
** notitle&lt;br /&gt;
** nocompletion&lt;br /&gt;
** nodescription&lt;br /&gt;
The class has a page level getter which you can use to fetch the current version of the class. The base state is initialised within the constructor with the completion information only fetched when data is exported for the template.&lt;br /&gt;
&lt;br /&gt;
The class has setters for the following variables which can be leveraged to modify the header for a particular page in the format set_{variable_name}:&lt;br /&gt;
* hidecompletion&lt;br /&gt;
* description&lt;br /&gt;
* title&lt;br /&gt;
Alternately, bulk operations can also be done by passing the above variables in an array to &#039;set_attrs&#039; which in turn calls the setters.&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note: Any updates to the activityheader needs to be performed before the call to $OUTPUT-&amp;gt;header&#039;&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
===== Theme updates: =====&lt;br /&gt;
* In order for 3rd party themes to use the class they need to export the activity_header and include the following into their base template :&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
   {{&amp;gt; core/activity_header}}&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;** headercontent being the array element that contains the exported activity_header data &lt;br /&gt;
* It is recommended for 3rd party themes to transition towards the secondary/tertiary navigation hierarchy to reduce user cognitive load and with a logical separation of components&lt;br /&gt;
** Secondary navigation can be added to the templates by following the example https://github.com/moodle/moodle/blob/master/theme/boost/templates/columns2.mustache#L64-L68 This leverages the secondary navigation class to generate it&#039;s content. &lt;br /&gt;
* Existing 3rd party themes that leverage the flat_navigation will still function with the additional caveat of the additional [[Moodle 4.0 developer update#Theme changes]]&lt;br /&gt;
** 3rd party themes should indicate that they do not implement secondary navigation via the page&#039;s &amp;quot;set_secondary_navigation&amp;quot; function. It is recommended to set this within the root layout file e.g. columns2&lt;br /&gt;
* In order to reintroduce the settings cog in 3rd party templates, you can introduce the following: &amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;region-main-settings-menu&amp;quot; class=&amp;quot;d-print-none {{#hasblocks}}has-blocks{{/hasblocks}}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div&amp;gt; {{{ output.region_main_settings_menu }}} &amp;lt;/div&amp;gt;            &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &lt;br /&gt;
===== Accessibility notes: =====&lt;br /&gt;
The jump to ‘maincontent’ div is now rendered within the activity header when within an activity context&lt;br /&gt;
== Component library ==&lt;br /&gt;
Each Moodle installation now ships with a Moodle User Interface (UI) Component library, a documentation system used to describe all the Bootstrap components and the custom Moodle components. The component Library is a helper tool for developers when creating user interfaces, a testing tool for theme developers and a documentation tool for core developers. The ultimate goal of having a component library is to encourage developers to create consistent user interfaces to improve Moodle’s overall user experience.&lt;br /&gt;
&lt;br /&gt;
The library contains pages with documentation about User Interface components. It contains details on how to use the component, what variations are available and the JavaScript events / options are associated with the component.&lt;br /&gt;
&lt;br /&gt;
When writing on these pages it is possible to render core mustache templates using some custom syntax like this:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; mustache template=&amp;quot;core/notification_error&amp;quot; &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; /mustache &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also call core JavaScript or use HTML examples where the html code and the rendered result are visible in the Component Library. For more info visit the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-templates/ Moodle templates] page or the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-javascript/ Moodle JavaScript] page.&lt;br /&gt;
&lt;br /&gt;
Each page in the library uses the current css from the default theme in your Moodle installation, if you have multiple themes installed and enabled the setting &amp;quot;Allow theme changes on url&amp;quot;, the component library will have a theme selector option.&lt;br /&gt;
&lt;br /&gt;
A hosted version of the Component Library can be found here. http://componentlibrary.moodle.com&lt;br /&gt;
=== Enabling the Component Library ===&lt;br /&gt;
Component library pages are written in the markdown language. These pages need to be compiled to HTML pages before the Component Library is visible. To compile the pages the server running Moodle needs to have the [[Javascript Modules#Install%20NVM%20and%20Node|JavaScript developer tools installed]] (nodeJs and Grunt)&lt;br /&gt;
&lt;br /&gt;
If your server meets all requirements you can enable the library running&lt;br /&gt;
 $ npm install&lt;br /&gt;
 $ grunt componentlibrary&lt;br /&gt;
Further installation instructions can be found in the Component Library itself.&lt;br /&gt;
=== Documenting new UI Components ===&lt;br /&gt;
There are no set rules for adding new pages in the component library yet. These rules will need to be written and adopted in the integration process for Moodle code.&lt;br /&gt;
&lt;br /&gt;
As a guideline for making this rules consideration are:&lt;br /&gt;
&lt;br /&gt;
The component library is not about single use components, for example the Moodle grade book (a huge component with many custom features). Or about very common components like buttons, these are already covered by the Bootstrap section of the component library.&lt;br /&gt;
&lt;br /&gt;
New features should be build keeping in mind the UI part needs to be customisable and if possible (and making sense) reusable. And example would be the new page drawers that we are introducing for the Navigation project. Or the custom primary navigation menus where overflowing items are pushed into a More section.&lt;br /&gt;
== Theme changes ==&lt;br /&gt;
=== Edit switch ===&lt;br /&gt;
On theme boost the “Turn editing on” and “Customise this page” buttons have been replaced by an edit switch in the top navbar. Theme Classic will keep using the old buttons. Child themes can choose to use the edit switch if the theme config.php is using this variable&lt;br /&gt;
 $THEME-&amp;gt;haseditswitch = true;&lt;br /&gt;
The languague menu, which used to be rendered in place of the custom menu has moved to the user dropdown when the user is logged in. If not logged in it will be placed next to the search / notification / messaging icon in the top navbar.&lt;br /&gt;
=== Login page ===&lt;br /&gt;
The login page has been redesigned and allows the admin to configure a background image for the login page only in the theme settings page. This change is available in both Boost and Classic. The login page still has all the features with an improved layout. &lt;br /&gt;
=== The page footer ===&lt;br /&gt;
In large screens, the page footer button is only visible when clicking a help button at the bottom right of the screen.&lt;br /&gt;
=== User initials as profile picture placeholder ===&lt;br /&gt;
If users do not upload a profile picture the user initials are displayed on a rounded gray background as a placeholder picture in the top navbar or any other page using a placeholder image. This change will be available in both Boost and Classic. &lt;br /&gt;
&lt;br /&gt;
With the introduction of this placeholder image the full username will no longer be displayed in the top navbar.&lt;br /&gt;
=== Removal of back to top link ===&lt;br /&gt;
The &amp;quot;back to top&amp;quot; link will be removed for theme boost since the new course index reduced the dependence on page scrolling. Also, the new footer is positioned where this component used to be.&lt;br /&gt;
=== Styling changes ===&lt;br /&gt;
By default rounded edges will be used for UI components, for the page header and main content area the borders will be removed. &lt;br /&gt;
=== New layout page ===&lt;br /&gt;
Theme boost now uses the drawers.php layout for the course index and blocks.&lt;br /&gt;
== Question bank changes ==&lt;br /&gt;
There was a big project to deliver [[Question bank improvements for Moodle 4.0]] which added a new plugin type for adding features to the question banks, tracking the version history for each question as it is edited (question table has been split into &amp;lt;code&amp;gt;question&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;question_versions&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_bank_entries&amp;lt;/code&amp;gt;), and tracking where each question is going to be used, with new tables &amp;lt;code&amp;gt;question_references&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_set_references&amp;lt;/code&amp;gt;. This work was done in Epic MDL-70329 if you want to track down the details of any of the core changes.&lt;br /&gt;
=== Question type plugins ===&lt;br /&gt;
Amazingly, we (Safat and colleagues at Catalyst AU) managed to implement this without breaking most question type plugins.&lt;br /&gt;
&lt;br /&gt;
However, the changes to the question bank, and the other Moodle 4.0 changes, probably broke the Behat tests for your plugin. To help with fixing that, MDL-74130 adds navigation to key question type pages (Preview and Edit for a question, and standard question bank pages like the bank itself, import and export) which should let you fix your test efficiently, and in a way that will work in all Moodle versions since 3.9.&lt;br /&gt;
&lt;br /&gt;
The &#039;most&#039; in the first paragraph here is becuase more advance question types may require more effort to fix. (For example qtype_combined which creates multi-part qusetions like the core qtype_multianswer; or qtype_pmatch or qtype_stack, which store additional data - questions tests - alongside the question itseld. How should that work with versionning?) But, if you have not done weird things like that, you are probably safe. If you find anything else that causes problems, please list it here.&lt;br /&gt;
&lt;br /&gt;
The same thing should apply to question behaviour and question import/export format plugings: no significant changes required (probably just fixing the Behat tests because of the navigation changes).&lt;br /&gt;
=== New plugin type: qbank plugins ===&lt;br /&gt;
This is not something that will cause problems for people upgrading from 3.x. Rather, it is an exciting possibility you can explore once you have survived process of upgrading to 4.0. There is a whole new plugin type which you can create to add new features to the question bank. For example extra columns, new actions and bulk actions, and so on. See [[Question_bank_plugins]].&lt;br /&gt;
=== Activities that use questions ===&lt;br /&gt;
The probable bad news is if you have an activity module which uses questions. So far, the only activity which has been fixed is mod_quiz in Moodle core, so we don&#039;t yet have a good picture of what fixes will be necessary in other activities. Work is about to start fixing [https://github.com/studentquiz/moodle-mod_studentquiz mod_studentquiz], so watching that should give more clues. As we do that, we will try to update this section of this page. Other help writing the information required here would also be greatly appreciated.&lt;br /&gt;
== The course format system ==&lt;br /&gt;
Most of the logic for rendering and editing a course has been moved to a new subsystem called courseformat. The subsystem is located in &amp;quot;course/format&amp;quot; folder so it includes all the format plugins inside. The methods and modules which are distributed between the course and the course/format folders are now rearranged or refactored to be aligned with the current Moodle coding style.&lt;br /&gt;
=== Mandatory renderer in course formats ===&lt;br /&gt;
Now format plugins renderer is not optional anymore. Legacy formats without a renderer will get a deprecation message but it will continue working however, they should create a new renderer as soon as possible. The section-based format can do it by extending the provided core_courseformat\output\section_renderer class which includes all the necessary methods.&lt;br /&gt;
=== New format base class ===&lt;br /&gt;
The old base_format class (which all plugins extend) is now renamed as core_courseformat\base. The new class provides all the functionally of the previous base_format but it has been refactored to be used as a centralized source of truth for the course rendering. Legacy formats should extend the new class to avoid the deprecation message.&lt;br /&gt;
&lt;br /&gt;
Now, the plugin format class provides information such as:&lt;br /&gt;
* If the page is displaying a single or multiple section&lt;br /&gt;
* Give access to other related format objects like the modinfo, the course record, maximum number of sections...&lt;br /&gt;
* If the format is compatible with features like course index, reactive components, ajax...&lt;br /&gt;
* Other format specifics like the page title, the default section name, default blocks...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The format instance is now the main object output components will use to render a course (see next section for more information).&lt;br /&gt;
=== New course output classes and mustache files ===&lt;br /&gt;
Traditionally, section-based course formats uses print_single_section_page and print_multiple_section_page to render the course content. In Moodle 4.0 most of the course rendering methods are migrated to output components and mustache templates. The old methods will get deprecation messages if they use the old renderer methods.&lt;br /&gt;
&lt;br /&gt;
This is an example of a format rendering a course:&amp;lt;syntaxhighlight lang=&amp;quot;php-brief&amp;quot;&amp;gt;&lt;br /&gt;
// Get the course format instance.&lt;br /&gt;
$format = course_get_format($course);&lt;br /&gt;
&lt;br /&gt;
// Get the specific format renderer.&lt;br /&gt;
$renderer = $format-&amp;gt;get_renderer($PAGE);&lt;br /&gt;
&lt;br /&gt;
if (!empty($displaysection)) {&lt;br /&gt;
    // Setup the format instance to display a single section.&lt;br /&gt;
    $format-&amp;gt;set_section_number($displaysection);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Create the ouptut instance and render it.&lt;br /&gt;
$outputclass = $format-&amp;gt;get_output_classname(&#039;content&#039;);&lt;br /&gt;
$widget = new $outputclass($format);&lt;br /&gt;
&lt;br /&gt;
echo $renderer-&amp;gt;render($widget);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Format plugins are free to use its own output classes to render a course, or they could override the existing output classes by providing their own implementation. For example, the default output for &amp;quot;content&amp;quot; (as in the previous example) is &amp;quot;core_courseformat\output\local\|content&amp;quot;, however, if the plugin has a &amp;quot;format_XXX\output\courseformat\content&amp;quot; class, the $format-&amp;gt;class the get_output_class will return the overridden one.&lt;br /&gt;
Another important update on course rendering is that now all course structure is rendered using mustache templates instead of the original html_writer methods. Now themes are able to override the course format by providing alternative versions of the mustache files. All core course templates are located in &amp;quot;course/format/templates&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All the new output classes and a guide on how to migrate the current third-party plugins will be available soon.&lt;br /&gt;
=== Course editor javascript modules and frontend components ===&lt;br /&gt;
The majority of the javascript logic related to the course editing is replaced by AMD modules. Because this is a major change in the way courses are edited and rendered, by default format plugins will continue using the previous YUI modules for now. However, formats can start using the new libraries overriding the &amp;quot;$format-&amp;gt;supports_components()&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Some Moodle 4.0 new features are only available for courses using the new editor library:&lt;br /&gt;
* Edit the course via the course index&lt;br /&gt;
* Creating sections without reloading the course page&lt;br /&gt;
* The new move section/activity modal&lt;br /&gt;
* Native browser drag&amp;amp;drop implementation&lt;br /&gt;
The new course editor uses a component-based reactive pattern to keep track of the course changes. The pattern highlights are:&lt;br /&gt;
* The main AMD module &amp;quot;core_crouseformat\courseeditor&amp;quot; maintains a data structure called state.&lt;br /&gt;
* Each UI element is implemented as a Component that observes the course state data and reacts to any data change&lt;br /&gt;
* When any reactive component needs to modify the course, it asks the course editor to execute a mutation. Mutations encapsulate all web services calls and alter the course state data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The reactive library documentation, as well as the format plugin migration guide, will be available soon.&lt;br /&gt;
=== Other course related 4.0 changes ===&lt;br /&gt;
Two new web services have been added:&lt;br /&gt;
* core_courseformat_get_state: user by the new javascript course editor to get the current course state data (containing the list of sections, activities, and other course-related data)&lt;br /&gt;
* core_courseformat_update_course: to alter the current course content. Each call returns the parts of the course state altered by the action&lt;br /&gt;
== Behat changes ==&lt;br /&gt;
=== New steps ===&lt;br /&gt;
Moodle 4.0 introduces some new behat steps.&lt;br /&gt;
&lt;br /&gt;
Sometimes you want to create a bulk number of activities. In that case you can use:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
:count :entitytype exist with the following data:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Given 100 &amp;quot;mod_lti &amp;gt; tool types&amp;quot; exist with the following data:&lt;br /&gt;
  |name        |Test tool [count]                  |&lt;br /&gt;
  |description |Example description [count]        |&lt;br /&gt;
  |baseurl     |https://www.example.com/tool[count]|&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dynamic (AJAX) tabs is a new feature contributed to Moodle 4.0 by the Workplace team (MDL-71943). You can use the following step to navigate between the tabs.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on the &amp;quot;tab title&amp;quot; dynamic tab&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To make sure that edit mode is (or is not) available on the current page, the following steps can be used.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And edit mode should be available on the current page&lt;br /&gt;
And edit mode should not be available on the current page&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are new aliases for the existing steps &amp;lt;code&amp;gt;I turn editing mode on&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;I turn editing mode off&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I switch editing mode on&lt;br /&gt;
And I switch editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to the existing step to go to a course with editing mode on, we now have the following step to do the same but with editing mode being off.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I am on &amp;quot;course full name&amp;quot; course homepage with editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step is similar to the old &amp;lt;code&amp;gt;following &amp;quot;link string&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&amp;lt;/code&amp;gt; step, with more flexibility.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;Download&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;Starter&amp;quot; &amp;quot;table_row&amp;quot; should download between &amp;quot;0&amp;quot; and &amp;quot;5000&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to hover the mouse over the trigger area.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over the &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step enables an installed plugin.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;plugin name&amp;quot; &amp;quot;plugin type&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;course_summary&amp;quot; &amp;quot;block&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following is a special variation of &#039;I click on &amp;quot;&amp;lt;page name&amp;gt;&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;page&amp;quot; &amp;quot;region&amp;quot;&#039;. It first checks to see if we are on the given page via the breadcrumb. If not we then attempt to follow the link name given.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I follow the breadcrumb &amp;quot;page name&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use the following step to ensure a node is active in the navbar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Node&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;My courses&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to navigate to a given node in the primary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select &amp;quot;Node&amp;quot; from primary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check whether an item exists in the user menu or not.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the user menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Language&amp;quot; &amp;quot;link&amp;quot; should exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check if a submenu of the user menu is shown, and if an item exists or does not exist in a given user submenu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I follow &amp;quot;Language&amp;quot; in the user menu&lt;br /&gt;
Then I should see &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English (pirate) &amp;amp;lrm;(en_ar)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add enrolment methods to courses you can use the following new step. The data that you provide in the next lines are used to fill the enrolment method form.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;enrolment method&amp;quot; in &amp;quot;course identifier&amp;quot; with:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I add &amp;quot;Self enrolment&amp;quot; enrolment method in &amp;quot;Course 1&amp;quot; with:&lt;br /&gt;
  | Custom instance name     | Test student enrolment |&lt;br /&gt;
  | Enrolment key            | moodle_rules           |&lt;br /&gt;
  | Use group enrolment keys | Yes                    |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are 3 new steps specific to the calendar component. These steps can be used to hover over a day in the mini-calendar or the full calendar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the full calendar page&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the mini-calendar block&lt;br /&gt;
And I hover over today in the mini-calendar block&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some new steps are added to question bank to be able to add comment to questions, verify the existence of a comment, and deleting comments form questions. Please note that the steps for adding comments only write the comment text in the comment field. You still need to click on the &amp;quot;Add comment&amp;quot; button to save the comment.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question preview&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question preview&lt;br /&gt;
And I should see &amp;quot;number of comments&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;number of comments&amp;quot; on the row on the comments column&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;Question bank&amp;quot; in current page administration&lt;br /&gt;
And I should see &amp;quot;0&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;0&amp;quot; on the row on the comments column&lt;br /&gt;
And I add &amp;quot;test comment 01&amp;quot; comment to question&lt;br /&gt;
And I click on &amp;quot;Add comment&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Close&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I should see &amp;quot;1&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;1&amp;quot; on the row on the comments column&lt;br /&gt;
And I delete &amp;quot;test comment 01&amp;quot; comment from question&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar to the steps for comments, the following steps are to verify the number of a question&#039;s usage and to click on it in order to open the question usage modal.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
And I click &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new steps are related to bulk actions in the question bank UI.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should not see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on &amp;quot;First question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Second question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;With selected&amp;quot; &amp;quot;button&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Delete&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;Confirm&amp;quot; &amp;quot;dialogue&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/en/Report_builder Report builder] is a new feature contributed to Moodle 4.0 by the Workplace team. The following new step is added to Moodle 4.0 to select an action from the action menu in the list of custom reports table.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I press &amp;quot;action&amp;quot; action in the &amp;quot;report name&amp;quot; report row&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There&#039;s another step related to the report builder to set a column&#039;s aggregation in the report editor.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;column title&amp;quot; column aggregation to &amp;quot;aggregation method&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;First name&amp;quot; column aggregation to &amp;quot;Comma separated values&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step needs to be used in scenarios that involve testing BigBlueButton. For this to work, you need to have a [https://github.com/moodlehq/bigbluebutton_mock BigBlueButton Mock API Server] and set &amp;lt;code&amp;gt;TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER&amp;lt;/code&amp;gt; to point to that in config.php.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And a BigBlueButton mock server is configured&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step replicates receiving a callback from the BigBlueButton server indicating the recordings for meetings are ready for viewing.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And the BigBlueButtonBN server has sent recording ready notifications&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are specific to the lesson activity. Note that in 4.0, some links (such as the &amp;quot;edit&amp;quot; and the &amp;quot;grade essays&amp;quot; links) are replaced by buttons, so you need to update your old steps with the new ones.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I edit the lesson&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;A new step is added to be used in lesson activities to edit them. This step navigates the user to the lesson edit page.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I grade lesson essays&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;It&#039;s a new step to go to the &amp;quot;Grade essays&amp;quot; page of the lesson we are currently in.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select edit type &amp;quot;edit type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Select the lesson edit type when we are in the the lesson&#039;s edit page. &amp;quot;edit type&amp;quot; can either be &amp;quot;Collapsed&amp;quot; or &amp;quot;Expanded&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new step can be used to navigate to the exports page in the course gradebook and select the specified export type from the grade exports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;export option&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;XML file&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similarly, there&#039;s a new step to navigate to the imports page in the course gradebook and select the specified import type from the grade imports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;import option&amp;quot; import page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Boost steps ===&lt;br /&gt;
In addition to the steps listed in the previous section, there are also some Boost specific steps coming with Moodle 4.0. These steps only work in Boost or Boost child themes, so you need to make sure they are not used in scenarios that may be run by non-Boost themes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step checks whether a node is active in the secondary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see :name is active in secondary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Boost theme shows the language selector menu in the primary navigation when not logged in, and within the user menu when logged in. The following steps are to check if the primary navigation includes the language selector menu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And language selector menu should exist in the navbar&lt;br /&gt;
And language selector menu should not exist in the navbar&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the following steps can be used to check whether an item exists in the language selector menu in the Boost theme.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the language selector menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Modified steps ===&lt;br /&gt;
The step &amp;lt;code&amp;gt;I change the (window|viewport) size to &amp;quot;size&amp;quot;&amp;lt;/code&amp;gt; now supports 2 new values for the size argument. The size argument now accepts &amp;lt;code&amp;gt;mobile&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;tablet&amp;lt;/code&amp;gt; values in addition to &amp;lt;code&amp;gt;small&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;medium&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;large&amp;lt;/code&amp;gt;.&lt;br /&gt;
=== Removed steps ===&lt;br /&gt;
Some behat steps are removed or replaced with new steps.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a result of some design changes, hidden or restricted activities are no longer dimmed. Therefore the step&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be dimmed&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;is now removed.&lt;br /&gt;
Depending on what you were using that step for, you may be able to use these steps:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Label name&amp;quot; label should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Activity or resource name&amp;quot;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;region-main&amp;quot; &amp;quot;region&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Other things to consider ===&lt;br /&gt;
To make behat tests more readable and easy to maintain, it is recommended to use the most direct steps to get what the test needs. It is highly recommended to use&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
instead of navigating to the activity via&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
Now that [https://docs.moodle.org/dev/Prototypes#Course_creation_improvements Course index] is integrated these behat steps&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
will fail using Boost theme.&lt;br /&gt;
&lt;br /&gt;
The reason for it is that the drawer used in Boost is hiding the course index. So when the test is trying to follow an &amp;quot;Activity name&amp;quot; link, it finds two different links:&lt;br /&gt;
* one in the course index&lt;br /&gt;
* another one in the course main content.&lt;br /&gt;
But the first one, the one in the course index, is hidden by the drawer, and the test fails.&lt;br /&gt;
&lt;br /&gt;
However the recommended behat steps&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
Old behat steps that may now fail can be updated to the new steps.&lt;br /&gt;
For example:&lt;br /&gt;
 And I am on the &amp;quot;Test assignment name&amp;quot; &amp;quot;assign activity&amp;quot; page logged in as teacher1&lt;br /&gt;
instead of:&lt;br /&gt;
 When I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
 And I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 And I follow &amp;quot;Test assignment name&amp;quot;&lt;br /&gt;
Or for settings, instead of:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I follow &amp;quot;Test choice name&amp;quot;&lt;br /&gt;
And I navigate to &amp;quot;Edit settings&amp;quot; in current page administration&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Use:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I am on the &amp;quot;Test choice name&amp;quot; &amp;quot;choice activity editing&amp;quot; page&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are also similar stream-lined navigation steps for accessing question bank pages. See MDL-74130.&lt;br /&gt;
== Other ==&lt;br /&gt;
=== Core plugins review ===&lt;br /&gt;
A few plugins from core Moodle LMS which are no longer or hardly used have been removed and, if appropriate, added to the Moodle plugins directory.&lt;br /&gt;
&lt;br /&gt;
More information about this project, the list of plugins to be removed and the process to follow for keeping them before upgrading to 4.0 can be found in the [[Core plugins review]] page.&lt;br /&gt;
=== Site admin presets plugin ===&lt;br /&gt;
The third-party plugin [https://moodle.org/plugins/block_admin_presets Admin presets], created by David Monllaó and maintained by developers from [https://pimenko.com/ Pimenko] has been adapted and integrated into Moodle 4.0. It stores settings and plugins status (enabled/disabled) in what&#039;s called &amp;quot;presets&amp;quot; to let admins quickly switch between different configurations.&lt;br /&gt;
&lt;br /&gt;
More information about this project can be found in the [[Site admin presets|Site admin presets plugin]] page.&lt;br /&gt;
=== JavaScript browser support changes ===&lt;br /&gt;
From Moodle 4.0, Internet Explorer is no longer supported. See MDL-73915 and MDLSITE-6109 for further information on this change.&lt;br /&gt;
&lt;br /&gt;
This change means that changes built on 4.0 onwards (including the master branch) will be different to older versions of Moodle.&lt;br /&gt;
&lt;br /&gt;
For plugin developers supporting multiple versions of Moodle using a single plugin version, the compiled javascript files are backwards compatible and will _work_ on all supported versions, however if you run the `grunt` command on multiple versions you will see unbuilt changes. Running grunt on all versions of Moodle is not necessary and this check can be safely disabled for Moodle versions 3.9 - 4.0, as long as only at least you run `grunt` against at least one version of Moodle.&lt;br /&gt;
&lt;br /&gt;
If you need to support Internet Explorer and do not wish to fork your plugin for Moodle 4.0 onwards, then it is recommended that you run `grunt` on an older version of Moodle.&lt;br /&gt;
=== The course index element ===&lt;br /&gt;
The new course index feature can be themed using a set of scss variables. Use them to change the look and feel instead of adding custom css&lt;br /&gt;
 /theme/boost/scss/moodle/courseindex.scss&lt;br /&gt;
With the introduction of the course index component, the previous and next links shown underneath each activity are no longer needed and they will be removed.&lt;br /&gt;
=== Activity icons ===&lt;br /&gt;
The icons used for activities have been redesigned and updated for all core moodle activities.&lt;br /&gt;
&lt;br /&gt;
When viewing the new icons in a file manager, for example for the quiz activity, you will see a simple black monochrome icon with a transparent background.&lt;br /&gt;
&lt;br /&gt;
On the course page, or in the activity chooser, the icon will display as a white icon on a coloured background. Styling of the icons on the coursepage is controlled by the css in theme/boost/scss/moodle/icons.scss.&lt;br /&gt;
&lt;br /&gt;
The background colour for activity icons is set using a new variable in function [modname]_supports(). The quiz activity is of type assessment, so in function quiz_supports() there is a new line defining the purpose:&lt;br /&gt;
 case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_ASSESSMENT;&lt;br /&gt;
Available purposes are:&lt;br /&gt;
* MOD_PURPOSE_COMMUNICATION&lt;br /&gt;
* MOD_PURPOSE_ASSESSMENT&lt;br /&gt;
* MOD_PURPOSE_COLLABORATION&lt;br /&gt;
* MOD_PURPOSE_CONTENT&lt;br /&gt;
* MOD_PURPOSE_ADMINISTRATION&lt;br /&gt;
* MOD_PURPOSE_INTERFACE&lt;br /&gt;
The background colours linked to these purposes are set in theme/boost/scss/moodle/variables.scss&lt;br /&gt;
 $activity-icon-colors: map-merge(&lt;br /&gt;
     (&lt;br /&gt;
         &amp;quot;administration&amp;quot;: #5d63f6,&lt;br /&gt;
         &amp;quot;assessment&amp;quot;: #eb66a2,&lt;br /&gt;
         &amp;quot;collaboration&amp;quot;: #f7634d,&lt;br /&gt;
         &amp;quot;communication&amp;quot;: #11a676,&lt;br /&gt;
         &amp;quot;content&amp;quot;: #399be2,&lt;br /&gt;
         &amp;quot;interface&amp;quot;: #a378ff&lt;br /&gt;
     ),&lt;br /&gt;
     $activity-icon-colors&lt;br /&gt;
 );&lt;br /&gt;
If activity plugins do not define FEATURE_MOD_PURPOSE the activity icon will be rendered against a light grey background. There is no requirement to define the purpose of activity plugins, it will only affect the icon styling.&lt;br /&gt;
&lt;br /&gt;
Plugins implementing the variable FEATURE_MOD_PURPOSE are only supported on Moodle 4.0 and newer.&lt;br /&gt;
&lt;br /&gt;
Customising the activity icon can be done in an alternative way. For example using the styles.css in mod/[pluginname/styles.css&lt;br /&gt;
&lt;br /&gt;
In the example below the activity plugin developer chooses to keep the coloured icon for the activity and render it as large as the coloured background on the core activities&lt;br /&gt;
 .modicon_subcourse.activityiconcontainer {&lt;br /&gt;
     background-color: transparent;&lt;br /&gt;
     padding: 0;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 .modicon_subcourse.activityiconcontainer img {&lt;br /&gt;
     width: 50px;&lt;br /&gt;
     height: 50px;&lt;br /&gt;
 }&lt;br /&gt;
To customize all icon colours use this scss array and add it to the ‘Raw initial SCSS’ in the theme Boost advanced settings page. The complete array of icon background colours can be overridden using the ‘Raw initial SCSS’ in the theme settings page. The example below changes the colours of each activity type.&lt;br /&gt;
 $activity-icon-colors: (&lt;br /&gt;
     &amp;quot;administration&amp;quot;: #5D63F6,&lt;br /&gt;
     &amp;quot;assessment&amp;quot;: #11A676,&lt;br /&gt;
     &amp;quot;collaboration&amp;quot;: #EB66A2,&lt;br /&gt;
     &amp;quot;communication&amp;quot;: #F7634D,&lt;br /&gt;
     &amp;quot;content&amp;quot;: #399BE2,&lt;br /&gt;
     &amp;quot;interface&amp;quot;: #A378FF&lt;br /&gt;
 )&lt;br /&gt;
== I&#039;m a developer, what do I need to know? ==&lt;br /&gt;
This section is a quick checklist of the areas in this document that you should consult when updating your plugin.&lt;br /&gt;
=== Modules ===&lt;br /&gt;
If you are a module developer (activity / resources) then you need to review the following updates and changes:&lt;br /&gt;
* If using settings, reformat to work with the secondary navigation. We have significantly changed the way that settings are shown. Settings added to the course and activity administration branch of the navigation are now by default shown in the secondary navigation. You will most likely find them in the more section of the secondary navigation. Please avoid creating settings in containers (a parent navigation node with children). These settings will still be shown, but this goes against the pattern that we are trying to establish for navigation around the site. If you have a lot of settings, consider creating a specific page to handle your additional settings.&lt;br /&gt;
** The order of the items in the secondary navigation may not be to your liking. This can be changed. See [[Moodle_4.0_developer_update#Changing_the_order_of_tabs|changing the order of tabs]]&lt;br /&gt;
* Update my behat tests to use new steps for site navigation. See [[Moodle_4.0_developer_update#Behat_changes|new behat steps]].&lt;br /&gt;
* Update my module to use the new activity_header API. See [[Moodle_4.0_developer_update#The_activity_header_class|the activity header]].&lt;br /&gt;
* Update my pages to make it work with the general format of the tertiary navigation. See [[Moodle_4.0_developer_update#Tertiary_navigation|the tertiary navigation]].&lt;br /&gt;
* Update my activity icon to use the API and set a purpose. See [[Moodle_4.0_developer_update#Activity_icons|activity icons]].&lt;br /&gt;
=== Themes ===&lt;br /&gt;
If you are a theme developer then you may want to consider the following:&lt;br /&gt;
* Take a look at the [[Moodle_4.0_developer_update#Navigation_changes|new navigation]] and decide if you want to incorporate this into your theme.&lt;br /&gt;
** A new layout ([[Moodle_4.0_developer_update#New_layout_page|drawers]])&lt;br /&gt;
** An [[Moodle_4.0_developer_update#Edit_switch|edit switch]]&lt;br /&gt;
** The [[Moodle_4.0_developer_update#The_course_index_element|course index]]&lt;br /&gt;
* Use of the flat nav&lt;br /&gt;
* New Site administration page and layout&lt;br /&gt;
* Course settings and how they are displayed&lt;br /&gt;
=== Course format ===&lt;br /&gt;
There have been a lot of changes made to the course format. Most in the process of moving the course format away from using the old rendering system and towards templates.&lt;br /&gt;
We recommend the following sections be read carefully:&lt;br /&gt;
# [[Moodle_4.0_developer_update#The_course_format_system|The course format]]. There have been a lot of deprecations and reading this section is critical in understanding the changes made.&lt;br /&gt;
# Consider moving the rendering of your content over to the [[Templates|template system]].&lt;br /&gt;
=== Other plugins ===&lt;br /&gt;
# Are you adding settings? See the [[Moodle_4.0_developer_update#Adding_items_to_the_navigation|secondary nav]] for adding items to this navigation bar.&lt;br /&gt;
# Have a look at [[Moodle_4.0_developer_update#Secondary_navigation|secondary]] and [[Moodle_4.0_developer_update#Tertiary_navigation|tertiary]] navigation changes in general if you have a plugin that has multiple pages to navigate around.&lt;br /&gt;
# Do you have behat tests? Check the new [[Moodle_4.0_developer_update#Behat_changes|behat changes]].&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61856</id>
		<title>Moodle 4.0 developer update</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61856"/>
		<updated>2022-03-18T07:05:55Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Theme updates: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 4.0}}This page highlights the important changes that are coming in Moodle 4.0 for developers. Including how the UX improvements impact custom themes, relevant API changes, and what you can do as developer to prepare for the 4.0 release.&lt;br /&gt;
== Navigation changes ==&lt;br /&gt;
The core Navigation API has been left mostly untouched. The callbacks to all navigation callbacks remains unchanged and will be called as part of the regular &#039;navigation&#039; and &#039;settingsnav&#039; initialisation. Some new core classes have been created and exist within a new namespace &#039;core/navigation&#039; and serves as conduit to rearrange, cherry-pick existing navigation nodes from the navigation/settingsnav trees and display within the respective navigation type. As such, it is highly recommended to provide unique keys for custom navigation nodes as this helps in the cherry-picking / rearranging process within the new classes.&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
The primary navigation(the navbar) apart from the existing content will now display links to the Dashboard, My Courses, Site Admin and Course search, by default. You can still add items to the navbar via the &#039;custom menu&#039; option. This will be displayed within the &#039;More&#039; menu. We have transitioned the menus to be rendered via templates - refer user_menu.mustache. The lang menu has been moved to reside within the user menu.&lt;br /&gt;
==== Customising the primary navigation ====&lt;br /&gt;
Not yet implemented but we are looking at allowing the full addition and removal of any of the primary navigation tabs in the boost theme config file.&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
The main content area shows tabs for secondary navigation with a maximum of 5 items being rendered in this ‘more’ menu. A new UI component has been created to render menus like this. Files:&lt;br /&gt;
 /lib/templates/moremenu.mustache&lt;br /&gt;
==== Adding items to the navigation ====&lt;br /&gt;
The secondary navigation pulls information mainly from the settings navigation node from each context. Any plugin that implements the existing navigation hooks will have their items added to the secondary navigation.&lt;br /&gt;
Existing navigation hooks:&lt;br /&gt;
* {module}_extend_navigation&lt;br /&gt;
* {local}_extend_navigation&lt;br /&gt;
* {report}_report_extend_navigation&lt;br /&gt;
* {plugin}_extend_navigation_course&lt;br /&gt;
* {plugin}_extend_navigation_category_settings&lt;br /&gt;
==== Changing the order of tabs ====&lt;br /&gt;
Apart from the previously mentioned functions, you can also create a custom secondary class as mentioned earlier. This will automatically be picked by getter and used to render the secondary nav within the activity. E.g. mod_assign/local/views/secondary. Note: This is currently only possible on an activity and block level.&lt;br /&gt;
=== Tertiary navigation ===&lt;br /&gt;
We&#039;ve moved action buttons to the top of the page. We would encourage you to do the same.&lt;br /&gt;
If you have any buttons on an activity page that go to another page, or open a form (or similar), then we encourage you to move them from the body of your activity page to the top. All of the core activities have been updated to follow this pattern. Please take a look to see how you can format your activity in a similar fashion. There is no API here. You are welcome to create the buttons and display them as you wish in this top area.&lt;br /&gt;
=== New API functions ===&lt;br /&gt;
==== Page API ====&lt;br /&gt;
* Magic getters to fetch the primary and secondary navs and the primary output.&lt;br /&gt;
* The secondarynav magic getter also checks whether a custom secondary class has been defined within the module&#039;s local\views directory. Use this if you want to deviate from the standard secondary nav structure/order.&lt;br /&gt;
&lt;br /&gt;
* set_secondarynav - Force override the secondary navigation class&lt;br /&gt;
&lt;br /&gt;
* set_secondary_navigation - Sets the ‘_hassecondarynavigation’ and optionally the ‘_hastablistsecondarynavigation’ to indicate whether a page should render the secondary navigation, and if the secondary navigation should be rendered and behave with a tablist ARIA role (as opposed to its default which is being rendered with a menubar ARIA role).&lt;br /&gt;
==== Navigationlib ====&lt;br /&gt;
* set_show_in_secondary_navigation - whether or not a node should be displayed in the secondary nav. Accepts a single boolean argument&lt;br /&gt;
* set_force_into_more_menu- whether or not to force a node into the &#039;More&#039; menu. Accepts a single boolean argument&lt;br /&gt;
==== The activity header class ====&lt;br /&gt;
There is a new activity header class that handles the display of information common to activities. 3rd party activities are not required to explicitly output this information as part of rendering individual pages.&lt;br /&gt;
&lt;br /&gt;
The common information that are currently handled by the class are:&lt;br /&gt;
* title&lt;br /&gt;
* description&lt;br /&gt;
* completion information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As part of the update it was required that the initial information to be displayed by the class be toggable at a theme and layout level. Taking this into account the following theme level configurable exists:&lt;br /&gt;
* activityheaderconfig =&amp;gt; An array that currently only enforces &#039;notitle&#039; but can be expanded in the future NOTE: Boost has this set as true by default &#039;options&#039;&lt;br /&gt;
The following layout level options that can be defined:&lt;br /&gt;
* noactivityheader - to remove the header in this specific layout.&lt;br /&gt;
* activityheader - An array that enforces the following options:&lt;br /&gt;
** notitle&lt;br /&gt;
** nocompletion&lt;br /&gt;
** nodescription&lt;br /&gt;
The class has a page level getter which you can use to fetch the current version of the class. The base state is initialised within the constructor with the completion information only fetched when data is exported for the template.&lt;br /&gt;
&lt;br /&gt;
The class has setters for the following variables which can be leveraged to modify the header for a particular page in the format set_{variable_name}:&lt;br /&gt;
* hidecompletion&lt;br /&gt;
* description&lt;br /&gt;
* title&lt;br /&gt;
Alternately, bulk operations can also be done by passing the above variables in an array to &#039;set_attrs&#039; which in turn calls the setters.&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note: Any updates to the activityheader needs to be performed before the call to $OUTPUT-&amp;gt;header&#039;&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
===== Theme updates: =====&lt;br /&gt;
&lt;br /&gt;
* In order for 3rd party themes to use the class they need to export the activity_header and include the following into their base template :&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
   {{&amp;gt; core/activity_header}}&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;** headercontent being the array element that contains the exported activity_header data &lt;br /&gt;
* It is recommended for 3rd party themes to transition towards the secondary/tertiary navigation hierarchy to reduce user cognitive load and with a logical separation of components&lt;br /&gt;
** Secondary navigation can be added to the templates by following the example https://github.com/moodle/moodle/blob/master/theme/boost/templates/columns2.mustache#L64-L68 This leverages the secondary navigation class to generate it&#039;s content. &lt;br /&gt;
* Existing 3rd party themes that leverage the flat_navigation will still function with the additional caveat of the additional [[Moodle 4.0 developer update#Theme changes]] &lt;br /&gt;
* In order to reintroduce the settings cog in 3rd party templates, you can introduce the following:  &amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;region-main-settings-menu&amp;quot; class=&amp;quot;d-print-none {{#hasblocks}}has-blocks{{/hasblocks}}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div&amp;gt; {{{ output.region_main_settings_menu }}} &amp;lt;/div&amp;gt;            &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
===== Accessibility notes: =====&lt;br /&gt;
The jump to ‘maincontent’ div is now rendered within the activity header when within an activity context&lt;br /&gt;
== Component library ==&lt;br /&gt;
Each Moodle installation now ships with a Moodle User Interface (UI) Component library, a documentation system used to describe all the Bootstrap components and the custom Moodle components. The component Library is a helper tool for developers when creating user interfaces, a testing tool for theme developers and a documentation tool for core developers. The ultimate goal of having a component library is to encourage developers to create consistent user interfaces to improve Moodle’s overall user experience.&lt;br /&gt;
&lt;br /&gt;
The library contains pages with documentation about User Interface components. It contains details on how to use the component, what variations are available and the JavaScript events / options are associated with the component.&lt;br /&gt;
&lt;br /&gt;
When writing on these pages it is possible to render core mustache templates using some custom syntax like this:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; mustache template=&amp;quot;core/notification_error&amp;quot; &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; /mustache &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also call core JavaScript or use HTML examples where the html code and the rendered result are visible in the Component Library. For more info visit the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-templates/ Moodle templates] page or the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-javascript/ Moodle JavaScript] page.&lt;br /&gt;
&lt;br /&gt;
Each page in the library uses the current css from the default theme in your Moodle installation, if you have multiple themes installed and enabled the setting &amp;quot;Allow theme changes on url&amp;quot;, the component library will have a theme selector option.&lt;br /&gt;
&lt;br /&gt;
A hosted version of the Component Library can be found here. http://componentlibrary.moodle.com&lt;br /&gt;
=== Enabling the Component Library ===&lt;br /&gt;
Component library pages are written in the markdown language. These pages need to be compiled to HTML pages before the Component Library is visible. To compile the pages the server running Moodle needs to have the [[Javascript Modules#Install%20NVM%20and%20Node|JavaScript developer tools installed]] (nodeJs and Grunt)&lt;br /&gt;
&lt;br /&gt;
If your server meets all requirements you can enable the library running&lt;br /&gt;
 $ npm install&lt;br /&gt;
 $ grunt componentlibrary&lt;br /&gt;
Further installation instructions can be found in the Component Library itself.&lt;br /&gt;
=== Documenting new UI Components ===&lt;br /&gt;
There are no set rules for adding new pages in the component library yet. These rules will need to be written and adopted in the integration process for Moodle code.&lt;br /&gt;
&lt;br /&gt;
As a guideline for making this rules consideration are:&lt;br /&gt;
&lt;br /&gt;
The component library is not about single use components, for example the Moodle grade book (a huge component with many custom features). Or about very common components like buttons, these are already covered by the Bootstrap section of the component library.&lt;br /&gt;
&lt;br /&gt;
New features should be build keeping in mind the UI part needs to be customisable and if possible (and making sense) reusable. And example would be the new page drawers that we are introducing for the Navigation project. Or the custom primary navigation menus where overflowing items are pushed into a More section.&lt;br /&gt;
== Theme changes ==&lt;br /&gt;
=== Edit switch ===&lt;br /&gt;
On theme boost the “Turn editing on” and “Customise this page” buttons have been replaced by an edit switch in the top navbar. Theme Classic will keep using the old buttons. Child themes can choose to use the edit switch if the theme config.php is using this variable&lt;br /&gt;
 $THEME-&amp;gt;haseditswitch = true;&lt;br /&gt;
The languague menu, which used to be rendered in place of the custom menu has moved to the user dropdown when the user is logged in. If not logged in it will be placed next to the search / notification / messaging icon in the top navbar.&lt;br /&gt;
=== Login page ===&lt;br /&gt;
The login page has been redesigned and allows the admin to configure a background image for the login page only in the theme settings page. This change is available in both Boost and Classic. The login page still has all the features with an improved layout. &lt;br /&gt;
=== The page footer ===&lt;br /&gt;
In large screens, the page footer button is only visible when clicking a help button at the bottom right of the screen.&lt;br /&gt;
=== User initials as profile picture placeholder ===&lt;br /&gt;
If users do not upload a profile picture the user initials are displayed on a rounded gray background as a placeholder picture in the top navbar or any other page using a placeholder image. This change will be available in both Boost and Classic. &lt;br /&gt;
&lt;br /&gt;
With the introduction of this placeholder image the full username will no longer be displayed in the top navbar.&lt;br /&gt;
=== Removal of back to top link ===&lt;br /&gt;
The &amp;quot;back to top&amp;quot; link will be removed for theme boost since the new course index reduced the dependence on page scrolling. Also, the new footer is positioned where this component used to be.&lt;br /&gt;
=== Styling changes ===&lt;br /&gt;
By default rounded edges will be used for UI components, for the page header and main content area the borders will be removed. &lt;br /&gt;
=== New layout page ===&lt;br /&gt;
Theme boost now uses the drawers.php layout for the course index and blocks.&lt;br /&gt;
== Question bank changes ==&lt;br /&gt;
There was a big project to deliver [[Question bank improvements for Moodle 4.0]] which added a new plugin type for adding features to the question banks, tracking the version history for each question as it is edited (question table has been split into &amp;lt;code&amp;gt;question&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;question_versions&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_bank_entries&amp;lt;/code&amp;gt;), and tracking where each question is going to be used, with new tables &amp;lt;code&amp;gt;question_references&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_set_references&amp;lt;/code&amp;gt;. This work was done in Epic MDL-70329 if you want to track down the details of any of the core changes.&lt;br /&gt;
=== Question type plugins ===&lt;br /&gt;
Amazingly, we (Safat and colleagues at Catalyst AU) managed to implement this without breaking most question type plugins.&lt;br /&gt;
&lt;br /&gt;
However, the changes to the question bank, and the other Moodle 4.0 changes, probably broke the Behat tests for your plugin. To help with fixing that, MDL-74130 adds navigation to key question type pages (Preview and Edit for a question, and standard question bank pages like the bank itself, import and export) which should let you fix your test efficiently, and in a way that will work in all Moodle versions since 3.9.&lt;br /&gt;
&lt;br /&gt;
The &#039;most&#039; in the first paragraph here is becuase more advance question types may require more effort to fix. (For example qtype_combined which creates multi-part qusetions like the core qtype_multianswer; or qtype_pmatch or qtype_stack, which store additional data - questions tests - alongside the question itseld. How should that work with versionning?) But, if you have not done weird things like that, you are probably safe. If you find anything else that causes problems, please list it here.&lt;br /&gt;
&lt;br /&gt;
The same thing should apply to question behaviour and question import/export format plugings: no significant changes required (probably just fixing the Behat tests because of the navigation changes).&lt;br /&gt;
=== New plugin type: qbank plugins ===&lt;br /&gt;
This is not something that will cause problems for people upgrading from 3.x. Rather, it is an exciting possibility you can explore once you have survived process of upgrading to 4.0. There is a whole new plugin type which you can create to add new features to the question bank. For example extra columns, new actions and bulk actions, and so on. See [[Question_bank_plugins]].&lt;br /&gt;
=== Activities that use questions ===&lt;br /&gt;
The probable bad news is if you have an activity module which uses questions. So far, the only activity which has been fixed is mod_quiz in Moodle core, so we don&#039;t yet have a good picture of what fixes will be necessary in other activities. Work is about to start fixing [https://github.com/studentquiz/moodle-mod_studentquiz mod_studentquiz], so watching that should give more clues. As we do that, we will try to update this section of this page. Other help writing the information required here would also be greatly appreciated.&lt;br /&gt;
== The course format system ==&lt;br /&gt;
Most of the logic for rendering and editing a course has been moved to a new subsystem called courseformat. The subsystem is located in &amp;quot;course/format&amp;quot; folder so it includes all the format plugins inside. The methods and modules which are distributed between the course and the course/format folders are now rearranged or refactored to be aligned with the current Moodle coding style.&lt;br /&gt;
=== Mandatory renderer in course formats ===&lt;br /&gt;
Now format plugins renderer is not optional anymore. Legacy formats without a renderer will get a deprecation message but it will continue working however, they should create a new renderer as soon as possible. The section-based format can do it by extending the provided core_courseformat\output\section_renderer class which includes all the necessary methods.&lt;br /&gt;
=== New format base class ===&lt;br /&gt;
The old base_format class (which all plugins extend) is now renamed as core_courseformat\base. The new class provides all the functionally of the previous base_format but it has been refactored to be used as a centralized source of truth for the course rendering. Legacy formats should extend the new class to avoid the deprecation message.&lt;br /&gt;
&lt;br /&gt;
Now, the plugin format class provides information such as:&lt;br /&gt;
* If the page is displaying a single or multiple section&lt;br /&gt;
* Give access to other related format objects like the modinfo, the course record, maximum number of sections...&lt;br /&gt;
* If the format is compatible with features like course index, reactive components, ajax...&lt;br /&gt;
* Other format specifics like the page title, the default section name, default blocks...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The format instance is now the main object output components will use to render a course (see next section for more information).&lt;br /&gt;
=== New course output classes and mustache files ===&lt;br /&gt;
Traditionally, section-based course formats uses print_single_section_page and print_multiple_section_page to render the course content. In Moodle 4.0 most of the course rendering methods are migrated to output components and mustache templates. The old methods will get deprecation messages if they use the old renderer methods.&lt;br /&gt;
&lt;br /&gt;
This is an example of a format rendering a course:&amp;lt;syntaxhighlight lang=&amp;quot;php-brief&amp;quot;&amp;gt;&lt;br /&gt;
// Get the course format instance.&lt;br /&gt;
$format = course_get_format($course);&lt;br /&gt;
&lt;br /&gt;
// Get the specific format renderer.&lt;br /&gt;
$renderer = $format-&amp;gt;get_renderer($PAGE);&lt;br /&gt;
&lt;br /&gt;
if (!empty($displaysection)) {&lt;br /&gt;
    // Setup the format instance to display a single section.&lt;br /&gt;
    $format-&amp;gt;set_section_number($displaysection);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Create the ouptut instance and render it.&lt;br /&gt;
$outputclass = $format-&amp;gt;get_output_classname(&#039;content&#039;);&lt;br /&gt;
$widget = new $outputclass($format);&lt;br /&gt;
&lt;br /&gt;
echo $renderer-&amp;gt;render($widget);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Format plugins are free to use its own output classes to render a course, or they could override the existing output classes by providing their own implementation. For example, the default output for &amp;quot;content&amp;quot; (as in the previous example) is &amp;quot;core_courseformat\output\local\|content&amp;quot;, however, if the plugin has a &amp;quot;format_XXX\output\courseformat\content&amp;quot; class, the $format-&amp;gt;class the get_output_class will return the overridden one.&lt;br /&gt;
Another important update on course rendering is that now all course structure is rendered using mustache templates instead of the original html_writer methods. Now themes are able to override the course format by providing alternative versions of the mustache files. All core course templates are located in &amp;quot;course/format/templates&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All the new output classes and a guide on how to migrate the current third-party plugins will be available soon.&lt;br /&gt;
=== Course editor javascript modules and frontend components ===&lt;br /&gt;
The majority of the javascript logic related to the course editing is replaced by AMD modules. Because this is a major change in the way courses are edited and rendered, by default format plugins will continue using the previous YUI modules for now. However, formats can start using the new libraries overriding the &amp;quot;$format-&amp;gt;supports_components()&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Some Moodle 4.0 new features are only available for courses using the new editor library:&lt;br /&gt;
* Edit the course via the course index&lt;br /&gt;
* Creating sections without reloading the course page&lt;br /&gt;
* The new move section/activity modal&lt;br /&gt;
* Native browser drag&amp;amp;drop implementation&lt;br /&gt;
The new course editor uses a component-based reactive pattern to keep track of the course changes. The pattern highlights are:&lt;br /&gt;
* The main AMD module &amp;quot;core_crouseformat\courseeditor&amp;quot; maintains a data structure called state.&lt;br /&gt;
* Each UI element is implemented as a Component that observes the course state data and reacts to any data change&lt;br /&gt;
* When any reactive component needs to modify the course, it asks the course editor to execute a mutation. Mutations encapsulate all web services calls and alter the course state data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The reactive library documentation, as well as the format plugin migration guide, will be available soon.&lt;br /&gt;
=== Other course related 4.0 changes ===&lt;br /&gt;
Two new web services have been added:&lt;br /&gt;
* core_courseformat_get_state: user by the new javascript course editor to get the current course state data (containing the list of sections, activities, and other course-related data)&lt;br /&gt;
* core_courseformat_update_course: to alter the current course content. Each call returns the parts of the course state altered by the action&lt;br /&gt;
== Behat changes ==&lt;br /&gt;
=== New steps ===&lt;br /&gt;
Moodle 4.0 introduces some new behat steps.&lt;br /&gt;
&lt;br /&gt;
Sometimes you want to create a bulk number of activities. In that case you can use:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
:count :entitytype exist with the following data:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Given 100 &amp;quot;mod_lti &amp;gt; tool types&amp;quot; exist with the following data:&lt;br /&gt;
  |name        |Test tool [count]                  |&lt;br /&gt;
  |description |Example description [count]        |&lt;br /&gt;
  |baseurl     |https://www.example.com/tool[count]|&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dynamic (AJAX) tabs is a new feature contributed to Moodle 4.0 by the Workplace team (MDL-71943). You can use the following step to navigate between the tabs.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on the &amp;quot;tab title&amp;quot; dynamic tab&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To make sure that edit mode is (or is not) available on the current page, the following steps can be used.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And edit mode should be available on the current page&lt;br /&gt;
And edit mode should not be available on the current page&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are new aliases for the existing steps &amp;lt;code&amp;gt;I turn editing mode on&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;I turn editing mode off&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I switch editing mode on&lt;br /&gt;
And I switch editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to the existing step to go to a course with editing mode on, we now have the following step to do the same but with editing mode being off.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I am on &amp;quot;course full name&amp;quot; course homepage with editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step is similar to the old &amp;lt;code&amp;gt;following &amp;quot;link string&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&amp;lt;/code&amp;gt; step, with more flexibility.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;Download&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;Starter&amp;quot; &amp;quot;table_row&amp;quot; should download between &amp;quot;0&amp;quot; and &amp;quot;5000&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to hover the mouse over the trigger area.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over the &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step enables an installed plugin.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;plugin name&amp;quot; &amp;quot;plugin type&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;course_summary&amp;quot; &amp;quot;block&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following is a special variation of &#039;I click on &amp;quot;&amp;lt;page name&amp;gt;&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;page&amp;quot; &amp;quot;region&amp;quot;&#039;. It first checks to see if we are on the given page via the breadcrumb. If not we then attempt to follow the link name given.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I follow the breadcrumb &amp;quot;page name&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use the following step to ensure a node is active in the navbar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Node&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;My courses&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to navigate to a given node in the primary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select &amp;quot;Node&amp;quot; from primary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check whether an item exists in the user menu or not.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the user menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Language&amp;quot; &amp;quot;link&amp;quot; should exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check if a submenu of the user menu is shown, and if an item exists or does not exist in a given user submenu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I follow &amp;quot;Language&amp;quot; in the user menu&lt;br /&gt;
Then I should see &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English (pirate) &amp;amp;lrm;(en_ar)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add enrolment methods to courses you can use the following new step. The data that you provide in the next lines are used to fill the enrolment method form.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;enrolment method&amp;quot; in &amp;quot;course identifier&amp;quot; with:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I add &amp;quot;Self enrolment&amp;quot; enrolment method in &amp;quot;Course 1&amp;quot; with:&lt;br /&gt;
  | Custom instance name     | Test student enrolment |&lt;br /&gt;
  | Enrolment key            | moodle_rules           |&lt;br /&gt;
  | Use group enrolment keys | Yes                    |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are 3 new steps specific to the calendar component. These steps can be used to hover over a day in the mini-calendar or the full calendar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the full calendar page&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the mini-calendar block&lt;br /&gt;
And I hover over today in the mini-calendar block&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some new steps are added to question bank to be able to add comment to questions, verify the existence of a comment, and deleting comments form questions. Please note that the steps for adding comments only write the comment text in the comment field. You still need to click on the &amp;quot;Add comment&amp;quot; button to save the comment.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question preview&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question preview&lt;br /&gt;
And I should see &amp;quot;number of comments&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;number of comments&amp;quot; on the row on the comments column&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;Question bank&amp;quot; in current page administration&lt;br /&gt;
And I should see &amp;quot;0&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;0&amp;quot; on the row on the comments column&lt;br /&gt;
And I add &amp;quot;test comment 01&amp;quot; comment to question&lt;br /&gt;
And I click on &amp;quot;Add comment&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Close&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I should see &amp;quot;1&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;1&amp;quot; on the row on the comments column&lt;br /&gt;
And I delete &amp;quot;test comment 01&amp;quot; comment from question&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar to the steps for comments, the following steps are to verify the number of a question&#039;s usage and to click on it in order to open the question usage modal.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
And I click &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new steps are related to bulk actions in the question bank UI.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should not see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on &amp;quot;First question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Second question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;With selected&amp;quot; &amp;quot;button&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Delete&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;Confirm&amp;quot; &amp;quot;dialogue&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/en/Report_builder Report builder] is a new feature contributed to Moodle 4.0 by the Workplace team. The following new step is added to Moodle 4.0 to select an action from the action menu in the list of custom reports table.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I press &amp;quot;action&amp;quot; action in the &amp;quot;report name&amp;quot; report row&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There&#039;s another step related to the report builder to set a column&#039;s aggregation in the report editor.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;column title&amp;quot; column aggregation to &amp;quot;aggregation method&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;First name&amp;quot; column aggregation to &amp;quot;Comma separated values&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step needs to be used in scenarios that involve testing BigBlueButton. For this to work, you need to have a [https://github.com/moodlehq/bigbluebutton_mock BigBlueButton Mock API Server] and set &amp;lt;code&amp;gt;TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER&amp;lt;/code&amp;gt; to point to that in config.php.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And a BigBlueButton mock server is configured&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step replicates receiving a callback from the BigBlueButton server indicating the recordings for meetings are ready for viewing.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And the BigBlueButtonBN server has sent recording ready notifications&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are specific to the lesson activity. Note that in 4.0, some links (such as the &amp;quot;edit&amp;quot; and the &amp;quot;grade essays&amp;quot; links) are replaced by buttons, so you need to update your old steps with the new ones.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I edit the lesson&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;A new step is added to be used in lesson activities to edit them. This step navigates the user to the lesson edit page.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I grade lesson essays&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;It&#039;s a new step to go to the &amp;quot;Grade essays&amp;quot; page of the lesson we are currently in.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select edit type &amp;quot;edit type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Select the lesson edit type when we are in the the lesson&#039;s edit page. &amp;quot;edit type&amp;quot; can either be &amp;quot;Collapsed&amp;quot; or &amp;quot;Expanded&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new step can be used to navigate to the exports page in the course gradebook and select the specified export type from the grade exports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;export option&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;XML file&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similarly, there&#039;s a new step to navigate to the imports page in the course gradebook and select the specified import type from the grade imports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;import option&amp;quot; import page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Boost steps ===&lt;br /&gt;
In addition to the steps listed in the previous section, there are also some Boost specific steps coming with Moodle 4.0. These steps only work in Boost or Boost child themes, so you need to make sure they are not used in scenarios that may be run by non-Boost themes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step checks whether a node is active in the secondary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see :name is active in secondary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Boost theme shows the language selector menu in the primary navigation when not logged in, and within the user menu when logged in. The following steps are to check if the primary navigation includes the language selector menu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And language selector menu should exist in the navbar&lt;br /&gt;
And language selector menu should not exist in the navbar&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the following steps can be used to check whether an item exists in the language selector menu in the Boost theme.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the language selector menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Modified steps ===&lt;br /&gt;
The step &amp;lt;code&amp;gt;I change the (window|viewport) size to &amp;quot;size&amp;quot;&amp;lt;/code&amp;gt; now supports 2 new values for the size argument. The size argument now accepts &amp;lt;code&amp;gt;mobile&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;tablet&amp;lt;/code&amp;gt; values in addition to &amp;lt;code&amp;gt;small&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;medium&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;large&amp;lt;/code&amp;gt;.&lt;br /&gt;
=== Removed steps ===&lt;br /&gt;
Some behat steps are removed or replaced with new steps.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a result of some design changes, hidden or restricted activities are no longer dimmed. Therefore the step&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be dimmed&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;is now removed.&lt;br /&gt;
Depending on what you were using that step for, you may be able to use these steps:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Label name&amp;quot; label should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Activity or resource name&amp;quot;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;region-main&amp;quot; &amp;quot;region&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Other things to consider ===&lt;br /&gt;
To make behat tests more readable and easy to maintain, it is recommended to use the most direct steps to get what the test needs. It is highly recommended to use&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
instead of navigating to the activity via&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
Now that [https://docs.moodle.org/dev/Prototypes#Course_creation_improvements Course index] is integrated these behat steps&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
will fail using Boost theme.&lt;br /&gt;
&lt;br /&gt;
The reason for it is that the drawer used in Boost is hiding the course index. So when the test is trying to follow an &amp;quot;Activity name&amp;quot; link, it finds two different links:&lt;br /&gt;
* one in the course index&lt;br /&gt;
* another one in the course main content.&lt;br /&gt;
But the first one, the one in the course index, is hidden by the drawer, and the test fails.&lt;br /&gt;
&lt;br /&gt;
However the recommended behat steps&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
Old behat steps that may now fail can be updated to the new steps.&lt;br /&gt;
For example:&lt;br /&gt;
 And I am on the &amp;quot;Test assignment name&amp;quot; &amp;quot;assign activity&amp;quot; page logged in as teacher1&lt;br /&gt;
instead of:&lt;br /&gt;
 When I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
 And I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 And I follow &amp;quot;Test assignment name&amp;quot;&lt;br /&gt;
Or for settings, instead of:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I follow &amp;quot;Test choice name&amp;quot;&lt;br /&gt;
And I navigate to &amp;quot;Edit settings&amp;quot; in current page administration&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Use:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I am on the &amp;quot;Test choice name&amp;quot; &amp;quot;choice activity editing&amp;quot; page&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are also similar stream-lined navigation steps for accessing question bank pages. See MDL-74130.&lt;br /&gt;
== Other ==&lt;br /&gt;
=== Core plugins review ===&lt;br /&gt;
A few plugins from core Moodle LMS which are no longer or hardly used have been removed and, if appropriate, added to the Moodle plugins directory.&lt;br /&gt;
&lt;br /&gt;
More information about this project, the list of plugins to be removed and the process to follow for keeping them before upgrading to 4.0 can be found in the [[Core plugins review]] page.&lt;br /&gt;
=== Site admin presets plugin ===&lt;br /&gt;
The third-party plugin [https://moodle.org/plugins/block_admin_presets Admin presets], created by David Monllaó and maintained by developers from [https://pimenko.com/ Pimenko] has been adapted and integrated into Moodle 4.0. It stores settings and plugins status (enabled/disabled) in what&#039;s called &amp;quot;presets&amp;quot; to let admins quickly switch between different configurations.&lt;br /&gt;
&lt;br /&gt;
More information about this project can be found in the [[Site admin presets|Site admin presets plugin]] page.&lt;br /&gt;
=== JavaScript browser support changes ===&lt;br /&gt;
From Moodle 4.0, Internet Explorer is no longer supported. See MDL-73915 and MDLSITE-6109 for further information on this change.&lt;br /&gt;
&lt;br /&gt;
This change means that changes built on 4.0 onwards (including the master branch) will be different to older versions of Moodle.&lt;br /&gt;
&lt;br /&gt;
For plugin developers supporting multiple versions of Moodle using a single plugin version, the compiled javascript files are backwards compatible and will _work_ on all supported versions, however if you run the `grunt` command on multiple versions you will see unbuilt changes. Running grunt on all versions of Moodle is not necessary and this check can be safely disabled for Moodle versions 3.9 - 4.0, as long as only at least you run `grunt` against at least one version of Moodle.&lt;br /&gt;
&lt;br /&gt;
If you need to support Internet Explorer and do not wish to fork your plugin for Moodle 4.0 onwards, then it is recommended that you run `grunt` on an older version of Moodle.&lt;br /&gt;
=== The course index element ===&lt;br /&gt;
The new course index feature can be themed using a set of scss variables. Use them to change the look and feel instead of adding custom css&lt;br /&gt;
 /theme/boost/scss/moodle/courseindex.scss&lt;br /&gt;
With the introduction of the course index component, the previous and next links shown underneath each activity are no longer needed and they will be removed.&lt;br /&gt;
=== Activity icons ===&lt;br /&gt;
The icons used for activities have been redesigned and updated for all core moodle activities.&lt;br /&gt;
&lt;br /&gt;
When viewing the new icons in a file manager, for example for the quiz activity, you will see a simple black monochrome icon with a transparent background.&lt;br /&gt;
&lt;br /&gt;
On the course page, or in the activity chooser, the icon will display as a white icon on a coloured background. Styling of the icons on the coursepage is controlled by the css in theme/boost/scss/moodle/icons.scss.&lt;br /&gt;
&lt;br /&gt;
The background colour for activity icons is set using a new variable in function [modname]_supports(). The quiz activity is of type assessment, so in function quiz_supports() there is a new line defining the purpose:&lt;br /&gt;
 case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_ASSESSMENT;&lt;br /&gt;
Available purposes are:&lt;br /&gt;
* MOD_PURPOSE_COMMUNICATION&lt;br /&gt;
* MOD_PURPOSE_ASSESSMENT&lt;br /&gt;
* MOD_PURPOSE_COLLABORATION&lt;br /&gt;
* MOD_PURPOSE_CONTENT&lt;br /&gt;
* MOD_PURPOSE_ADMINISTRATION&lt;br /&gt;
* MOD_PURPOSE_INTERFACE&lt;br /&gt;
The background colours linked to these purposes are set in theme/boost/scss/moodle/variables.scss&lt;br /&gt;
 $activity-icon-colors: map-merge(&lt;br /&gt;
     (&lt;br /&gt;
         &amp;quot;administration&amp;quot;: #5d63f6,&lt;br /&gt;
         &amp;quot;assessment&amp;quot;: #eb66a2,&lt;br /&gt;
         &amp;quot;collaboration&amp;quot;: #f7634d,&lt;br /&gt;
         &amp;quot;communication&amp;quot;: #11a676,&lt;br /&gt;
         &amp;quot;content&amp;quot;: #399be2,&lt;br /&gt;
         &amp;quot;interface&amp;quot;: #a378ff&lt;br /&gt;
     ),&lt;br /&gt;
     $activity-icon-colors&lt;br /&gt;
 );&lt;br /&gt;
If activity plugins do not define FEATURE_MOD_PURPOSE the activity icon will be rendered against a light grey background. There is no requirement to define the purpose of activity plugins, it will only affect the icon styling.&lt;br /&gt;
&lt;br /&gt;
Plugins implementing the variable FEATURE_MOD_PURPOSE are only supported on Moodle 4.0 and newer.&lt;br /&gt;
&lt;br /&gt;
Customising the activity icon can be done in an alternative way. For example using the styles.css in mod/[pluginname/styles.css&lt;br /&gt;
&lt;br /&gt;
In the example below the activity plugin developer chooses to keep the coloured icon for the activity and render it as large as the coloured background on the core activities&lt;br /&gt;
 .modicon_subcourse.activityiconcontainer {&lt;br /&gt;
     background-color: transparent;&lt;br /&gt;
     padding: 0;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 .modicon_subcourse.activityiconcontainer img {&lt;br /&gt;
     width: 50px;&lt;br /&gt;
     height: 50px;&lt;br /&gt;
 }&lt;br /&gt;
To customize all icon colours use this scss array and add it to the ‘Raw initial SCSS’ in the theme Boost advanced settings page. The complete array of icon background colours can be overridden using the ‘Raw initial SCSS’ in the theme settings page. The example below changes the colours of each activity type.&lt;br /&gt;
 $activity-icon-colors: (&lt;br /&gt;
     &amp;quot;administration&amp;quot;: #5D63F6,&lt;br /&gt;
     &amp;quot;assessment&amp;quot;: #11A676,&lt;br /&gt;
     &amp;quot;collaboration&amp;quot;: #EB66A2,&lt;br /&gt;
     &amp;quot;communication&amp;quot;: #F7634D,&lt;br /&gt;
     &amp;quot;content&amp;quot;: #399BE2,&lt;br /&gt;
     &amp;quot;interface&amp;quot;: #A378FF&lt;br /&gt;
 )&lt;br /&gt;
== I&#039;m a developer, what do I need to know? ==&lt;br /&gt;
This section is a quick checklist of the areas in this document that you should consult when updating your plugin.&lt;br /&gt;
=== Modules ===&lt;br /&gt;
If you are a module developer (activity / resources) then you need to review the following updates and changes:&lt;br /&gt;
* If using settings, reformat to work with the secondary navigation. We have significantly changed the way that settings are shown. Settings added to the course and activity administration branch of the navigation are now by default shown in the secondary navigation. You will most likely find them in the more section of the secondary navigation. Please avoid creating settings in containers (a parent navigation node with children). These settings will still be shown, but this goes against the pattern that we are trying to establish for navigation around the site. If you have a lot of settings, consider creating a specific page to handle your additional settings.&lt;br /&gt;
** The order of the items in the secondary navigation may not be to your liking. This can be changed. See [[Moodle_4.0_developer_update#Changing_the_order_of_tabs|changing the order of tabs]]&lt;br /&gt;
* Update my behat tests to use new steps for site navigation. See [[Moodle_4.0_developer_update#Behat_changes|new behat steps]].&lt;br /&gt;
* Update my module to use the new activity_header API. See [[Moodle_4.0_developer_update#The_activity_header_class|the activity header]].&lt;br /&gt;
* Update my pages to make it work with the general format of the tertiary navigation. See [[Moodle_4.0_developer_update#Tertiary_navigation|the tertiary navigation]].&lt;br /&gt;
* Update my activity icon to use the API and set a purpose. See [[Moodle_4.0_developer_update#Activity_icons|activity icons]].&lt;br /&gt;
=== Themes ===&lt;br /&gt;
If you are a theme developer then you may want to consider the following:&lt;br /&gt;
* Take a look at the [[Moodle_4.0_developer_update#Navigation_changes|new navigation]] and decide if you want to incorporate this into your theme.&lt;br /&gt;
** A new layout ([[Moodle_4.0_developer_update#New_layout_page|drawers]])&lt;br /&gt;
** An [[Moodle_4.0_developer_update#Edit_switch|edit switch]]&lt;br /&gt;
** The [[Moodle_4.0_developer_update#The_course_index_element|course index]]&lt;br /&gt;
* Use of the flat nav&lt;br /&gt;
* New Site administration page and layout&lt;br /&gt;
* Course settings and how they are displayed&lt;br /&gt;
=== Course format ===&lt;br /&gt;
There have been a lot of changes made to the course format. Most in the process of moving the course format away from using the old rendering system and towards templates.&lt;br /&gt;
We recommend the following sections be read carefully:&lt;br /&gt;
# [[Moodle_4.0_developer_update#The_course_format_system|The course format]]. There have been a lot of deprecations and reading this section is critical in understanding the changes made.&lt;br /&gt;
# Consider moving the rendering of your content over to the [[Templates|template system]].&lt;br /&gt;
=== Other plugins ===&lt;br /&gt;
# Are you adding settings? See the [[Moodle_4.0_developer_update#Adding_items_to_the_navigation|secondary nav]] for adding items to this navigation bar.&lt;br /&gt;
# Have a look at [[Moodle_4.0_developer_update#Secondary_navigation|secondary]] and [[Moodle_4.0_developer_update#Tertiary_navigation|tertiary]] navigation changes in general if you have a plugin that has multiple pages to navigate around.&lt;br /&gt;
# Do you have behat tests? Check the new [[Moodle_4.0_developer_update#Behat_changes|behat changes]].&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61854</id>
		<title>Moodle 4.0 developer update</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61854"/>
		<updated>2022-03-17T02:28:39Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Page API */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 4.0}}This page highlights the important changes that are coming in Moodle 4.0 for developers. Including how the UX improvements impact custom themes, relevant API changes, and what you can do as developer to prepare for the 4.0 release.&lt;br /&gt;
== Navigation changes ==&lt;br /&gt;
The core Navigation API has been left mostly untouched. The callbacks to all navigation callbacks remains unchanged and will be called as part of the regular &#039;navigation&#039; and &#039;settingsnav&#039; initialisation. Some new core classes have been created and exist within a new namespace &#039;core/navigation&#039; and serves as conduit to rearrange, cherry-pick existing navigation nodes from the navigation/settingsnav trees and display within the respective navigation type. As such, it is highly recommended to provide unique keys for custom navigation nodes as this helps in the cherry-picking / rearranging process within the new classes.&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
The primary navigation(the navbar) apart from the existing content will now display links to the Dashboard, My Courses, Site Admin and Course search, by default. You can still add items to the navbar via the &#039;custom menu&#039; option. This will be displayed within the &#039;More&#039; menu. We have transitioned the menus to be rendered via templates - refer user_menu.mustache. The lang menu has been moved to reside within the user menu.&lt;br /&gt;
==== Customising the primary navigation ====&lt;br /&gt;
Not yet implemented but we are looking at allowing the full addition and removal of any of the primary navigation tabs in the boost theme config file.&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
The main content area shows tabs for secondary navigation with a maximum of 5 items being rendered in this ‘more’ menu. A new UI component has been created to render menus like this. Files:&lt;br /&gt;
 /lib/templates/moremenu.mustache&lt;br /&gt;
==== Adding items to the navigation ====&lt;br /&gt;
The secondary navigation pulls information mainly from the settings navigation node from each context. Any plugin that implements the existing navigation hooks will have their items added to the secondary navigation.&lt;br /&gt;
Existing navigation hooks:&lt;br /&gt;
* {module}_extend_navigation&lt;br /&gt;
* {local}_extend_navigation&lt;br /&gt;
* {report}_report_extend_navigation&lt;br /&gt;
* {plugin}_extend_navigation_course&lt;br /&gt;
* {plugin}_extend_navigation_category_settings&lt;br /&gt;
==== Changing the order of tabs ====&lt;br /&gt;
Apart from the previously mentioned functions, you can also create a custom secondary class as mentioned earlier. This will automatically be picked by getter and used to render the secondary nav within the activity. E.g. mod_assign/local/views/secondary. Note: This is currently only possible on an activity and block level.&lt;br /&gt;
=== Tertiary navigation ===&lt;br /&gt;
We&#039;ve moved action buttons to the top of the page. We would encourage you to do the same.&lt;br /&gt;
If you have any buttons on an activity page that go to another page, or open a form (or similar), then we encourage you to move them from the body of your activity page to the top. All of the core activities have been updated to follow this pattern. Please take a look to see how you can format your activity in a similar fashion. There is no API here. You are welcome to create the buttons and display them as you wish in this top area.&lt;br /&gt;
=== New API functions ===&lt;br /&gt;
==== Page API ====&lt;br /&gt;
* Magic getters to fetch the primary and secondary navs and the primary output.&lt;br /&gt;
* The secondarynav magic getter also checks whether a custom secondary class has been defined within the module&#039;s local\views directory. Use this if you want to deviate from the standard secondary nav structure/order.&lt;br /&gt;
&lt;br /&gt;
* set_secondarynav - Force override the secondary navigation class&lt;br /&gt;
&lt;br /&gt;
* set_secondary_navigation - Sets the ‘_hassecondarynavigation’ and optionally the ‘_hastablistsecondarynavigation’ to indicate whether a page should render the secondary navigation, and if the secondary navigation should be rendered and behave with a tablist ARIA role (as opposed to its default which is being rendered with a menubar ARIA role).&lt;br /&gt;
==== Navigationlib ====&lt;br /&gt;
* set_show_in_secondary_navigation - whether or not a node should be displayed in the secondary nav. Accepts a single boolean argument&lt;br /&gt;
* set_force_into_more_menu- whether or not to force a node into the &#039;More&#039; menu. Accepts a single boolean argument&lt;br /&gt;
==== The activity header class ====&lt;br /&gt;
There is a new activity header class that handles the display of information common to activities. 3rd party activities are not required to explicitly output this information as part of rendering individual pages.&lt;br /&gt;
&lt;br /&gt;
The common information that are currently handled by the class are:&lt;br /&gt;
* title&lt;br /&gt;
* description&lt;br /&gt;
* completion information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As part of the update it was required that the initial information to be displayed by the class be toggable at a theme and layout level. Taking this into account the following theme level configurable exists:&lt;br /&gt;
* activityheaderconfig =&amp;gt; An array that currently only enforces &#039;notitle&#039; but can be expanded in the future NOTE: Boost has this set as true by default &#039;options&#039;&lt;br /&gt;
The following layout level options that can be defined:&lt;br /&gt;
* noactivityheader - to remove the header in this specific layout.&lt;br /&gt;
* activityheader - An array that enforces the following options:&lt;br /&gt;
** notitle&lt;br /&gt;
** nocompletion&lt;br /&gt;
** nodescription&lt;br /&gt;
The class has a page level getter which you can use to fetch the current version of the class. The base state is initialised within the constructor with the completion information only fetched when data is exported for the template.&lt;br /&gt;
&lt;br /&gt;
The class has setters for the following variables which can be leveraged to modify the header for a particular page in the format set_{variable_name}:&lt;br /&gt;
* hidecompletion&lt;br /&gt;
* description&lt;br /&gt;
* title&lt;br /&gt;
Alternately, bulk operations can also be done by passing the above variables in an array to &#039;set_attrs&#039; which in turn calls the setters.&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note: Any updates to the activityheader needs to be performed before the call to $OUTPUT-&amp;gt;header&#039;&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
===== Theme updates: =====&lt;br /&gt;
In order for 3rd party themes to use the class they need to export the activity_header and include the following into their base template :&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
   {{&amp;gt; core/activity_header}}&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;** headercontent being the array element that contains the exported activity_header data &lt;br /&gt;
===== Accessibility notes: =====&lt;br /&gt;
The jump to ‘maincontent’ div is now rendered within the activity header when within an activity context&lt;br /&gt;
== Component library ==&lt;br /&gt;
Each Moodle installation now ships with a Moodle User Interface (UI) Component library, a documentation system used to describe all the Bootstrap components and the custom Moodle components. The component Library is a helper tool for developers when creating user interfaces, a testing tool for theme developers and a documentation tool for core developers. The ultimate goal of having a component library is to encourage developers to create consistent user interfaces to improve Moodle’s overall user experience.&lt;br /&gt;
&lt;br /&gt;
The library contains pages with documentation about User Interface components. It contains details on how to use the component, what variations are available and the JavaScript events / options are associated with the component.&lt;br /&gt;
&lt;br /&gt;
When writing on these pages it is possible to render core mustache templates using some custom syntax like this:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; mustache template=&amp;quot;core/notification_error&amp;quot; &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; /mustache &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also call core JavaScript or use HTML examples where the html code and the rendered result are visible in the Component Library. For more info visit the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-templates/ Moodle templates] page or the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-javascript/ Moodle JavaScript] page.&lt;br /&gt;
&lt;br /&gt;
Each page in the library uses the current css from the default theme in your Moodle installation, if you have multiple themes installed and enabled the setting &amp;quot;Allow theme changes on url&amp;quot;, the component library will have a theme selector option.&lt;br /&gt;
&lt;br /&gt;
A hosted version of the Component Library can be found here. http://componentlibrary.moodle.com&lt;br /&gt;
=== Enabling the Component Library ===&lt;br /&gt;
Component library pages are written in the markdown language. These pages need to be compiled to HTML pages before the Component Library is visible. To compile the pages the server running Moodle needs to have the [[Javascript Modules#Install%20NVM%20and%20Node|JavaScript developer tools installed]] (nodeJs and Grunt)&lt;br /&gt;
&lt;br /&gt;
If your server meets all requirements you can enable the library running&lt;br /&gt;
 $ npm install&lt;br /&gt;
 $ grunt componentlibrary&lt;br /&gt;
Further installation instructions can be found in the Component Library itself.&lt;br /&gt;
=== Documenting new UI Components ===&lt;br /&gt;
There are no set rules for adding new pages in the component library yet. These rules will need to be written and adopted in the integration process for Moodle code.&lt;br /&gt;
&lt;br /&gt;
As a guideline for making this rules consideration are:&lt;br /&gt;
&lt;br /&gt;
The component library is not about single use components, for example the Moodle grade book (a huge component with many custom features). Or about very common components like buttons, these are already covered by the Bootstrap section of the component library.&lt;br /&gt;
&lt;br /&gt;
New features should be build keeping in mind the UI part needs to be customisable and if possible (and making sense) reusable. And example would be the new page drawers that we are introducing for the Navigation project. Or the custom primary navigation menus where overflowing items are pushed into a More section.&lt;br /&gt;
== Theme changes ==&lt;br /&gt;
=== Edit switch ===&lt;br /&gt;
On theme boost the “Turn editing on” and “Customise this page” buttons have been replaced by an edit switch in the top navbar. Theme Classic will keep using the old buttons. Child themes can choose to use the edit switch if the theme config.php is using this variable&lt;br /&gt;
 $THEME-&amp;gt;haseditswitch = true;&lt;br /&gt;
The languague menu, which used to be rendered in place of the custom menu has moved to the user dropdown when the user is logged in. If not logged in it will be placed next to the search / notification / messaging icon in the top navbar.&lt;br /&gt;
=== Login page ===&lt;br /&gt;
The login page has been redesigned and allows the admin to configure a background image for the login page only in the theme settings page. This change is available in both Boost and Classic. The login page still has all the features with an improved layout. &lt;br /&gt;
=== The page footer ===&lt;br /&gt;
In large screens, the page footer button is only visible when clicking a help button at the bottom right of the screen.&lt;br /&gt;
=== User initials as profile picture placeholder ===&lt;br /&gt;
If users do not upload a profile picture the user initials are displayed on a rounded gray background as a placeholder picture in the top navbar or any other page using a placeholder image. This change will be available in both Boost and Classic. &lt;br /&gt;
&lt;br /&gt;
With the introduction of this placeholder image the full username will no longer be displayed in the top navbar.&lt;br /&gt;
=== Removal of back to top link ===&lt;br /&gt;
The &amp;quot;back to top&amp;quot; link will be removed for theme boost since the new course index reduced the dependence on page scrolling. Also, the new footer is positioned where this component used to be.&lt;br /&gt;
=== Styling changes ===&lt;br /&gt;
By default rounded edges will be used for UI components, for the page header and main content area the borders will be removed. &lt;br /&gt;
=== New layout page ===&lt;br /&gt;
Theme boost now uses the drawers.php layout for the course index and blocks.&lt;br /&gt;
== Question bank changes ==&lt;br /&gt;
There was a big project to deliver [[Question bank improvements for Moodle 4.0]] which added a new plugin type for adding features to the question banks, tracking the version history for each question as it is edited (question table has been split into &amp;lt;code&amp;gt;question&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;question_versions&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_bank_entries&amp;lt;/code&amp;gt;), and tracking where each question is going to be used, with new tables &amp;lt;code&amp;gt;question_references&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;question_set_references&amp;lt;/code&amp;gt;. This work was done in Epic MDL-70329 if you want to track down the details of any of the core changes.&lt;br /&gt;
=== Question type plugins ===&lt;br /&gt;
Amazingly, we (Safat and colleagues at Catalyst AU) managed to implement this without breaking most question type plugins.&lt;br /&gt;
&lt;br /&gt;
However, the changes to the question bank, and the other Moodle 4.0 changes, probably broke the Behat tests for your plugin. To help with fixing that, MDL-74130 adds navigation to key question type pages (Preview and Edit for a question, and standard question bank pages like the bank itself, import and export) which should let you fix your test efficiently, and in a way that will work in all Moodle versions since 3.9.&lt;br /&gt;
&lt;br /&gt;
The &#039;most&#039; in the first paragraph here is becuase more advance question types may require more effort to fix. (For example qtype_combined which creates multi-part qusetions like the core qtype_multianswer; or qtype_pmatch or qtype_stack, which store additional data - questions tests - alongside the question itseld. How should that work with versionning?) But, if you have not done weird things like that, you are probably safe. If you find anything else that causes problems, please list it here.&lt;br /&gt;
&lt;br /&gt;
The same thing should apply to question behaviour and question import/export format plugings: no significant changes required (probably just fixing the Behat tests because of the navigation changes).&lt;br /&gt;
=== New plugin type: qbank plugins ===&lt;br /&gt;
This is not something that will cause problems for people upgrading from 3.x. Rather, it is an exciting possibility you can explore once you have survived process of upgrading to 4.0. There is a whole new plugin type which you can create to add new features to the question bank. For example extra columns, new actions and bulk actions, and so on. See [[Question_bank_plugins]].&lt;br /&gt;
=== Activities that use questions ===&lt;br /&gt;
The probable bad news is if you have an activity module which uses questions. So far, the only activity which has been fixed is mod_quiz in Moodle core, so we don&#039;t yet have a good picture of what fixes will be necessary in other activities. Work is about to start fixing [https://github.com/studentquiz/moodle-mod_studentquiz mod_studentquiz], so watching that should give more clues. As we do that, we will try to update this section of this page. Other help writing the information required here would also be greatly appreciated.&lt;br /&gt;
== The course format system ==&lt;br /&gt;
Most of the logic for rendering and editing a course has been moved to a new subsystem called courseformat. The subsystem is located in &amp;quot;course/format&amp;quot; folder so it includes all the format plugins inside. The methods and modules which are distributed between the course and the course/format folders are now rearranged or refactored to be aligned with the current Moodle coding style.&lt;br /&gt;
=== Mandatory renderer in course formats ===&lt;br /&gt;
Now format plugins renderer is not optional anymore. Legacy formats without a renderer will get a deprecation message but it will continue working however, they should create a new renderer as soon as possible. The section-based format can do it by extending the provided core_courseformat\output\section_renderer class which includes all the necessary methods.&lt;br /&gt;
=== New format base class ===&lt;br /&gt;
The old base_format class (which all plugins extend) is now renamed as core_courseformat\base. The new class provides all the functionally of the previous base_format but it has been refactored to be used as a centralized source of truth for the course rendering. Legacy formats should extend the new class to avoid the deprecation message.&lt;br /&gt;
&lt;br /&gt;
Now, the plugin format class provides information such as:&lt;br /&gt;
* If the page is displaying a single or multiple section&lt;br /&gt;
* Give access to other related format objects like the modinfo, the course record, maximum number of sections...&lt;br /&gt;
* If the format is compatible with features like course index, reactive components, ajax...&lt;br /&gt;
* Other format specifics like the page title, the default section name, default blocks...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The format instance is now the main object output components will use to render a course (see next section for more information).&lt;br /&gt;
=== New course output classes and mustache files ===&lt;br /&gt;
Traditionally, section-based course formats uses print_single_section_page and print_multiple_section_page to render the course content. In Moodle 4.0 most of the course rendering methods are migrated to output components and mustache templates. The old methods will get deprecation messages if they use the old renderer methods.&lt;br /&gt;
&lt;br /&gt;
This is an example of a format rendering a course:&amp;lt;syntaxhighlight lang=&amp;quot;php-brief&amp;quot;&amp;gt;&lt;br /&gt;
// Get the course format instance.&lt;br /&gt;
$format = course_get_format($course);&lt;br /&gt;
&lt;br /&gt;
// Get the specific format renderer.&lt;br /&gt;
$renderer = $format-&amp;gt;get_renderer($PAGE);&lt;br /&gt;
&lt;br /&gt;
if (!empty($displaysection)) {&lt;br /&gt;
    // Setup the format instance to display a single section.&lt;br /&gt;
    $format-&amp;gt;set_section_number($displaysection);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Create the ouptut instance and render it.&lt;br /&gt;
$outputclass = $format-&amp;gt;get_output_classname(&#039;content&#039;);&lt;br /&gt;
$widget = new $outputclass($format);&lt;br /&gt;
&lt;br /&gt;
echo $renderer-&amp;gt;render($widget);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Format plugins are free to use its own output classes to render a course, or they could override the existing output classes by providing their own implementation. For example, the default output for &amp;quot;content&amp;quot; (as in the previous example) is &amp;quot;core_courseformat\output\local\|content&amp;quot;, however, if the plugin has a &amp;quot;format_XXX\output\courseformat\content&amp;quot; class, the $format-&amp;gt;class the get_output_class will return the overridden one.&lt;br /&gt;
Another important update on course rendering is that now all course structure is rendered using mustache templates instead of the original html_writer methods. Now themes are able to override the course format by providing alternative versions of the mustache files. All core course templates are located in &amp;quot;course/format/templates&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All the new output classes and a guide on how to migrate the current third-party plugins will be available soon.&lt;br /&gt;
=== Course editor javascript modules and frontend components ===&lt;br /&gt;
The majority of the javascript logic related to the course editing is replaced by AMD modules. Because this is a major change in the way courses are edited and rendered, by default format plugins will continue using the previous YUI modules for now. However, formats can start using the new libraries overriding the &amp;quot;$format-&amp;gt;supports_components()&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Some Moodle 4.0 new features are only available for courses using the new editor library:&lt;br /&gt;
* Edit the course via the course index&lt;br /&gt;
* Creating sections without reloading the course page&lt;br /&gt;
* The new move section/activity modal&lt;br /&gt;
* Native browser drag&amp;amp;drop implementation&lt;br /&gt;
The new course editor uses a component-based reactive pattern to keep track of the course changes. The pattern highlights are:&lt;br /&gt;
* The main AMD module &amp;quot;core_crouseformat\courseeditor&amp;quot; maintains a data structure called state.&lt;br /&gt;
* Each UI element is implemented as a Component that observes the course state data and reacts to any data change&lt;br /&gt;
* When any reactive component needs to modify the course, it asks the course editor to execute a mutation. Mutations encapsulate all web services calls and alter the course state data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The reactive library documentation, as well as the format plugin migration guide, will be available soon.&lt;br /&gt;
=== Other course related 4.0 changes ===&lt;br /&gt;
Two new web services have been added:&lt;br /&gt;
* core_courseformat_get_state: user by the new javascript course editor to get the current course state data (containing the list of sections, activities, and other course-related data)&lt;br /&gt;
* core_courseformat_update_course: to alter the current course content. Each call returns the parts of the course state altered by the action&lt;br /&gt;
== Behat changes ==&lt;br /&gt;
=== New steps ===&lt;br /&gt;
Moodle 4.0 introduces some new behat steps.&lt;br /&gt;
&lt;br /&gt;
Sometimes you want to create a bulk number of activities. In that case you can use:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
:count :entitytype exist with the following data:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Given 100 &amp;quot;mod_lti &amp;gt; tool types&amp;quot; exist with the following data:&lt;br /&gt;
  |name        |Test tool [count]                  |&lt;br /&gt;
  |description |Example description [count]        |&lt;br /&gt;
  |baseurl     |https://www.example.com/tool[count]|&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dynamic (AJAX) tabs is a new feature contributed to Moodle 4.0 by the Workplace team (MDL-71943). You can use the following step to navigate between the tabs.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on the &amp;quot;tab title&amp;quot; dynamic tab&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To make sure that edit mode is (or is not) available on the current page, the following steps can be used.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And edit mode should be available on the current page&lt;br /&gt;
And edit mode should not be available on the current page&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are new aliases for the existing steps &amp;lt;code&amp;gt;I turn editing mode on&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;I turn editing mode off&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I switch editing mode on&lt;br /&gt;
And I switch editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to the existing step to go to a course with editing mode on, we now have the following step to do the same but with editing mode being off.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I am on &amp;quot;course full name&amp;quot; course homepage with editing mode off&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step is similar to the old &amp;lt;code&amp;gt;following &amp;quot;link string&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&amp;lt;/code&amp;gt; step, with more flexibility.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot; should download between &amp;quot;min bytes&amp;quot; and &amp;quot;max bytes&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And following &amp;quot;Download&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;Starter&amp;quot; &amp;quot;table_row&amp;quot; should download between &amp;quot;0&amp;quot; and &amp;quot;5000&amp;quot; bytes&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to hover the mouse over the trigger area.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over the &amp;quot;element string&amp;quot; &amp;quot;element type&amp;quot; in the &amp;quot;container string&amp;quot; &amp;quot;container type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step enables an installed plugin.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;plugin name&amp;quot; &amp;quot;plugin type&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I enable &amp;quot;course_summary&amp;quot; &amp;quot;block&amp;quot; plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following is a special variation of &#039;I click on &amp;quot;&amp;lt;page name&amp;gt;&amp;quot; &amp;quot;link&amp;quot; in the &amp;quot;page&amp;quot; &amp;quot;region&amp;quot;&#039;. It first checks to see if we are on the given page via the breadcrumb. If not we then attempt to follow the link name given.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I follow the breadcrumb &amp;quot;page name&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use the following step to ensure a node is active in the navbar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Node&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;My courses&amp;quot; is active in navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step can be used to navigate to a given node in the primary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select &amp;quot;Node&amp;quot; from primary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check whether an item exists in the user menu or not.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the user menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Language&amp;quot; &amp;quot;link&amp;quot; should exist in the user menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are to check if a submenu of the user menu is shown, and if an item exists or does not exist in a given user submenu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the &amp;quot;submenu name&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I follow &amp;quot;Language&amp;quot; in the user menu&lt;br /&gt;
Then I should see &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
And &amp;quot;English (pirate) &amp;amp;lrm;(en_ar)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;Language selector&amp;quot; user submenu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add enrolment methods to courses you can use the following new step. The data that you provide in the next lines are used to fill the enrolment method form.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;enrolment method&amp;quot; in &amp;quot;course identifier&amp;quot; with:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I add &amp;quot;Self enrolment&amp;quot; enrolment method in &amp;quot;Course 1&amp;quot; with:&lt;br /&gt;
  | Custom instance name     | Test student enrolment |&lt;br /&gt;
  | Enrolment key            | moodle_rules           |&lt;br /&gt;
  | Use group enrolment keys | Yes                    |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are 3 new steps specific to the calendar component. These steps can be used to hover over a day in the mini-calendar or the full calendar.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the full calendar page&lt;br /&gt;
And I hover over day &amp;quot;day of month&amp;quot; of this month in the mini-calendar block&lt;br /&gt;
And I hover over today in the mini-calendar block&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some new steps are added to question bank to be able to add comment to questions, verify the existence of a comment, and deleting comments form questions. Please note that the steps for adding comments only write the comment text in the comment field. You still need to click on the &amp;quot;Add comment&amp;quot; button to save the comment.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question&lt;br /&gt;
And I add &amp;quot;comment text&amp;quot; comment to question preview&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question&lt;br /&gt;
And I delete &amp;quot;comment text&amp;quot; comment from question preview&lt;br /&gt;
And I should see &amp;quot;number of comments&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;number of comments&amp;quot; on the row on the comments column&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;Question bank&amp;quot; in current page administration&lt;br /&gt;
And I should see &amp;quot;0&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;0&amp;quot; on the row on the comments column&lt;br /&gt;
And I add &amp;quot;test comment 01&amp;quot; comment to question&lt;br /&gt;
And I click on &amp;quot;Add comment&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Close&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;.modal-dialog&amp;quot; &amp;quot;css_element&amp;quot;&lt;br /&gt;
And I should see &amp;quot;1&amp;quot; on the comments column&lt;br /&gt;
And I click &amp;quot;1&amp;quot; on the row on the comments column&lt;br /&gt;
And I delete &amp;quot;test comment 01&amp;quot; comment from question&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar to the steps for comments, the following steps are to verify the number of a question&#039;s usage and to click on it in order to open the question usage modal.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
And I click &amp;quot;usage count&amp;quot; on the usage column&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new steps are related to bulk actions in the question bank UI.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
And I should not see question bulk action &amp;quot;action&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on &amp;quot;First question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Second question&amp;quot; &amp;quot;checkbox&amp;quot;&lt;br /&gt;
And I click on &amp;quot;With selected&amp;quot; &amp;quot;button&amp;quot;&lt;br /&gt;
And I should see question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on question bulk action &amp;quot;deleteselected&amp;quot;&lt;br /&gt;
And I click on &amp;quot;Delete&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;Confirm&amp;quot; &amp;quot;dialogue&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/en/Report_builder Report builder] is a new feature contributed to Moodle 4.0 by the Workplace team. The following new step is added to Moodle 4.0 to select an action from the action menu in the list of custom reports table.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I press &amp;quot;action&amp;quot; action in the &amp;quot;report name&amp;quot; report row&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There&#039;s another step related to the report builder to set a column&#039;s aggregation in the report editor.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;column title&amp;quot; column aggregation to &amp;quot;aggregation method&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I set the &amp;quot;First name&amp;quot; column aggregation to &amp;quot;Comma separated values&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step needs to be used in scenarios that involve testing BigBlueButton. For this to work, you need to have a [https://github.com/moodlehq/bigbluebutton_mock BigBlueButton Mock API Server] and set &amp;lt;code&amp;gt;TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER&amp;lt;/code&amp;gt; to point to that in config.php.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And a BigBlueButton mock server is configured&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step replicates receiving a callback from the BigBlueButton server indicating the recordings for meetings are ready for viewing.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And the BigBlueButtonBN server has sent recording ready notifications&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following steps are specific to the lesson activity. Note that in 4.0, some links (such as the &amp;quot;edit&amp;quot; and the &amp;quot;grade essays&amp;quot; links) are replaced by buttons, so you need to update your old steps with the new ones.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I edit the lesson&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;A new step is added to be used in lesson activities to edit them. This step navigates the user to the lesson edit page.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I grade lesson essays&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;It&#039;s a new step to go to the &amp;quot;Grade essays&amp;quot; page of the lesson we are currently in.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I select edit type &amp;quot;edit type&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Select the lesson edit type when we are in the the lesson&#039;s edit page. &amp;quot;edit type&amp;quot; can either be &amp;quot;Collapsed&amp;quot; or &amp;quot;Expanded&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following new step can be used to navigate to the exports page in the course gradebook and select the specified export type from the grade exports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;export option&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;XML file&amp;quot; export page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similarly, there&#039;s a new step to navigate to the imports page in the course gradebook and select the specified import type from the grade imports navigation selector.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I navigate to &amp;quot;import option&amp;quot; import page in the course gradebook&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Boost steps ===&lt;br /&gt;
In addition to the steps listed in the previous section, there are also some Boost specific steps coming with Moodle 4.0. These steps only work in Boost or Boost child themes, so you need to make sure they are not used in scenarios that may be run by non-Boost themes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following step checks whether a node is active in the secondary navigation.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see :name is active in secondary navigation&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Boost theme shows the language selector menu in the primary navigation when not logged in, and within the user menu when logged in. The following steps are to check if the primary navigation includes the language selector menu.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And language selector menu should exist in the navbar&lt;br /&gt;
And language selector menu should not exist in the navbar&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And the following steps can be used to check whether an item exists in the language selector menu in the Boost theme.&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should exist in the language selector menu&lt;br /&gt;
And &amp;quot;item text&amp;quot; &amp;quot;selector type&amp;quot; should not exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For example:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;English &amp;amp;lrm;(en)&amp;amp;lrm;&amp;quot; &amp;quot;link&amp;quot; should exist in the language selector menu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Modified steps ===&lt;br /&gt;
The step &amp;lt;code&amp;gt;I change the (window|viewport) size to &amp;quot;size&amp;quot;&amp;lt;/code&amp;gt; now supports 2 new values for the size argument. The size argument now accepts &amp;lt;code&amp;gt;mobile&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;tablet&amp;lt;/code&amp;gt; values in addition to &amp;lt;code&amp;gt;small&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;medium&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;large&amp;lt;/code&amp;gt;.&lt;br /&gt;
=== Removed steps ===&lt;br /&gt;
Some behat steps are removed or replaced with new steps.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a result of some design changes, hidden or restricted activities are no longer dimmed. Therefore the step&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be dimmed&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;is now removed.&lt;br /&gt;
Depending on what you were using that step for, you may be able to use these steps:&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Label name&amp;quot; label should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; activity should be hidden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I should see &amp;quot;Activity or resource name&amp;quot;&lt;br /&gt;
And &amp;quot;Activity or resource name&amp;quot; &amp;quot;link&amp;quot; should not exist in the &amp;quot;region-main&amp;quot; &amp;quot;region&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Other things to consider ===&lt;br /&gt;
To make behat tests more readable and easy to maintain, it is recommended to use the most direct steps to get what the test needs. It is highly recommended to use&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
instead of navigating to the activity via&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
Now that [https://docs.moodle.org/dev/Prototypes#Course_creation_improvements Course index] is integrated these behat steps&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
will fail using Boost theme.&lt;br /&gt;
&lt;br /&gt;
The reason for it is that the drawer used in Boost is hiding the course index. So when the test is trying to follow an &amp;quot;Activity name&amp;quot; link, it finds two different links:&lt;br /&gt;
* one in the course index&lt;br /&gt;
* another one in the course main content.&lt;br /&gt;
But the first one, the one in the course index, is hidden by the drawer, and the test fails.&lt;br /&gt;
&lt;br /&gt;
However the recommended behat steps&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
Old behat steps that may now fail can be updated to the new steps.&lt;br /&gt;
For example:&lt;br /&gt;
 And I am on the &amp;quot;Test assignment name&amp;quot; &amp;quot;assign activity&amp;quot; page logged in as teacher1&lt;br /&gt;
instead of:&lt;br /&gt;
 When I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
 And I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 And I follow &amp;quot;Test assignment name&amp;quot;&lt;br /&gt;
Or for settings, instead of:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I follow &amp;quot;Test choice name&amp;quot;&lt;br /&gt;
And I navigate to &amp;quot;Edit settings&amp;quot; in current page administration&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Use:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;And I am on the &amp;quot;Test choice name&amp;quot; &amp;quot;choice activity editing&amp;quot; page&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are also similar stream-lined navigation steps for accessing question bank pages. See MDL-74130.&lt;br /&gt;
== Other ==&lt;br /&gt;
=== Core plugins review ===&lt;br /&gt;
A few plugins from core Moodle LMS which are no longer or hardly used have been removed and, if appropriate, added to the Moodle plugins directory.&lt;br /&gt;
&lt;br /&gt;
More information about this project, the list of plugins to be removed and the process to follow for keeping them before upgrading to 4.0 can be found in the [[Core plugins review]] page.&lt;br /&gt;
=== Site admin presets plugin ===&lt;br /&gt;
The third-party plugin [https://moodle.org/plugins/block_admin_presets Admin presets], created by David Monllaó and maintained by developers from [https://pimenko.com/ Pimenko] has been adapted and integrated into Moodle 4.0. It stores settings and plugins status (enabled/disabled) in what&#039;s called &amp;quot;presets&amp;quot; to let admins quickly switch between different configurations.&lt;br /&gt;
&lt;br /&gt;
More information about this project can be found in the [[Site admin presets|Site admin presets plugin]] page.&lt;br /&gt;
=== JavaScript browser support changes ===&lt;br /&gt;
From Moodle 4.0, Internet Explorer is no longer supported. See MDL-73915 and MDLSITE-6109 for further information on this change.&lt;br /&gt;
&lt;br /&gt;
This change means that changes built on 4.0 onwards (including the master branch) will be different to older versions of Moodle.&lt;br /&gt;
&lt;br /&gt;
For plugin developers supporting multiple versions of Moodle using a single plugin version, the compiled javascript files are backwards compatible and will _work_ on all supported versions, however if you run the `grunt` command on multiple versions you will see unbuilt changes. Running grunt on all versions of Moodle is not necessary and this check can be safely disabled for Moodle versions 3.9 - 4.0, as long as only at least you run `grunt` against at least one version of Moodle.&lt;br /&gt;
&lt;br /&gt;
If you need to support Internet Explorer and do not wish to fork your plugin for Moodle 4.0 onwards, then it is recommended that you run `grunt` on an older version of Moodle.&lt;br /&gt;
=== The course index element ===&lt;br /&gt;
The new course index feature can be themed using a set of scss variables. Use them to change the look and feel instead of adding custom css&lt;br /&gt;
 /theme/boost/scss/moodle/courseindex.scss&lt;br /&gt;
With the introduction of the course index component, the previous and next links shown underneath each activity are no longer needed and they will be removed.&lt;br /&gt;
=== Activity icons ===&lt;br /&gt;
The icons used for activities have been redesigned and updated for all core moodle activities.&lt;br /&gt;
&lt;br /&gt;
When viewing the new icons in a file manager, for example for the quiz activity, you will see a simple black monochrome icon with a transparent background.&lt;br /&gt;
&lt;br /&gt;
On the course page, or in the activity chooser, the icon will display as a white icon on a coloured background. Styling of the icons on the coursepage is controlled by the css in theme/boost/scss/moodle/icons.scss.&lt;br /&gt;
&lt;br /&gt;
The background colour for activity icons is set using a new variable in function [modname]_supports(). The quiz activity is of type assessment, so in function quiz_supports() there is a new line defining the purpose:&lt;br /&gt;
 case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_ASSESSMENT;&lt;br /&gt;
Available purposes are:&lt;br /&gt;
* MOD_PURPOSE_COMMUNICATION&lt;br /&gt;
* MOD_PURPOSE_ASSESSMENT&lt;br /&gt;
* MOD_PURPOSE_COLLABORATION&lt;br /&gt;
* MOD_PURPOSE_CONTENT&lt;br /&gt;
* MOD_PURPOSE_ADMINISTRATION&lt;br /&gt;
* MOD_PURPOSE_INTERFACE&lt;br /&gt;
The background colours linked to these purposes are set in theme/boost/scss/moodle/variables.scss&lt;br /&gt;
 $activity-icon-colors: map-merge(&lt;br /&gt;
     (&lt;br /&gt;
         &amp;quot;administration&amp;quot;: #5d63f6,&lt;br /&gt;
         &amp;quot;assessment&amp;quot;: #eb66a2,&lt;br /&gt;
         &amp;quot;collaboration&amp;quot;: #f7634d,&lt;br /&gt;
         &amp;quot;communication&amp;quot;: #11a676,&lt;br /&gt;
         &amp;quot;content&amp;quot;: #399be2,&lt;br /&gt;
         &amp;quot;interface&amp;quot;: #a378ff&lt;br /&gt;
     ),&lt;br /&gt;
     $activity-icon-colors&lt;br /&gt;
 );&lt;br /&gt;
If activity plugins do not define FEATURE_MOD_PURPOSE the activity icon will be rendered against a light grey background. There is no requirement to define the purpose of activity plugins, it will only affect the icon styling.&lt;br /&gt;
&lt;br /&gt;
Plugins implementing the variable FEATURE_MOD_PURPOSE are only supported on Moodle 4.0 and newer.&lt;br /&gt;
&lt;br /&gt;
Customising the activity icon can be done in an alternative way. For example using the styles.css in mod/[pluginname/styles.css&lt;br /&gt;
&lt;br /&gt;
In the example below the activity plugin developer chooses to keep the coloured icon for the activity and render it as large as the coloured background on the core activities&lt;br /&gt;
 .modicon_subcourse.activityiconcontainer {&lt;br /&gt;
     background-color: transparent;&lt;br /&gt;
     padding: 0;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 .modicon_subcourse.activityiconcontainer img {&lt;br /&gt;
     width: 50px;&lt;br /&gt;
     height: 50px;&lt;br /&gt;
 }&lt;br /&gt;
To customize all icon colours use this scss array and add it to the ‘Raw initial SCSS’ in the theme Boost advanced settings page. The complete array of icon background colours can be overridden using the ‘Raw initial SCSS’ in the theme settings page. The example below changes the colours of each activity type.&lt;br /&gt;
 $activity-icon-colors: (&lt;br /&gt;
     &amp;quot;administration&amp;quot;: #5D63F6,&lt;br /&gt;
     &amp;quot;assessment&amp;quot;: #11A676,&lt;br /&gt;
     &amp;quot;collaboration&amp;quot;: #EB66A2,&lt;br /&gt;
     &amp;quot;communication&amp;quot;: #F7634D,&lt;br /&gt;
     &amp;quot;content&amp;quot;: #399BE2,&lt;br /&gt;
     &amp;quot;interface&amp;quot;: #A378FF&lt;br /&gt;
 )&lt;br /&gt;
== I&#039;m a developer, what do I need to know? ==&lt;br /&gt;
This section is a quick checklist of the areas in this document that you should consult when updating your plugin.&lt;br /&gt;
=== Modules ===&lt;br /&gt;
If you are a module developer (activity / resources) then you need to review the following updates and changes:&lt;br /&gt;
* If using settings, reformat to work with the secondary navigation. We have significantly changed the way that settings are shown. Settings added to the course and activity administration branch of the navigation are now by default shown in the secondary navigation. You will most likely find them in the more section of the secondary navigation. Please avoid creating settings in containers (a parent navigation node with children). These settings will still be shown, but this goes against the pattern that we are trying to establish for navigation around the site. If you have a lot of settings, consider creating a specific page to handle your additional settings.&lt;br /&gt;
** The order of the items in the secondary navigation may not be to your liking. This can be changed. See [[Moodle_4.0_developer_update#Changing_the_order_of_tabs|changing the order of tabs]]&lt;br /&gt;
* Update my behat tests to use new steps for site navigation. See [[Moodle_4.0_developer_update#Behat_changes|new behat steps]].&lt;br /&gt;
* Update my module to use the new activity_header API. See [[Moodle_4.0_developer_update#The_activity_header_class|the activity header]].&lt;br /&gt;
* Update my pages to make it work with the general format of the tertiary navigation. See [[Moodle_4.0_developer_update#Tertiary_navigation|the tertiary navigation]].&lt;br /&gt;
* Update my activity icon to use the API and set a purpose. See [[Moodle_4.0_developer_update#Activity_icons|activity icons]].&lt;br /&gt;
=== Themes ===&lt;br /&gt;
If you are a theme developer then you may want to consider the following:&lt;br /&gt;
* Take a look at the [[Moodle_4.0_developer_update#Navigation_changes|new navigation]] and decide if you want to incorporate this into your theme.&lt;br /&gt;
** A new layout ([[Moodle_4.0_developer_update#New_layout_page|drawers]])&lt;br /&gt;
** An [[Moodle_4.0_developer_update#Edit_switch|edit switch]]&lt;br /&gt;
** The [[Moodle_4.0_developer_update#The_course_index_element|course index]]&lt;br /&gt;
* Use of the flat nav&lt;br /&gt;
* New Site administration page and layout&lt;br /&gt;
* Course settings and how they are displayed&lt;br /&gt;
=== Course format ===&lt;br /&gt;
There have been a lot of changes made to the course format. Most in the process of moving the course format away from using the old rendering system and towards templates.&lt;br /&gt;
We recommend the following sections be read carefully:&lt;br /&gt;
# [[Moodle_4.0_developer_update#The_course_format_system|The course format]]. There have been a lot of deprecations and reading this section is critical in understanding the changes made.&lt;br /&gt;
# Consider moving the rendering of your content over to the [[Templates|template system]].&lt;br /&gt;
=== Other plugins ===&lt;br /&gt;
# Are you adding settings? See the [[Moodle_4.0_developer_update#Adding_items_to_the_navigation|secondary nav]] for adding items to this navigation bar.&lt;br /&gt;
# Have a look at [[Moodle_4.0_developer_update#Secondary_navigation|secondary]] and [[Moodle_4.0_developer_update#Tertiary_navigation|tertiary]] navigation changes in general if you have a plugin that has multiple pages to navigate around.&lt;br /&gt;
# Do you have behat tests? Check the new [[Moodle_4.0_developer_update#Behat_changes|behat changes]].&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61766</id>
		<title>Moodle 4.0 developer update</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61766"/>
		<updated>2022-03-04T06:27:23Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* The activity header class */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 4.0}}This page highlights the important changes that are coming in Moodle 4.0 for developers. Including how the UX improvements impact custom themes, relevant API changes, and what you can do as developer to prepare for the 4.0 release.&lt;br /&gt;
== Navigation changes ==&lt;br /&gt;
The core Navigation API has been left mostly untouched. The callbacks to all navigation callbacks remains unchanged and will be called as part of the regular &#039;navigation&#039; and &#039;settingsnav&#039; initialisation. Some new core classes have been created and exist within a new namespace &#039;core/navigation&#039; and serves as conduit to rearrange, cherry-pick existing navigation nodes from the navigation/settingsnav trees and display within the respective navigation type. As such, it is highly recommended to provide unique keys for custom navigation nodes as this helps in the cherry-picking / rearranging process within the new classes.&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
The primary navigation(the navbar) apart from the existing content will now display links to the Dashboard, My Courses, Site Admin and Course search, by default. You can still add items to the navbar via the &#039;custom menu&#039; option. This will be displayed within the &#039;More&#039; menu. We have transitioned the menus to be rendered via templates - refer user_menu.mustache. The lang menu has been moved to reside within the user menu.&lt;br /&gt;
==== Customising the primary navigation ====&lt;br /&gt;
Not yet implemented but we are looking at allowing the full addition and removal of any of the primary navigation tabs in the boost theme config file.&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
The main content area shows tabs for secondary navigation with a maximum of 5 items being rendered in this ‘more’ menu. A new UI component has been created to render menus like this. Files:&lt;br /&gt;
 /lib/templates/moremenu.mustache&lt;br /&gt;
==== Changing the order of tabs ====&lt;br /&gt;
Apart from the previously mentioned functions, you can also create a custom secondary class as mentioned earlier. This will automatically be picked by getter and used to render the secondary nav within the activity. E.g. mod_assign/local/views/secondary. Note: This is currently only possible on an activity and block level. &lt;br /&gt;
=== Tertiary navigation ===&lt;br /&gt;
=== New API functions ===&lt;br /&gt;
==== Page API ====&lt;br /&gt;
* Magic getters to fetch the primary and secondary navs and the primary output.&lt;br /&gt;
* The secondarynav magic getter also checks whether a custom secondary class has been defined within the module&#039;s local\views directory. Use this if you want to deviate from the standard secondary nav structure/order.&lt;br /&gt;
&lt;br /&gt;
* set_secondary_nav - Force override the secondary navigation class&lt;br /&gt;
&lt;br /&gt;
* has_secondary_navigation_setter - Sets the ‘_hassecondarynavigation’ to indicate whether a page should render the secondary navigation&lt;br /&gt;
==== Navigationlib ====&lt;br /&gt;
* set_show_in_secondary_navigation - whether or not a node should be displayed in the secondary nav. Accepts a single boolean argument&lt;br /&gt;
* set_force_into_more_menu- whether or not to force a node into the &#039;More&#039; menu. Accepts a single boolean argument&lt;br /&gt;
==== The activity header class ====&lt;br /&gt;
There is a new activity header class that handles the display of information common to activities. 3rd party activities are not required to explicitly output this information as part of rendering individual pages.&lt;br /&gt;
&lt;br /&gt;
The common information that are currently handled by the class are:&lt;br /&gt;
&lt;br /&gt;
* title&lt;br /&gt;
* description&lt;br /&gt;
* completion information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As part of the update it was required that the initial information to be displayed by the class be toggable at a theme and layout level. Taking this into account the following theme level configurable exists:&lt;br /&gt;
&lt;br /&gt;
* activityheaderconfig =&amp;gt; An array that currently only enforces &#039;notitle&#039; but can be expanded in the future  NOTE: Boost has this set as true by default &#039;options&#039;&lt;br /&gt;
&lt;br /&gt;
The following layout level options that can be defined:&lt;br /&gt;
&lt;br /&gt;
* noactivityheader - to remove the header in this specific layout.&lt;br /&gt;
* activityheader - An array that enforces the following options:&lt;br /&gt;
** notitle&lt;br /&gt;
** nocompletion&lt;br /&gt;
** nodescription&lt;br /&gt;
&lt;br /&gt;
The class has a page level getter which you can use to fetch the current version of the class. The base state is initialised within the constructor with the completion information only fetched when data is exported for the template.&lt;br /&gt;
&lt;br /&gt;
The class has setters for the following variables which can be leveraged to modify the header for a particular page in the format set_{variable_name}:&lt;br /&gt;
&lt;br /&gt;
* hidecompletion&lt;br /&gt;
* description&lt;br /&gt;
* title&lt;br /&gt;
&lt;br /&gt;
Alternately, bulk operations can also be done by passing the above variables in an array to &#039;set_attrs&#039; which in turn calls the setters.&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note: Any updates to the activityheader needs to be performed before the call to $OUTPUT-&amp;gt;header&#039;&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Theme updates: =====&lt;br /&gt;
In order for 3rd party themes to use the class they need to export the activity_header and include the following into their base template :&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
   {{&amp;gt; core/activity_header}}&lt;br /&gt;
{{#headercontent}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;** headercontent being the array element that contains the exported activity_header data &lt;br /&gt;
&lt;br /&gt;
===== Accessibility notes: =====&lt;br /&gt;
The jump to ‘maincontent’ div is now rendered within the activity header when within an activity context&lt;br /&gt;
== Component library ==&lt;br /&gt;
Each Moodle installation now ships with a Moodle User Interface (UI) Component library, a documentation system used to describe all the Bootstrap components and the custom Moodle components. The component Library is a helper tool for developers when creating user interfaces, a testing tool for theme developers and a documentation tool for core developers. The ultimate goal of having a component library is to encourage developers to create consistent user interfaces to improve Moodle’s overall user experience.&lt;br /&gt;
&lt;br /&gt;
The library contains pages with documentation about User Interface components. It contains details on how to use the component, what variations are available and the JavaScript events / options are associated with the component.&lt;br /&gt;
&lt;br /&gt;
When writing on these pages it is possible to render core mustache templates using some custom syntax like this:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; mustache template=&amp;quot;core/notification_error&amp;quot; &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt; /mustache &amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also call core JavaScript or use HTML examples where the html code and the rendered result are visible in the Component Library. For more info visit the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-templates/ Moodle templates] page or the [http://componentlibrary.moodle.com/admin/tool/componentlibrary/docspage.php/library/moodle-javascript/ Moodle JavaScript] page.&lt;br /&gt;
&lt;br /&gt;
Each page in the library uses the current css from the default theme in your Moodle installation, if you have multiple themes installed and enabled the setting &amp;quot;Allow theme changes on url&amp;quot;, the component library will have a theme selector option.&lt;br /&gt;
&lt;br /&gt;
A hosted version of the Component Library can be found here. http://componentlibrary.moodle.com&lt;br /&gt;
=== Enabling the Component Library ===&lt;br /&gt;
Component library pages are written in the markdown language. These pages need to be compiled to HTML pages before the Component Library is visible. To compile the pages the server running Moodle needs to have the [[Javascript Modules#Install%20NVM%20and%20Node|JavaScript developer tools installed]] (nodeJs and Grunt)&lt;br /&gt;
&lt;br /&gt;
If your server meets all requirements you can enable the library running&lt;br /&gt;
 $ npm install&lt;br /&gt;
 $ grunt componentlibrary&lt;br /&gt;
Further installation instructions can be found in the Component Library itself.&lt;br /&gt;
=== Documenting new UI Components ===&lt;br /&gt;
There are no set rules for adding new pages in the component library yet. These rules will need to be written and adopted in the integration process for Moodle code.&lt;br /&gt;
&lt;br /&gt;
As a guideline for making this rules consideration are:&lt;br /&gt;
&lt;br /&gt;
The component library is not about single use components, for example the Moodle grade book (a huge component with many custom features). Or about very common components like buttons, these are already covered by the Bootstrap section of the component library.&lt;br /&gt;
&lt;br /&gt;
New features should be build keeping in mind the UI part needs to be customisable and if possible (and making sense) reusable. And example would be the new page drawers that we are introducing for the Navigation project. Or the custom primary navigation menus where overflowing items are pushed into a More section.&lt;br /&gt;
== Theme changes ==&lt;br /&gt;
=== Edit switch ===&lt;br /&gt;
On theme boost the “Turn editing on” and “Customise this page” buttons have been replaced by an edit switch in the top navbar. Theme Classic will keep using the old buttons. Child themes can choose to use the edit switch if the theme config.php is using this variable&lt;br /&gt;
 $THEME-&amp;gt;haseditswitch = true;&lt;br /&gt;
The languague menu, which used to be rendered in place of the custom menu has moved to the user dropdown when the user is logged in. If not logged in it will be placed next to the search / notification / messaging icon in the top navbar.&lt;br /&gt;
=== Login page ===&lt;br /&gt;
The login page has been redesigned and allows the admin to configure a background image for the login page only in the theme settings page. This change is available in both Boost and Classic. The login page still has all the features with an improved layout. &lt;br /&gt;
=== The page footer ===&lt;br /&gt;
In large screens, the page footer button is only visible when clicking a help button at the bottom right of the screen.&lt;br /&gt;
=== User initials as profile picture placeholder ===&lt;br /&gt;
If users do not upload a profile picture the user initials are displayed on a rounded gray background as a placeholder picture in the top navbar or any other page using a placeholder image. This change will be available in both Boost and Classic. &lt;br /&gt;
&lt;br /&gt;
With the introduction of this placeholder image the full username will no longer be displayed in the top navbar.&lt;br /&gt;
=== Removal of back to top link ===&lt;br /&gt;
The &amp;quot;back to top&amp;quot; link will be removed for theme boost since the new course index reduced the dependence on page scrolling. Also, the new footer is positioned where this component used to be.&lt;br /&gt;
=== Styling changes ===&lt;br /&gt;
By default rounded edges will be used for UI components, for the page header and main content area the borders will be removed. &lt;br /&gt;
=== New layout page ===&lt;br /&gt;
Theme boost now uses the drawers.php layout for the course index and blocks.&lt;br /&gt;
== The course format system ==&lt;br /&gt;
Most of the logic for rendering and editing a course has been moved to a new subsystem called courseformat. The subsystem is located in &amp;quot;course/format&amp;quot; folder so it includes all the format plugins inside. The methods and modules which are distributed between the course and the course/format folders are now rearranged or refactored to be aligned with the current Moodle coding style.&lt;br /&gt;
=== Mandatory renderer in course formats ===&lt;br /&gt;
Now format plugins renderer is not optional anymore. Legacy formats without a renderer will get a deprecation message but it will continue working however, they should create a new renderer as soon as possible. The section-based format can do it by extending the provided core_courseformat\output\section_renderer class which includes all the necessary methods.&lt;br /&gt;
=== New format base class ===&lt;br /&gt;
The old base_format class (which all plugins extend) is now renamed as core_courseformat\base. The new class provides all the functionally of the previous base_format but it has been refactored to be used as a centralized source of truth for the course rendering. Legacy formats should extend the new class to avoid the deprecation message.&lt;br /&gt;
&lt;br /&gt;
Now, the plugin format class provides information such as:&lt;br /&gt;
* If the page is displaying a single or multiple section&lt;br /&gt;
* Give access to other related format objects like the modinfo, the course record, maximum number of sections...&lt;br /&gt;
* If the format is compatible with features like course index, reactive components, ajax...&lt;br /&gt;
* Other format specifics like the page title, the default section name, default blocks...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The format instance is now the main object output components will use to render a course (see next section for more information).&lt;br /&gt;
=== New course output classes and mustache files ===&lt;br /&gt;
Traditionally, section-based course formats uses print_single_section_page and print_multiple_section_page to render the course content. In Moodle 4.0 most of the course rendering methods are migrated to output components and mustache templates. The old methods will get deprecation messages if they use the old renderer methods.&lt;br /&gt;
&lt;br /&gt;
This is an example of a format rendering a course:&amp;lt;syntaxhighlight lang=&amp;quot;php-brief&amp;quot;&amp;gt;&lt;br /&gt;
// Get the course format instance.&lt;br /&gt;
$format = course_get_format($course);&lt;br /&gt;
&lt;br /&gt;
// Get the specific format renderer.&lt;br /&gt;
$renderer = $format-&amp;gt;get_renderer($PAGE);&lt;br /&gt;
&lt;br /&gt;
if (!empty($displaysection)) {&lt;br /&gt;
    // Setup the format instance to display a single section.&lt;br /&gt;
    $format-&amp;gt;set_section_number($displaysection);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Create the ouptut instance and render it.&lt;br /&gt;
$outputclass = $format-&amp;gt;get_output_classname(&#039;content&#039;);&lt;br /&gt;
$widget = new $outputclass($format);&lt;br /&gt;
&lt;br /&gt;
echo $renderer-&amp;gt;render($widget);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Format plugins are free to use its own output classes to render a course, or they could override the existing output classes by providing their own implementation. For example, the default output for &amp;quot;content&amp;quot; (as in the previous example) is &amp;quot;core_courseformat\output\local\|content&amp;quot;, however, if the plugin has a &amp;quot;format_XXX\output\courseformat\content&amp;quot; class, the $format-&amp;gt;class the get_output_class will return the overridden one.&lt;br /&gt;
Another important update on course rendering is that now all course structure is rendered using mustache templates instead of the original html_writer methods. Now themes are able to override the course format by providing alternative versions of the mustache files. All core course templates are located in &amp;quot;course/format/templates&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All the new output classes and a guide on how to migrate the current third-party plugins will be available soon.&lt;br /&gt;
=== Course editor javascript modules and frontend components ===&lt;br /&gt;
The majority of the javascript logic related to the course editing is replaced by AMD modules. Because this is a major change in the way courses are edited and rendered, by default format plugins will continue using the previous YUI modules for now. However, formats can start using the new libraries overriding the &amp;quot;$format-&amp;gt;supports_components()&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Some Moodle 4.0 new features are only available for courses using the new editor library:&lt;br /&gt;
* Edit the course via the course index&lt;br /&gt;
* Creating sections without reloading the course page&lt;br /&gt;
* The new move section/activity modal&lt;br /&gt;
* Native browser drag&amp;amp;drop implementation&lt;br /&gt;
The new course editor uses a component-based reactive pattern to keep track of the course changes. The pattern highlights are:&lt;br /&gt;
* The main AMD module &amp;quot;core_crouseformat\courseeditor&amp;quot; maintains a data structure called state.&lt;br /&gt;
* Each UI element is implemented as a Component that observes the course state data and reacts to any data change&lt;br /&gt;
* When any reactive component needs to modify the course, it asks the course editor to execute a mutation. Mutations encapsulate all web services calls and alter the course state data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The reactive library documentation, as well as the format plugin migration guide, will be available soon.&lt;br /&gt;
=== Other course related 4.0 changes ===&lt;br /&gt;
Two new web services have been added:&lt;br /&gt;
* core_courseformat_get_state: user by the new javascript course editor to get the current course state data (containing the list of sections, activities, and other course-related data)&lt;br /&gt;
* core_courseformat_update_course: to alter the current course content. Each call returns the parts of the course state altered by the action&lt;br /&gt;
== Behat changes ==&lt;br /&gt;
To make behat tests more readable and easy to maintain, it is recommended to use the most direct steps to get what the test needs. It is highly recommended to use&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
instead of navigating to the activity via&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
Now that [https://docs.moodle.org/dev/Prototypes#Course_creation_improvements Course index] is integrated these behat steps&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
will fail using Boost theme.&lt;br /&gt;
&lt;br /&gt;
The reason for it is that the drawer used in Boost is hiding the course index. So when the test is trying to follow an &amp;quot;Activity name&amp;quot; link, it finds two different links:&lt;br /&gt;
* one in the course index&lt;br /&gt;
* another one in the course main content.&lt;br /&gt;
But the first one, the one in the course index, is hidden by the drawer, and the test fails.&lt;br /&gt;
&lt;br /&gt;
However the recommended behat steps&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
Old behat steps that may now fail can be updated to the new steps.&lt;br /&gt;
For example:&lt;br /&gt;
 And I am on the &amp;quot;Test assignment name&amp;quot; &amp;quot;assign activity&amp;quot; page logged in as teacher1&lt;br /&gt;
instead of:&lt;br /&gt;
 When I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
 And I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 And I follow &amp;quot;Test assignment name&amp;quot;&lt;br /&gt;
== Other ==&lt;br /&gt;
=== Core plugins review ===&lt;br /&gt;
A few plugins from core Moodle LMS which are no longer or hardly used have been removed and, if appropriate, added to the Moodle plugins directory.&lt;br /&gt;
&lt;br /&gt;
More information about this project, the list of plugins to be removed and the process to follow for keeping them before upgrading to 4.0 can be found in the [[Core plugins review]] page.&lt;br /&gt;
=== Site admin presets plugin ===&lt;br /&gt;
The third-party plugin [https://moodle.org/plugins/block_admin_presets Admin presets], created by David Monllaó and maintained by developers from [https://pimenko.com/ Pimenko] has been adapted and integrated into Moodle 4.0. It stores settings and plugins status (enabled/disabled) in what&#039;s called &amp;quot;presets&amp;quot; to let admins quickly switch between different configurations.&lt;br /&gt;
&lt;br /&gt;
More information about this project can be found in the [[Site admin presets|Site admin presets plugin]] page.&lt;br /&gt;
=== JavaScript browser support changes ===&lt;br /&gt;
From Moodle 4.0, Internet Explorer is no longer supported. See MDL-73915 and MDLSITE-6109 for further information on this change.&lt;br /&gt;
&lt;br /&gt;
This change means that changes built on 4.0 onwards (including the master branch) will be different to older versions of Moodle.&lt;br /&gt;
&lt;br /&gt;
For plugin developers supporting multiple versions of Moodle using a single plugin version, the compiled javascript files are backwards compatible and will _work_ on all supported versions, however if you run the `grunt` command on multiple versions you will see unbuilt changes. Running grunt on all versions of Moodle is not necessary and this check can be safely disabled for Moodle versions 3.9 - 4.0, as long as only at least you run `grunt` against at least one version of Moodle.&lt;br /&gt;
&lt;br /&gt;
If you need to support Internet Explorer and do not wish to fork your plugin for Moodle 4.0 onwards, then it is recommended that you run `grunt` on an older version of Moodle.&lt;br /&gt;
=== The course index element ===&lt;br /&gt;
The new course index feature can be themed using a set of scss variables. Use them to change the look and feel instead of adding custom css&lt;br /&gt;
 /theme/boost/scss/moodle/courseindex.scss&lt;br /&gt;
With the introduction of the course index component, the previous and next links shown underneath each activity are no longer needed and they will be removed.&lt;br /&gt;
=== Activity icons ===&lt;br /&gt;
The icons used for activities have been redesigned and updated for all core moodle activities.&lt;br /&gt;
&lt;br /&gt;
When viewing the new icons in a file manager, for example for the quiz activity, you will see a simple black monochrome icon with a transparent background.&lt;br /&gt;
&lt;br /&gt;
On the course page, or in the activity chooser, the icon will display as a white icon on a coloured background. Styling of the icons on the coursepage is controlled by the css in theme/boost/scss/moodle/icons.scss.&lt;br /&gt;
&lt;br /&gt;
The background colour for activity icons is set using a new variable in function [modname]_supports(). The quiz activity is of type assessment, so in function quiz_supports() there is a new line defining the purpose:&lt;br /&gt;
 case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_ASSESSMENT;&lt;br /&gt;
Available purposes are:&lt;br /&gt;
* MOD_PURPOSE_COMMUNICATION&lt;br /&gt;
* MOD_PURPOSE_ASSESSMENT&lt;br /&gt;
* MOD_PURPOSE_COLLABORATION&lt;br /&gt;
* MOD_PURPOSE_CONTENT&lt;br /&gt;
* MOD_PURPOSE_ADMINISTRATION&lt;br /&gt;
* MOD_PURPOSE_INTERFACE&lt;br /&gt;
The background colours linked to these purposes are set in theme/boost/scss/moodle/variables.scss&lt;br /&gt;
 $activity-icon-colors: map-merge(&lt;br /&gt;
     (&lt;br /&gt;
         &amp;quot;administration&amp;quot;: #5d63f6,&lt;br /&gt;
         &amp;quot;assessment&amp;quot;: #eb66a2,&lt;br /&gt;
         &amp;quot;collaboration&amp;quot;: #f7634d,&lt;br /&gt;
         &amp;quot;communication&amp;quot;: #11a676,&lt;br /&gt;
         &amp;quot;content&amp;quot;: #399be2,&lt;br /&gt;
         &amp;quot;interface&amp;quot;: #a378ff&lt;br /&gt;
     ),&lt;br /&gt;
     $activity-icon-colors&lt;br /&gt;
 );&lt;br /&gt;
If activity plugins do not define FEATURE_MOD_PURPOSE the activity icon will be rendered against a light grey background. There is no requirement to define the purpose of activity plugins, it will only affect the icon styling.&lt;br /&gt;
&lt;br /&gt;
Plugins implementing the variable FEATURE_MOD_PURPOSE are only supported on Moodle 4.0 and newer.&lt;br /&gt;
&lt;br /&gt;
Customising the activity icon can be done in an alternative way. For example using the styles.css in mod/[pluginname/styles.css&lt;br /&gt;
&lt;br /&gt;
In the example below the activity plugin developer chooses to keep the coloured icon for the activity and render it as large as the coloured background on the core activities&lt;br /&gt;
 .modicon_subcourse.activityiconcontainer {&lt;br /&gt;
     background-color: transparent;&lt;br /&gt;
     padding: 0;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 .modicon_subcourse.activityiconcontainer img {&lt;br /&gt;
     width: 50px;&lt;br /&gt;
     height: 50px;&lt;br /&gt;
 }&lt;br /&gt;
To customize all icon colours use this scss array and add it to the ‘Raw initial SCSS’ in the theme Boost advanced settings page. The complete array of icon background colours can be overridden using the ‘Raw initial SCSS’ in the theme settings page. The example below changes the colours of each activity type.&lt;br /&gt;
 $activity-icon-colors: (&lt;br /&gt;
     &amp;quot;administration&amp;quot;: #5D63F6,&lt;br /&gt;
     &amp;quot;assessment&amp;quot;: #11A676,&lt;br /&gt;
     &amp;quot;collaboration&amp;quot;: #EB66A2,&lt;br /&gt;
     &amp;quot;communication&amp;quot;: #F7634D,&lt;br /&gt;
     &amp;quot;content&amp;quot;: #399BE2,&lt;br /&gt;
     &amp;quot;interface&amp;quot;: #A378FF&lt;br /&gt;
 )&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61206</id>
		<title>Moodle 4.0 developer update</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_developer_update&amp;diff=61206"/>
		<updated>2021-09-02T13:17:54Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Navigation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 4.0}}This page will highlight the important changes that are coming in Moodle 4.0 for developers. Including how the UX improvements impact custom themes, relevant API changes, and what you can do as developer to prepare for the 4.0 release.&lt;br /&gt;
== UX and theme changes ==&lt;br /&gt;
== Component library ==&lt;br /&gt;
== Navigation ==&lt;br /&gt;
The core Navigation API has been left mostly untouched. The callbacks to all navigation callbacks remains unchanged and will be called as part of the regular &#039;navigation&#039; and &#039;settingsnav&#039; initialisation. Some new core classes have been created and exist within a new namespace &#039;core/navigation&#039; and serves as conduit to rearrange, cherry-pick existing navigation nodes from the navigation/settingsnav trees and display within the respective navigation type. As such, it is highly recommended to provide unique keys for custom navigation nodes as this helps in the cherry-picking / rearranging process within the new classes.&lt;br /&gt;
&lt;br /&gt;
===== Primary navigation / Primary Output =====&lt;br /&gt;
The primary navigation(the navbar) apart from the existing content will now display links to the Dashboard, My Courses, Site Admin and Course search, by default. You can still add items to the navbar via the &#039;custom menu&#039; option. This will be displayed within the &#039;More&#039; menu. We have transitioned the menus to be rendered via templates - refer user_menu.mustache. The lang menu has been moved to reside within the user menu.&lt;br /&gt;
&lt;br /&gt;
===== New view =====&lt;br /&gt;
All settings for courses/modules will now be displayed as tabs within the module. A predefined set of tabs will be shown with any remaining / newly added ones residing within the &#039;Course Admin&#039; page. The settings cog will not be shown anymore. It is recommended to review any settings as some might be displayed as tabs and possibly move them to the tertiary navigation as is done in the core activity modules&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;. At most 5 tabs will be displayed to a user with all the overflow nodes now residing within the &#039;More&#039; menu. Some of the nodes can be hidden by using the new functions defined. &lt;br /&gt;
&lt;br /&gt;
===== New API functions =====&lt;br /&gt;
&lt;br /&gt;
====== Page API ======&lt;br /&gt;
&lt;br /&gt;
* Magic getters to fetch the primary and secondary navs and the primary output.&lt;br /&gt;
* The secondarynav magic getter also checks whether a custom secondary class has been defined within the module&#039;s local\views directory. Use this if you want to deviate from the standard secondary nav structure/order.&lt;br /&gt;
&lt;br /&gt;
* set_secondary_nav - Force override the secondary navigation class&lt;br /&gt;
&lt;br /&gt;
* has_secondary_navigation_setter - Sets the ‘_hassecondarynavigation’ to indicate whether a page should render the secondary navigation&lt;br /&gt;
&lt;br /&gt;
====== Navigationlib ======&lt;br /&gt;
&lt;br /&gt;
* set_show_in_secondary_navigation - whether or not a node should be displayed in the secondary nav. Accepts a single boolean argument&lt;br /&gt;
* set_force_into_more_menu- whether or not to force a node into the &#039;More&#039; menu. Accepts a single boolean argument&lt;br /&gt;
&lt;br /&gt;
===== Changing order of tabs in secondary navigation nodes =====&lt;br /&gt;
Apart from the previously mentioned functions, you can also create a custom secondary class as mentioned earlier. This will automatically be picked by getter and used to render the secondary nav within the activity. E.g. mod_assign/local/views/secondary. Note: This is currently only possible on an activity and block level. &lt;br /&gt;
&lt;br /&gt;
===== Upcoming changes: =====&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;sup&amp;gt;1 -&amp;lt;/sup&amp;gt; Complete tertiary nav overhaul for core’s modules - [https://tracker.moodle.org/browse/MDL-71912 MDL-71912]. [https://tracker.moodle.org/browse/MDL-71913 MDL-71913],[https://tracker.moodle.org/browse/MDL-71914 MDL-71914],[https://tracker.moodle.org/browse/MDL-71915 MDL-71915]&lt;br /&gt;
# Backwards compatibility for complex deep nested custom navigation. Any custom navigation added by 3rd party devs will now be displayed as flatter structure within a URL select - [https://tracker.moodle.org/browse/MDL-72352 MDL-72352]&lt;br /&gt;
# New module API to inject common content at the top of a module page. The common content would be the title, description and activity information. This solves 2 issues:&lt;br /&gt;
## A centralised location where we can handle #2 and inject it into the relevant page&lt;br /&gt;
## A centralised location where we can inject items particularly activity_information without the need to be replicated in each module. &lt;br /&gt;
&lt;br /&gt;
== The core_courseformat subsystem ==&lt;br /&gt;
Most of the logic for rendering and editing a course has been moved to a new subsystem called courseformat. The subsystem is located in &amp;quot;course/format&amp;quot; folder so it includes all the format plugins inside. The methods and modules which are distributed between the course and the course/format folders are now rearranged or refactored to be aligned with the current Moodle coding style.&lt;br /&gt;
==== Mandatory renderer in course formats ====&lt;br /&gt;
Now format plugins renderer is not optional anymore. Legacy formats without a renderer will get a deprecation message but it will continue working however, they should create a new renderer as soon as possible. The section-based format can do it by extending the provided core_courseformat\output\section_renderer class which includes all the necessary methods.&lt;br /&gt;
==== New format base class ====&lt;br /&gt;
The old base_format class (which all plugins extend) is now renamed as core_courseformat\base. The new class provides all the functionally of the previous base_format but it has been refactored to be used as a centralized source of truth for the course rendering. Legacy formats should extend the new class to avoid the deprecation message.&lt;br /&gt;
&lt;br /&gt;
Now, the plugin format class provides information such as:&lt;br /&gt;
* If the page is displaying a single or multiple section&lt;br /&gt;
* Give access to other related format objects like the modinfo, the course record, maximum number of sections...&lt;br /&gt;
* If the format is compatible with features like course index, reactive components, ajax...&lt;br /&gt;
* Other format specifics like the page title, the default section name, default blocks...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The format instance is now the main object output components will use to render a course (see next section for more information).&lt;br /&gt;
==== New course output classes and mustache files ====&lt;br /&gt;
Traditionally, section-based course formats uses print_single_section_page and print_multiple_section_page to render the course content. In Moodle 4.0 most of the course rendering methods are migrated to output components and mustache templates. The old methods will get deprecation messages if they use the old renderer methods.&lt;br /&gt;
&lt;br /&gt;
This is an example of a format rendering a course:&amp;lt;syntaxhighlight lang=&amp;quot;php-brief&amp;quot;&amp;gt;&lt;br /&gt;
// Get the course format instance.&lt;br /&gt;
$format = course_get_format($course);&lt;br /&gt;
&lt;br /&gt;
// Get the specific format renderer.&lt;br /&gt;
$renderer = $format-&amp;gt;get_renderer($PAGE);&lt;br /&gt;
&lt;br /&gt;
if (!empty($displaysection)) {&lt;br /&gt;
    // Setup the format instance to display a single section.&lt;br /&gt;
    $format-&amp;gt;set_section_number($displaysection);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Create the ouptut instance and render it.&lt;br /&gt;
$outputclass = $format-&amp;gt;get_output_classname(&#039;content&#039;);&lt;br /&gt;
$widget = new $outputclass($format);&lt;br /&gt;
&lt;br /&gt;
echo $renderer-&amp;gt;render($widget);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Format plugins are free to use its own output classes to render a course, or they could override the existing output classes by providing their own implementation. For example, the default output for &amp;quot;content&amp;quot; (as in the previous example) is &amp;quot;core_courseformat\output\local\|content&amp;quot;, however, if the plugin has a &amp;quot;format_XXX\output\courseformat\content&amp;quot; class, the $format-&amp;gt;class the get_output_class will return the overridden one.&lt;br /&gt;
Another important update on course rendering is that now all course structure is rendered using mustache templates instead of the original html_writer methods. Now themes are able to override the course format by providing alternative versions of the mustache files. All core course templates are located in &amp;quot;course/format/templates&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All the new output classes and a guide on how to migrate the current third-party plugins will be available soon.&lt;br /&gt;
==== Course editor javascript modules and frontend components ====&lt;br /&gt;
The majority of the javascript logic related to the course editing is replaced by AMD modules. Because this is a major change in the way courses are edited and rendered, by default format plugins will continue using the previous YUI modules for now. However, formats can start using the new libraries overriding the &amp;quot;$format-&amp;gt;supports_components()&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Some new feature of Moodle 4.0 are only available for courses using the new editor library:&lt;br /&gt;
* Edit the course via the course index&lt;br /&gt;
* Creating sections without reloading the course page&lt;br /&gt;
* The new move section/activity modal&lt;br /&gt;
* Native browser drag&amp;amp;drop implementation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The new course editor uses a component-based reactive pattern to keep track of the course changes.&lt;br /&gt;
==== Other course related 4.0 changes ====&lt;br /&gt;
* New web services&lt;br /&gt;
== API changes ==&lt;br /&gt;
== Behat changes ==&lt;br /&gt;
To make behat tests more readable and easy to maintain, it is recommended to use the most direct steps to get what the test needs. So since MDL-66335 was integrated, and the step was improved in MDL-72179 is highly recommended to use&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
instead of navigating to the activity via&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
Now that [https://docs.moodle.org/dev/Prototypes#Course_creation_improvements Course index] (MDL-71209) is integrated but the project is not stable, these behat steps&lt;br /&gt;
 I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 I follow &amp;quot;Activity name&amp;quot;&lt;br /&gt;
will fail using Boost theme.&lt;br /&gt;
&lt;br /&gt;
The reason for it is that the drawer used in Boost is hiding the course index. So when the test is trying to follow an &amp;quot;Activity name&amp;quot; link, it finds two different links:&lt;br /&gt;
* one in the course index&lt;br /&gt;
* another one in the course main content.&lt;br /&gt;
But the first one, the one in the course index, is hidden by the drawer, and the test fails.&lt;br /&gt;
&lt;br /&gt;
However the recommended behat steps&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page &lt;br /&gt;
or&lt;br /&gt;
 I am on the &amp;quot;Activity name&amp;quot; &amp;quot;[modname] activity&amp;quot; page logged in as &amp;quot;user&amp;quot;&lt;br /&gt;
work &#039;&#039;&#039;fine&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Some of the failing behats are fixed in https://github.com/ferranrecio/moodle/commit/c79d58a50b48aa6891ff1d3ba92a7b0ab2393c88#diff-fdf8b0b1eade3b69eaad038de0ddd7c8dec2be7afa32dc693fb929739a49fa9dR32 - MDL-71209&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
 And I am on the &amp;quot;Test assignment name&amp;quot; &amp;quot;assign activity&amp;quot; page logged in as teacher1&lt;br /&gt;
instead of:&lt;br /&gt;
 When I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
 And I am on &amp;quot;Course&amp;quot; course homepage&lt;br /&gt;
 And I follow &amp;quot;Test assignment name&amp;quot;&lt;br /&gt;
== Core plugins review ==&lt;br /&gt;
A few plugins from core Moodle LMS which are no longer or hardly used have been removed and, if appropriate, added to the Moodle plugins directory.&lt;br /&gt;
&lt;br /&gt;
More information about this project, the list of plugins to be removed and the process to follow for keeping them before upgrading to 4.0 can be found in the [[Core plugins review]] page.&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_navigation_improvements&amp;diff=60543</id>
		<title>Moodle 4.0 navigation improvements</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_navigation_improvements&amp;diff=60543"/>
		<updated>2021-08-06T06:52:53Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Technical design of *_navigation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|state = In progress&lt;br /&gt;
|name = Update general Moodle navigation&lt;br /&gt;
|tracker = MDL-69588 (epic)&lt;br /&gt;
|discussion = [https://moodle.org/mod/forum/discuss.php?d=418328 Navigation for Moodle 4.0]&lt;br /&gt;
|assignee = Team Alpha&lt;br /&gt;
}}&lt;br /&gt;
{{Template:Moodle 4.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
With the incoming release of Moodle 4.0, it is our desire to improve the user experience surrounding the navigation of courses, modules and other key areas by reducing the cognitive load upon users when navigating. These improvements will only be made to the existing primary Moodle theme: Boost. Whilst the primary focus is upon Boost it is our goal that the theme Classic will retain its current functionality.&lt;br /&gt;
The overall aim of this project is to create a simplified navigation hierarchy where:&lt;br /&gt;
* Users no longer feel overwhelmed by numerous pathways to get to a single destination&lt;br /&gt;
* Navigation pathways follow common patterns all throughout Moodle&lt;br /&gt;
* Navigation options presented to the user are contextually relevant; so that users intuitively and quickly learn how to get to where they need to be&lt;br /&gt;
* Navigation has a consistent look and feel between desktop sized viewports &amp;amp; mobile sized viewports&lt;br /&gt;
The focus of this project is on the student and teacher navigation experience.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Prototype / mock-ups ==&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
Across all of Moodle the header of the site will be changed for 4.0 with important navigation elements being rendered within the header of Moodle.&lt;br /&gt;
With this change to navigation new active and hover states will be created to inform users of where they currently are and where they are navigating to at a glance.&lt;br /&gt;
&lt;br /&gt;
When the amount of navigation items exceeds the width of the viewport width then a new dynamic menu item will appear that navigation elements overflow into.&lt;br /&gt;
&lt;br /&gt;
On mobile devices it is expected that within Moodle the primary navigation will be rendered as a navigation drawer in the same fashion as the current navigation drawer.&lt;br /&gt;
&lt;br /&gt;
The image below shows a prototype for Moodle 4.0 with navigation within the header for the page, it also includes custom menu elements to demonstrate that existing functionality is being accounted for.&lt;br /&gt;
==== Desktop primary navigation ====&lt;br /&gt;
[[File:Primary.png]]&lt;br /&gt;
==== Mobile primary navigation ====&lt;br /&gt;
Primary navigation (mobile device inactive)&lt;br /&gt;
[[File:Primary_mobile_inactive.png]]&lt;br /&gt;
&lt;br /&gt;
Primary navigation (mobile device active)&lt;br /&gt;
[[File:Primary_mobile_active.png]]&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
Navigation items will now appear as tabs within the context header (Course header, Site admin header, etc...) and similar to the primary navigation the active element will have an indicator below the active tab and have hover styling that indicates the potential tab item that’ll be navigated to.&lt;br /&gt;
&lt;br /&gt;
Also similar to the primary navigation a dynamic “More” menu will be implemented to accommodate navigation elements when the viewport width reduces to a point where elements can not feasibly be shown within the menu area. At most 5 tabs will be shown excluding the &#039;More&#039; menu/tab. Any extra tabs will now reside within the &#039;More&#039; menu.&lt;br /&gt;
&lt;br /&gt;
The secondary navigation will appear in most cases and specifically in System, Course, Module and Category contexts. However in other situations and other contexts it does not make sense to show the secondary navigation either from a UX perspective OR because of multiple entry points into the respective page. e.g. user profile page and blocks.&lt;br /&gt;
&lt;br /&gt;
The below image shows the secondary navigation within the page header, this will look similar to the above primary navigation image.&lt;br /&gt;
==== Desktop secondary navigation ====&lt;br /&gt;
[[File:Secondary.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Page header (Context header) ===&lt;br /&gt;
Work here will primarily focus on user interactions with the context header such as automatic hiding and displaying of elements depending on the users&#039; scrolling and page position. Other changes will include rearranging elements, modifying font sizing, weight and spacing around the current page name.&lt;br /&gt;
&lt;br /&gt;
The below image shows the page header on a mobile device as the desktop viewport examples can be seen in the prior images.&lt;br /&gt;
==== Mobile view page header ====&lt;br /&gt;
[[File:Mobile_context.png]]&lt;br /&gt;
==== Breadcrumbs ====&lt;br /&gt;
Breadcrumbs are being changed to follow the guidelines set in [https://www.nngroup.com/articles/breadcrumbs/ Nielsen Norman Group - Breadcrumbs: 11 Design Guidelines]&lt;br /&gt;
&lt;br /&gt;
A few of the changes being implemented:&lt;br /&gt;
# Remove entries without any links&lt;br /&gt;
# Remove the link from the last item in the list as this defines the page a user is already on&lt;br /&gt;
# Remove breadcrumbs from the course index page as this can be accessed via the primary navigation links as a new root page.&lt;br /&gt;
# Remove breadcrumbs from site admin pages as navigation can be done via the secondary navigation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User stories ==&lt;br /&gt;
These are the user stories that this project aims to address.&lt;br /&gt;
=== For the student ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Student user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to easily move between courses and activities so that I can focus on learning.&lt;br /&gt;
| I should be able to easily see my list of courses in a predictable place and be able to jump from one course to another or one activity to another at speed.&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to view my grades within a course so that I know how I am doing.&lt;br /&gt;
| Within the course context I should be able to click straight through to my grade overview.&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to view my grades for a forum activity, so that I can receive feedback on my participation.&lt;br /&gt;
| Within a forum activity I should be able to view my grades using the existing forum grading functionality.&lt;br /&gt;
|}&lt;br /&gt;
=== For the course creator / teacher ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Course creator / teacher user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily move between courses and activities so that I can focus on course creation or facilitation.&lt;br /&gt;
| I should be able to easily see my list of courses in a predictable place and be able to jump from one course to another at speed.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access the course settings so that I can make changes as necessary.&lt;br /&gt;
| Within a course, the course settings should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access activity settings so that I can make changes as necessary.&lt;br /&gt;
| Within a course activity or resource, the settings should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access course reports so that I can review my students&#039; activity.&lt;br /&gt;
| Within a course, the reports should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access the course gradebook so that I can check my students&#039; grades.&lt;br /&gt;
| Within a course, the gradebook should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily grade a student&#039;s forum posts, so that I can provide them with feedback on their participation.&lt;br /&gt;
| Within a forum activity, I can open the forum grading functionality and give each students a grade.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to be able to easily add new content or modify existing content in a course so that I can update the course as necessary.&lt;br /&gt;
| Within a course, I can easily turn on course editing to add or edit activities and resources.&lt;br /&gt;
|}&lt;br /&gt;
=== For the administrator ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Administrator user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a site administrator, I want to be able to easily access site administration settings so that I can make changes as necessary.&lt;br /&gt;
| Links to the site administration settings still appear in easily findable locations for site administrators.&lt;br /&gt;
|}&lt;br /&gt;
=== Common user stories ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;User story&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to see other participants within a course so that I can contact them.&lt;br /&gt;
| Within the course I can easily find a navigation item for participants.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to be able to navigate around the site using assistive technologies.&lt;br /&gt;
| The new navigation meets WCAG 2.1 AA and can be used with screen readers and other assistive technologies.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to see an overview of all of my courses so that I can easily access a particular course.&lt;br /&gt;
| I can navigate to a page that contains the courses I am currently enrolled in or have access to.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to easily navigate to a course I am enrolled in so that I can continue my learning.&lt;br /&gt;
| I can easily find my desired course to review its content.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to quickly navigate to the site home page so that I can find other relevant content.&lt;br /&gt;
| I am able to navigate to the site home page easily and quickly.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to be able to go from one activity back to the course page so that I can easily find another activity.&lt;br /&gt;
| As any user, I should be able to use the context header bar within an activity or resource to navigate back to the course page.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to navigate back to the section the activity is in so that I can find other activities in the same section.&lt;br /&gt;
| As any user, I should be able to use the context header bar within an activity to navigate back to the section of the course that the current activity is placed in.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I can search a forum so that I can find relevant posts or discussions before making a new post.&lt;br /&gt;
| I can still search forums in a similar or identical way as I currently can (pre Moodle 4.0).&lt;br /&gt;
|}&lt;br /&gt;
== Code architecture ==&lt;br /&gt;
Global and settings navigation are a true source of the internal navigation system. The new structure will be grouped into 2 broad components - primary and secondary navigation. The structure are for display purposes and can be interpreted by the different themes as they please.&lt;br /&gt;
&lt;br /&gt;
The 2 components cover the following: &lt;br /&gt;
* &#039;primary&#039; navigation items across the top of the page with the site header. This has 2 sub-components:&lt;br /&gt;
** views/primary - Contains the base nodes for a vanilla moodle install. Based on current designs these are - Home, Dashboard, My Courses, Site Admin&lt;br /&gt;
** output/primary - An amalgamation of everything that can appear on the top of the page which includes the base nodes within view/primary as well as user, lang and custom menu items.&lt;br /&gt;
* &#039;secondary&#039; navigation items across the top of the page content within the context header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Based on user testing and UX research, it was decided that an ordered set of nodes be defined and shown within the secondary navigation at a site/course/module level. This was based on most used items, common items between modules as well as existing functionality. &lt;br /&gt;
&lt;br /&gt;
The current idea is to provide mapping constructs within the secondary nav class which would cherry-pick navigation nodes based on their keys, from the global and settings navigation trees. This way, we avoid creating any additional callbacks and CRUD statements. &lt;br /&gt;
&lt;br /&gt;
The current idea is to create a view based class system where views/*_navigation classes extend the existing navigation_node class. The idea behind this new structure is that the system and third party theme developers can easily fetch a representation of the current navigation within a given context and immediately render out only the view they want as opposed to fetching the entire navigation for the page.&lt;br /&gt;
=== Technical design of *_navigation ===&lt;br /&gt;
The primary &amp;amp; secondary navigation classes are representations of the navigation within a given context. The instances of these navigation views will be capable of accepting navigation items appended to them within plugins; however, plugins will not be able to remove existing navigation_node‘s.&lt;br /&gt;
&lt;br /&gt;
Custom label added via plugin&lt;br /&gt;
[[File:Primary.png]]&lt;br /&gt;
&lt;br /&gt;
Assuming a label &#039;Custom label&#039; has been added. This can only be done via the custommenuitems in site admin by an authorised user. This is picked up output/primary.php and is still displayed at the top of the page.&lt;br /&gt;
&lt;br /&gt;
Any additional tabs to be added in the secondary navigation must be added to the settings navigation via the existing callbacks. The location of additional nodes/tabs depends on the following:&lt;br /&gt;
&lt;br /&gt;
# The order defined in the mapping construct in the secondary navigation class&lt;br /&gt;
# The number of items displayed&lt;br /&gt;
# The width of the viewport&lt;br /&gt;
# Whether the new tab is forced to reside within the more menu.&lt;br /&gt;
&lt;br /&gt;
=== Consideration given to third party plugins ===&lt;br /&gt;
The new navigation classes will leverage the existing global and setting navigation and nodes defined in them. This provides access to callbacks that are already implemented for both course module plugins and local plugins that modify what navigation_node’s populate the either navigation view.&lt;br /&gt;
&lt;br /&gt;
This means that both core and third party Moodle theme plugins will not be able to mutate / modify any received new navigation views as the only accessible functions publicly defined would be to fetch a representation of the navigation to be output by the theme in a template.&lt;br /&gt;
&lt;br /&gt;
As previously mentioned the secondary navigation is context based &lt;br /&gt;
If a core OR third party Moodle plugin require a custom view/order for the nodes it is recommended to ship the plugin with a secondary class within the namespace and is only applicable to course modules&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
mod_{pluginname}\local\views&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The process for calling these new navigation views is similar to existing methods of calling navigation, there&#039;ll be a new properties added to the lib/pagelib.php called primarynavigation &amp;amp; secondarynavigation. These properties will be used in conjunction with magic_get_*nav() to create a new primary_navigation or secondary_navigation and trigger the initialization method.&lt;br /&gt;
To view a similar calling method, view how the navigation is called within any of the columns files within the boost theme where it calls flatnav.&lt;br /&gt;
=== Further reading ===&lt;br /&gt;
More technical discussion can be found within issues in the navigation epic MDL-69588 or in the specification document (releasing soon)&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_navigation_improvements&amp;diff=60542</id>
		<title>Moodle 4.0 navigation improvements</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_navigation_improvements&amp;diff=60542"/>
		<updated>2021-08-06T05:12:22Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Code architecture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|state = In progress&lt;br /&gt;
|name = Update general Moodle navigation&lt;br /&gt;
|tracker = MDL-69588 (epic)&lt;br /&gt;
|discussion = [https://moodle.org/mod/forum/discuss.php?d=418328 Navigation for Moodle 4.0]&lt;br /&gt;
|assignee = Team Alpha&lt;br /&gt;
}}&lt;br /&gt;
{{Template:Moodle 4.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
With the incoming release of Moodle 4.0, it is our desire to improve the user experience surrounding the navigation of courses, modules and other key areas by reducing the cognitive load upon users when navigating. These improvements will only be made to the existing primary Moodle theme: Boost. Whilst the primary focus is upon Boost it is our goal that the theme Classic will retain its current functionality.&lt;br /&gt;
The overall aim of this project is to create a simplified navigation hierarchy where:&lt;br /&gt;
* Users no longer feel overwhelmed by numerous pathways to get to a single destination&lt;br /&gt;
* Navigation pathways follow common patterns all throughout Moodle&lt;br /&gt;
* Navigation options presented to the user are contextually relevant; so that users intuitively and quickly learn how to get to where they need to be&lt;br /&gt;
* Navigation has a consistent look and feel between desktop sized viewports &amp;amp; mobile sized viewports&lt;br /&gt;
The focus of this project is on the student and teacher navigation experience.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Prototype / mock-ups ==&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
Across all of Moodle the header of the site will be changed for 4.0 with important navigation elements being rendered within the header of Moodle.&lt;br /&gt;
With this change to navigation new active and hover states will be created to inform users of where they currently are and where they are navigating to at a glance.&lt;br /&gt;
&lt;br /&gt;
When the amount of navigation items exceeds the width of the viewport width then a new dynamic menu item will appear that navigation elements overflow into.&lt;br /&gt;
&lt;br /&gt;
On mobile devices it is expected that within Moodle the primary navigation will be rendered as a navigation drawer in the same fashion as the current navigation drawer.&lt;br /&gt;
&lt;br /&gt;
The image below shows a prototype for Moodle 4.0 with navigation within the header for the page, it also includes custom menu elements to demonstrate that existing functionality is being accounted for.&lt;br /&gt;
==== Desktop primary navigation ====&lt;br /&gt;
[[File:Primary.png]]&lt;br /&gt;
==== Mobile primary navigation ====&lt;br /&gt;
Primary navigation (mobile device inactive)&lt;br /&gt;
[[File:Primary_mobile_inactive.png]]&lt;br /&gt;
&lt;br /&gt;
Primary navigation (mobile device active)&lt;br /&gt;
[[File:Primary_mobile_active.png]]&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
Navigation items will now appear as tabs within the context header (Course header, Site admin header, etc...) and similar to the primary navigation the active element will have an indicator below the active tab and have hover styling that indicates the potential tab item that’ll be navigated to.&lt;br /&gt;
&lt;br /&gt;
Also similar to the primary navigation a dynamic “More” menu will be implemented to accommodate navigation elements when the viewport width reduces to a point where elements can not feasibly be shown within the menu area. At most 5 tabs will be shown excluding the &#039;More&#039; menu/tab. Any extra tabs will now reside within the &#039;More&#039; menu.&lt;br /&gt;
&lt;br /&gt;
The below image shows the secondary navigation within the page header, this will look similar to the above primary navigation image.&lt;br /&gt;
==== Desktop secondary navigation ====&lt;br /&gt;
[[File:Secondary.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Page header (Context header) ===&lt;br /&gt;
Work here will primarily focus on user interactions with the context header such as automatic hiding and displaying of elements depending on the users&#039; scrolling and page position. Other changes will include rearranging elements, modifying font sizing, weight and spacing around the current page name.&lt;br /&gt;
&lt;br /&gt;
The below image shows the page header on a mobile device as the desktop viewport examples can be seen in the prior images.&lt;br /&gt;
==== Mobile view page header ====&lt;br /&gt;
[[File:Mobile_context.png]]&lt;br /&gt;
==== Breadcrumbs ====&lt;br /&gt;
Breadcrumbs are being changed to follow the guidelines set in [https://www.nngroup.com/articles/breadcrumbs/ Nielsen Norman Group - Breadcrumbs: 11 Design Guidelines]&lt;br /&gt;
&lt;br /&gt;
A few of the changes being implemented:&lt;br /&gt;
# Remove entries without any links&lt;br /&gt;
# Remove the link from the last item in the list as this defines the page a user is already on&lt;br /&gt;
# Remove breadcrumbs from the course index page as this can be accessed via the primary navigation links as a new root page.&lt;br /&gt;
# Remove breadcrumbs from site admin pages as navigation can be done via the secondary navigation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User stories ==&lt;br /&gt;
These are the user stories that this project aims to address.&lt;br /&gt;
=== For the student ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Student user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to easily move between courses and activities so that I can focus on learning.&lt;br /&gt;
| I should be able to easily see my list of courses in a predictable place and be able to jump from one course to another or one activity to another at speed.&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to view my grades within a course so that I know how I am doing.&lt;br /&gt;
| Within the course context I should be able to click straight through to my grade overview.&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to view my grades for a forum activity, so that I can receive feedback on my participation.&lt;br /&gt;
| Within a forum activity I should be able to view my grades using the existing forum grading functionality.&lt;br /&gt;
|}&lt;br /&gt;
=== For the course creator / teacher ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Course creator / teacher user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily move between courses and activities so that I can focus on course creation or facilitation.&lt;br /&gt;
| I should be able to easily see my list of courses in a predictable place and be able to jump from one course to another at speed.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access the course settings so that I can make changes as necessary.&lt;br /&gt;
| Within a course, the course settings should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access activity settings so that I can make changes as necessary.&lt;br /&gt;
| Within a course activity or resource, the settings should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access course reports so that I can review my students&#039; activity.&lt;br /&gt;
| Within a course, the reports should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access the course gradebook so that I can check my students&#039; grades.&lt;br /&gt;
| Within a course, the gradebook should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily grade a student&#039;s forum posts, so that I can provide them with feedback on their participation.&lt;br /&gt;
| Within a forum activity, I can open the forum grading functionality and give each students a grade.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to be able to easily add new content or modify existing content in a course so that I can update the course as necessary.&lt;br /&gt;
| Within a course, I can easily turn on course editing to add or edit activities and resources.&lt;br /&gt;
|}&lt;br /&gt;
=== For the administrator ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Administrator user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a site administrator, I want to be able to easily access site administration settings so that I can make changes as necessary.&lt;br /&gt;
| Links to the site administration settings still appear in easily findable locations for site administrators.&lt;br /&gt;
|}&lt;br /&gt;
=== Common user stories ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;User story&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to see other participants within a course so that I can contact them.&lt;br /&gt;
| Within the course I can easily find a navigation item for participants.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to be able to navigate around the site using assistive technologies.&lt;br /&gt;
| The new navigation meets WCAG 2.1 AA and can be used with screen readers and other assistive technologies.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to see an overview of all of my courses so that I can easily access a particular course.&lt;br /&gt;
| I can navigate to a page that contains the courses I am currently enrolled in or have access to.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to easily navigate to a course I am enrolled in so that I can continue my learning.&lt;br /&gt;
| I can easily find my desired course to review its content.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to quickly navigate to the site home page so that I can find other relevant content.&lt;br /&gt;
| I am able to navigate to the site home page easily and quickly.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to be able to go from one activity back to the course page so that I can easily find another activity.&lt;br /&gt;
| As any user, I should be able to use the context header bar within an activity or resource to navigate back to the course page.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to navigate back to the section the activity is in so that I can find other activities in the same section.&lt;br /&gt;
| As any user, I should be able to use the context header bar within an activity to navigate back to the section of the course that the current activity is placed in.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I can search a forum so that I can find relevant posts or discussions before making a new post.&lt;br /&gt;
| I can still search forums in a similar or identical way as I currently can (pre Moodle 4.0).&lt;br /&gt;
|}&lt;br /&gt;
== Code architecture ==&lt;br /&gt;
Global and settings navigation are a true source of the internal navigation system. The new structure will be grouped into 2 broad components - primary and secondary navigation. The structure are for display purposes and can be interpreted by the different themes as they please.&lt;br /&gt;
&lt;br /&gt;
The 2 components cover the following: &lt;br /&gt;
* &#039;primary&#039; navigation items across the top of the page with the site header. This has 2 sub-components:&lt;br /&gt;
** views/primary - Contains the base nodes for a vanilla moodle install. Based on current designs these are - Home, Dashboard, My Courses, Site Admin&lt;br /&gt;
** output/primary - An amalgamation of everything that can appear on the top of the page which includes the base nodes within view/primary as well as user, lang and custom menu items.&lt;br /&gt;
* &#039;secondary&#039; navigation items across the top of the page content within the context header&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Based on user testing and UX research, it was decided that an ordered set of nodes be defined and shown within the secondary navigation at a site/course/module level. This was based on most used items, common items between modules as well as existing functionality. &lt;br /&gt;
&lt;br /&gt;
The current idea is to provide mapping constructs within the secondary nav class which would cherry-pick navigation nodes based on their keys, from the global and settings navigation trees. This way, we avoid creating any additional callbacks and CRUD statements. &lt;br /&gt;
&lt;br /&gt;
The current idea is to create a view based class system where views/*_navigation classes extend the existing navigation_node class. The idea behind this new structure is that the system and third party theme developers can easily fetch a representation of the current navigation within a given context and immediately render out only the view they want as opposed to fetching the entire navigation for the page.&lt;br /&gt;
&lt;br /&gt;
=== Technical design of *_navigation ===&lt;br /&gt;
The primary &amp;amp; secondary navigation classes are representations of the navigation within a given context. The instances of these navigation views will be capable of accepting navigation items appended to them within plugins; however, plugins will not be able to remove existing navigation_node‘s.&lt;br /&gt;
&lt;br /&gt;
Custom label added via plugin&lt;br /&gt;
[[File:Primary.png]]&lt;br /&gt;
&lt;br /&gt;
An example of the above would be the following where &amp;quot;Custom label&amp;quot; has been added by an arbitrary plugin to the primary navigation of a Moodle instance:&lt;br /&gt;
&lt;br /&gt;
Note: In this example we will be using simple strings, During implementation the navigation_node class should be used.&lt;br /&gt;
&lt;br /&gt;
$primarynav = $PAGE-&amp;gt;secondarynavigationview&lt;br /&gt;
$customlabel = $secondnav-&amp;gt;register(&#039;Custom label&#039;)&lt;br /&gt;
&lt;br /&gt;
To add further navigation items underneath the &amp;quot;Custom label&amp;quot; navigation item you could then do the following:&lt;br /&gt;
&lt;br /&gt;
$customlabel-&amp;gt;register_child(&#039;Secondary label&#039;)&lt;br /&gt;
$doclabels = $customlabel-&amp;gt;register_child(&#039;Docs&#039;)&lt;br /&gt;
$doclabels-&amp;gt;register(&#039;Indepth docs&#039;)&lt;br /&gt;
&lt;br /&gt;
After the following the following would be represented within the primary navigation after the default navigation items:&lt;br /&gt;
* Custom label&lt;br /&gt;
** Secondary label&lt;br /&gt;
** Docs&lt;br /&gt;
*** Indepth docs&lt;br /&gt;
=== Consideration given to third party plugins ===&lt;br /&gt;
It is highly likely that the new navigation classes will be using functions from settings_navigation such as load_module_settings(). This provides access to callbacks that are already implemented for both course module plugins and local plugins that modify what navigation_node’s populate the either navigation view.&lt;br /&gt;
&lt;br /&gt;
This means that both core and third party Moodle theme plugins will not be able to mutate / modify any received new navigation views as the only accessible functions publicly defined would be to fetch a representation of the navigation to be output by the theme in a template.&lt;br /&gt;
&lt;br /&gt;
The process for calling these new navigation views is similar to existing methods of calling navigation, there&#039;ll be a new properties added to the lib/pagelib.php called primarynavigationview &amp;amp; secondarynavigationview. These properties will be used in conjunction with magic_get_*navview() to create a new primary_navigation_view or secondary_navigation_view and trigger the initialization method.&lt;br /&gt;
To view a similar calling method, view how the navigation is called within any of the columns files within the boost theme where it calls flatnav.&lt;br /&gt;
=== Further reading ===&lt;br /&gt;
More technical discussion can be found within issues in the navigation epic MDL-69588 or in the specification document (releasing soon)&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_navigation_improvements&amp;diff=60541</id>
		<title>Moodle 4.0 navigation improvements</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_navigation_improvements&amp;diff=60541"/>
		<updated>2021-08-06T04:14:47Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Breadcrumbs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|state = In progress&lt;br /&gt;
|name = Update general Moodle navigation&lt;br /&gt;
|tracker = MDL-69588 (epic)&lt;br /&gt;
|discussion = [https://moodle.org/mod/forum/discuss.php?d=418328 Navigation for Moodle 4.0]&lt;br /&gt;
|assignee = Team Alpha&lt;br /&gt;
}}&lt;br /&gt;
{{Template:Moodle 4.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
With the incoming release of Moodle 4.0, it is our desire to improve the user experience surrounding the navigation of courses, modules and other key areas by reducing the cognitive load upon users when navigating. These improvements will only be made to the existing primary Moodle theme: Boost. Whilst the primary focus is upon Boost it is our goal that the theme Classic will retain its current functionality.&lt;br /&gt;
The overall aim of this project is to create a simplified navigation hierarchy where:&lt;br /&gt;
* Users no longer feel overwhelmed by numerous pathways to get to a single destination&lt;br /&gt;
* Navigation pathways follow common patterns all throughout Moodle&lt;br /&gt;
* Navigation options presented to the user are contextually relevant; so that users intuitively and quickly learn how to get to where they need to be&lt;br /&gt;
* Navigation has a consistent look and feel between desktop sized viewports &amp;amp; mobile sized viewports&lt;br /&gt;
The focus of this project is on the student and teacher navigation experience.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Prototype / mock-ups ==&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
Across all of Moodle the header of the site will be changed for 4.0 with important navigation elements being rendered within the header of Moodle.&lt;br /&gt;
With this change to navigation new active and hover states will be created to inform users of where they currently are and where they are navigating to at a glance.&lt;br /&gt;
&lt;br /&gt;
When the amount of navigation items exceeds the width of the viewport width then a new dynamic menu item will appear that navigation elements overflow into.&lt;br /&gt;
&lt;br /&gt;
On mobile devices it is expected that within Moodle the primary navigation will be rendered as a navigation drawer in the same fashion as the current navigation drawer.&lt;br /&gt;
&lt;br /&gt;
The image below shows a prototype for Moodle 4.0 with navigation within the header for the page, it also includes custom menu elements to demonstrate that existing functionality is being accounted for.&lt;br /&gt;
==== Desktop primary navigation ====&lt;br /&gt;
[[File:Primary.png]]&lt;br /&gt;
==== Mobile primary navigation ====&lt;br /&gt;
Primary navigation (mobile device inactive)&lt;br /&gt;
[[File:Primary_mobile_inactive.png]]&lt;br /&gt;
&lt;br /&gt;
Primary navigation (mobile device active)&lt;br /&gt;
[[File:Primary_mobile_active.png]]&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
Navigation items will now appear as tabs within the context header (Course header, Site admin header, etc...) and similar to the primary navigation the active element will have an indicator below the active tab and have hover styling that indicates the potential tab item that’ll be navigated to.&lt;br /&gt;
&lt;br /&gt;
Also similar to the primary navigation a dynamic “More” menu will be implemented to accommodate navigation elements when the viewport width reduces to a point where elements can not feasibly be shown within the menu area. At most 5 tabs will be shown excluding the &#039;More&#039; menu/tab. Any extra tabs will now reside within the &#039;More&#039; menu.&lt;br /&gt;
&lt;br /&gt;
The below image shows the secondary navigation within the page header, this will look similar to the above primary navigation image.&lt;br /&gt;
==== Desktop secondary navigation ====&lt;br /&gt;
[[File:Secondary.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Page header (Context header) ===&lt;br /&gt;
Work here will primarily focus on user interactions with the context header such as automatic hiding and displaying of elements depending on the users&#039; scrolling and page position. Other changes will include rearranging elements, modifying font sizing, weight and spacing around the current page name.&lt;br /&gt;
&lt;br /&gt;
The below image shows the page header on a mobile device as the desktop viewport examples can be seen in the prior images.&lt;br /&gt;
==== Mobile view page header ====&lt;br /&gt;
[[File:Mobile_context.png]]&lt;br /&gt;
==== Breadcrumbs ====&lt;br /&gt;
Breadcrumbs are being changed to follow the guidelines set in [https://www.nngroup.com/articles/breadcrumbs/ Nielsen Norman Group - Breadcrumbs: 11 Design Guidelines]&lt;br /&gt;
&lt;br /&gt;
A few of the changes being implemented:&lt;br /&gt;
# Remove entries without any links&lt;br /&gt;
# Remove the link from the last item in the list as this defines the page a user is already on&lt;br /&gt;
# Remove breadcrumbs from the course index page as this can be accessed via the primary navigation links as a new root page.&lt;br /&gt;
# Remove breadcrumbs from site admin pages as navigation can be done via the secondary navigation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User stories ==&lt;br /&gt;
These are the user stories that this project aims to address.&lt;br /&gt;
=== For the student ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Student user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to easily move between courses and activities so that I can focus on learning.&lt;br /&gt;
| I should be able to easily see my list of courses in a predictable place and be able to jump from one course to another or one activity to another at speed.&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to view my grades within a course so that I know how I am doing.&lt;br /&gt;
| Within the course context I should be able to click straight through to my grade overview.&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to view my grades for a forum activity, so that I can receive feedback on my participation.&lt;br /&gt;
| Within a forum activity I should be able to view my grades using the existing forum grading functionality.&lt;br /&gt;
|}&lt;br /&gt;
=== For the course creator / teacher ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Course creator / teacher user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily move between courses and activities so that I can focus on course creation or facilitation.&lt;br /&gt;
| I should be able to easily see my list of courses in a predictable place and be able to jump from one course to another at speed.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access the course settings so that I can make changes as necessary.&lt;br /&gt;
| Within a course, the course settings should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access activity settings so that I can make changes as necessary.&lt;br /&gt;
| Within a course activity or resource, the settings should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access course reports so that I can review my students&#039; activity.&lt;br /&gt;
| Within a course, the reports should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access the course gradebook so that I can check my students&#039; grades.&lt;br /&gt;
| Within a course, the gradebook should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily grade a student&#039;s forum posts, so that I can provide them with feedback on their participation.&lt;br /&gt;
| Within a forum activity, I can open the forum grading functionality and give each students a grade.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to be able to easily add new content or modify existing content in a course so that I can update the course as necessary.&lt;br /&gt;
| Within a course, I can easily turn on course editing to add or edit activities and resources.&lt;br /&gt;
|}&lt;br /&gt;
=== For the administrator ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Administrator user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a site administrator, I want to be able to easily access site administration settings so that I can make changes as necessary.&lt;br /&gt;
| Links to the site administration settings still appear in easily findable locations for site administrators.&lt;br /&gt;
|}&lt;br /&gt;
=== Common user stories ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;User story&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to see other participants within a course so that I can contact them.&lt;br /&gt;
| Within the course I can easily find a navigation item for participants.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to be able to navigate around the site using assistive technologies.&lt;br /&gt;
| The new navigation meets WCAG 2.1 AA and can be used with screen readers and other assistive technologies.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to see an overview of all of my courses so that I can easily access a particular course.&lt;br /&gt;
| I can navigate to a page that contains the courses I am currently enrolled in or have access to.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to easily navigate to a course I am enrolled in so that I can continue my learning.&lt;br /&gt;
| I can easily find my desired course to review its content.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to quickly navigate to the site home page so that I can find other relevant content.&lt;br /&gt;
| I am able to navigate to the site home page easily and quickly.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to be able to go from one activity back to the course page so that I can easily find another activity.&lt;br /&gt;
| As any user, I should be able to use the context header bar within an activity or resource to navigate back to the course page.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to navigate back to the section the activity is in so that I can find other activities in the same section.&lt;br /&gt;
| As any user, I should be able to use the context header bar within an activity to navigate back to the section of the course that the current activity is placed in.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I can search a forum so that I can find relevant posts or discussions before making a new post.&lt;br /&gt;
| I can still search forums in a similar or identical way as I currently can (pre Moodle 4.0).&lt;br /&gt;
|}&lt;br /&gt;
== Code architecture ==&lt;br /&gt;
Navigation views are a way to distinguish from the actual navigation of the system. Global and settings navigation are a true source of the internal navigation system. The views are for display purposes and can be interpreted by the different themes as they please.&lt;br /&gt;
&lt;br /&gt;
As a developer you can register your new navigation item against different views for example &lt;br /&gt;
* &#039;primary&#039; navigation items across the top of the page with the site header&lt;br /&gt;
* &#039;secondary&#039; navigation items across the top of the page content within the context header&lt;br /&gt;
As seen in the diagram below, the current idea is to create a view based class system where *_navigation_view classes extend the existing navigation_node class. The idea behind this new structure is that the system and third party theme developers can easily fetch a representation of the current navigation within a given context and immediately render out only the view they want as opposed to fetching the entire navigation for the page.&lt;br /&gt;
&lt;br /&gt;
New classes that extend existing classes&lt;br /&gt;
[[File:view_diagram.jpg&lt;br /&gt;
=== Technical design of *_navigation_view ===&lt;br /&gt;
The primary &amp;amp; secondary navigation view classes are representations of the navigation within a given context. The instances of these navigation views will be capable of accepting navigation items appended to them within plugins; however, plugins will not be able to remove existing navigation_node‘s.&lt;br /&gt;
&lt;br /&gt;
Custom label added via plugin&lt;br /&gt;
[[File:Primary.png]]&lt;br /&gt;
&lt;br /&gt;
An example of the above would be the following where &amp;quot;Custom label&amp;quot; has been added by an arbitrary plugin to the primary navigation of a Moodle instance:&lt;br /&gt;
&lt;br /&gt;
Note: In this example we will be using simple strings, During implementation the navigation_node class should be used.&lt;br /&gt;
&lt;br /&gt;
$primarynav = $PAGE-&amp;gt;secondarynavigationview&lt;br /&gt;
$customlabel = $secondnav-&amp;gt;register(&#039;Custom label&#039;)&lt;br /&gt;
&lt;br /&gt;
To add further navigation items underneath the &amp;quot;Custom label&amp;quot; navigation item you could then do the following:&lt;br /&gt;
&lt;br /&gt;
$customlabel-&amp;gt;register_child(&#039;Secondary label&#039;)&lt;br /&gt;
$doclabels = $customlabel-&amp;gt;register_child(&#039;Docs&#039;)&lt;br /&gt;
$doclabels-&amp;gt;register(&#039;Indepth docs&#039;)&lt;br /&gt;
&lt;br /&gt;
After the following the following would be represented within the primary navigation after the default navigation items:&lt;br /&gt;
* Custom label&lt;br /&gt;
** Secondary label&lt;br /&gt;
** Docs&lt;br /&gt;
*** Indepth docs&lt;br /&gt;
=== Consideration given to third party plugins ===&lt;br /&gt;
It is highly likely that the new navigation classes will be using functions from settings_navigation such as load_module_settings(). This provides access to callbacks that are already implemented for both course module plugins and local plugins that modify what navigation_node’s populate the either navigation view.&lt;br /&gt;
&lt;br /&gt;
This means that both core and third party Moodle theme plugins will not be able to mutate / modify any received new navigation views as the only accessible functions publicly defined would be to fetch a representation of the navigation to be output by the theme in a template.&lt;br /&gt;
&lt;br /&gt;
The process for calling these new navigation views is similar to existing methods of calling navigation, there&#039;ll be a new properties added to the lib/pagelib.php called primarynavigationview &amp;amp; secondarynavigationview. These properties will be used in conjunction with magic_get_*navview() to create a new primary_navigation_view or secondary_navigation_view and trigger the initialization method.&lt;br /&gt;
To view a similar calling method, view how the navigation is called within any of the columns files within the boost theme where it calls flatnav.&lt;br /&gt;
=== Further reading ===&lt;br /&gt;
More technical discussion can be found within issues in the navigation epic MDL-69588 or in the specification document (releasing soon)&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_navigation_improvements&amp;diff=60540</id>
		<title>Moodle 4.0 navigation improvements</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_navigation_improvements&amp;diff=60540"/>
		<updated>2021-08-06T04:12:28Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Page header (Context header) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|state = In progress&lt;br /&gt;
|name = Update general Moodle navigation&lt;br /&gt;
|tracker = MDL-69588 (epic)&lt;br /&gt;
|discussion = [https://moodle.org/mod/forum/discuss.php?d=418328 Navigation for Moodle 4.0]&lt;br /&gt;
|assignee = Team Alpha&lt;br /&gt;
}}&lt;br /&gt;
{{Template:Moodle 4.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
With the incoming release of Moodle 4.0, it is our desire to improve the user experience surrounding the navigation of courses, modules and other key areas by reducing the cognitive load upon users when navigating. These improvements will only be made to the existing primary Moodle theme: Boost. Whilst the primary focus is upon Boost it is our goal that the theme Classic will retain its current functionality.&lt;br /&gt;
The overall aim of this project is to create a simplified navigation hierarchy where:&lt;br /&gt;
* Users no longer feel overwhelmed by numerous pathways to get to a single destination&lt;br /&gt;
* Navigation pathways follow common patterns all throughout Moodle&lt;br /&gt;
* Navigation options presented to the user are contextually relevant; so that users intuitively and quickly learn how to get to where they need to be&lt;br /&gt;
* Navigation has a consistent look and feel between desktop sized viewports &amp;amp; mobile sized viewports&lt;br /&gt;
The focus of this project is on the student and teacher navigation experience.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Prototype / mock-ups ==&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
Across all of Moodle the header of the site will be changed for 4.0 with important navigation elements being rendered within the header of Moodle.&lt;br /&gt;
With this change to navigation new active and hover states will be created to inform users of where they currently are and where they are navigating to at a glance.&lt;br /&gt;
&lt;br /&gt;
When the amount of navigation items exceeds the width of the viewport width then a new dynamic menu item will appear that navigation elements overflow into.&lt;br /&gt;
&lt;br /&gt;
On mobile devices it is expected that within Moodle the primary navigation will be rendered as a navigation drawer in the same fashion as the current navigation drawer.&lt;br /&gt;
&lt;br /&gt;
The image below shows a prototype for Moodle 4.0 with navigation within the header for the page, it also includes custom menu elements to demonstrate that existing functionality is being accounted for.&lt;br /&gt;
==== Desktop primary navigation ====&lt;br /&gt;
[[File:Primary.png]]&lt;br /&gt;
==== Mobile primary navigation ====&lt;br /&gt;
Primary navigation (mobile device inactive)&lt;br /&gt;
[[File:Primary_mobile_inactive.png]]&lt;br /&gt;
&lt;br /&gt;
Primary navigation (mobile device active)&lt;br /&gt;
[[File:Primary_mobile_active.png]]&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
Navigation items will now appear as tabs within the context header (Course header, Site admin header, etc...) and similar to the primary navigation the active element will have an indicator below the active tab and have hover styling that indicates the potential tab item that’ll be navigated to.&lt;br /&gt;
&lt;br /&gt;
Also similar to the primary navigation a dynamic “More” menu will be implemented to accommodate navigation elements when the viewport width reduces to a point where elements can not feasibly be shown within the menu area. At most 5 tabs will be shown excluding the &#039;More&#039; menu/tab. Any extra tabs will now reside within the &#039;More&#039; menu.&lt;br /&gt;
&lt;br /&gt;
The below image shows the secondary navigation within the page header, this will look similar to the above primary navigation image.&lt;br /&gt;
==== Desktop secondary navigation ====&lt;br /&gt;
[[File:Secondary.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Page header (Context header) ===&lt;br /&gt;
Work here will primarily focus on user interactions with the context header such as automatic hiding and displaying of elements depending on the users&#039; scrolling and page position. Other changes will include rearranging elements, modifying font sizing, weight and spacing around the current page name.&lt;br /&gt;
&lt;br /&gt;
The below image shows the page header on a mobile device as the desktop viewport examples can be seen in the prior images.&lt;br /&gt;
==== Mobile view page header ====&lt;br /&gt;
[[File:Mobile_context.png]]&lt;br /&gt;
&lt;br /&gt;
==== Breadcrumbs ====&lt;br /&gt;
Breadcrumbs are being changed to follow the guidelines set in [https://www.nngroup.com/articles/breadcrumbs/ Nielsen Norman Group - Breadcrumbs: 11 Design Guidelines]&lt;br /&gt;
&lt;br /&gt;
A few of the changes being implemented:&lt;br /&gt;
# Remove entries without any links&lt;br /&gt;
# Remove the link from the last item in the list as this defines the page a user is already on&lt;br /&gt;
# Remove breadcrumbs from the course index page as this can be accessed via the primary navigation links as a new root page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User stories ==&lt;br /&gt;
These are the user stories that this project aims to address.&lt;br /&gt;
=== For the student ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Student user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to easily move between courses and activities so that I can focus on learning.&lt;br /&gt;
| I should be able to easily see my list of courses in a predictable place and be able to jump from one course to another or one activity to another at speed.&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to view my grades within a course so that I know how I am doing.&lt;br /&gt;
| Within the course context I should be able to click straight through to my grade overview.&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to view my grades for a forum activity, so that I can receive feedback on my participation.&lt;br /&gt;
| Within a forum activity I should be able to view my grades using the existing forum grading functionality.&lt;br /&gt;
|}&lt;br /&gt;
=== For the course creator / teacher ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Course creator / teacher user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily move between courses and activities so that I can focus on course creation or facilitation.&lt;br /&gt;
| I should be able to easily see my list of courses in a predictable place and be able to jump from one course to another at speed.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access the course settings so that I can make changes as necessary.&lt;br /&gt;
| Within a course, the course settings should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access activity settings so that I can make changes as necessary.&lt;br /&gt;
| Within a course activity or resource, the settings should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access course reports so that I can review my students&#039; activity.&lt;br /&gt;
| Within a course, the reports should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access the course gradebook so that I can check my students&#039; grades.&lt;br /&gt;
| Within a course, the gradebook should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily grade a student&#039;s forum posts, so that I can provide them with feedback on their participation.&lt;br /&gt;
| Within a forum activity, I can open the forum grading functionality and give each students a grade.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to be able to easily add new content or modify existing content in a course so that I can update the course as necessary.&lt;br /&gt;
| Within a course, I can easily turn on course editing to add or edit activities and resources.&lt;br /&gt;
|}&lt;br /&gt;
=== For the administrator ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Administrator user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a site administrator, I want to be able to easily access site administration settings so that I can make changes as necessary.&lt;br /&gt;
| Links to the site administration settings still appear in easily findable locations for site administrators.&lt;br /&gt;
|}&lt;br /&gt;
=== Common user stories ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;User story&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to see other participants within a course so that I can contact them.&lt;br /&gt;
| Within the course I can easily find a navigation item for participants.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to be able to navigate around the site using assistive technologies.&lt;br /&gt;
| The new navigation meets WCAG 2.1 AA and can be used with screen readers and other assistive technologies.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to see an overview of all of my courses so that I can easily access a particular course.&lt;br /&gt;
| I can navigate to a page that contains the courses I am currently enrolled in or have access to.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to easily navigate to a course I am enrolled in so that I can continue my learning.&lt;br /&gt;
| I can easily find my desired course to review its content.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to quickly navigate to the site home page so that I can find other relevant content.&lt;br /&gt;
| I am able to navigate to the site home page easily and quickly.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to be able to go from one activity back to the course page so that I can easily find another activity.&lt;br /&gt;
| As any user, I should be able to use the context header bar within an activity or resource to navigate back to the course page.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to navigate back to the section the activity is in so that I can find other activities in the same section.&lt;br /&gt;
| As any user, I should be able to use the context header bar within an activity to navigate back to the section of the course that the current activity is placed in.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I can search a forum so that I can find relevant posts or discussions before making a new post.&lt;br /&gt;
| I can still search forums in a similar or identical way as I currently can (pre Moodle 4.0).&lt;br /&gt;
|}&lt;br /&gt;
== Code architecture ==&lt;br /&gt;
Navigation views are a way to distinguish from the actual navigation of the system. Global and settings navigation are a true source of the internal navigation system. The views are for display purposes and can be interpreted by the different themes as they please.&lt;br /&gt;
&lt;br /&gt;
As a developer you can register your new navigation item against different views for example &lt;br /&gt;
* &#039;primary&#039; navigation items across the top of the page with the site header&lt;br /&gt;
* &#039;secondary&#039; navigation items across the top of the page content within the context header&lt;br /&gt;
As seen in the diagram below, the current idea is to create a view based class system where *_navigation_view classes extend the existing navigation_node class. The idea behind this new structure is that the system and third party theme developers can easily fetch a representation of the current navigation within a given context and immediately render out only the view they want as opposed to fetching the entire navigation for the page.&lt;br /&gt;
&lt;br /&gt;
New classes that extend existing classes&lt;br /&gt;
[[File:view_diagram.jpg&lt;br /&gt;
=== Technical design of *_navigation_view ===&lt;br /&gt;
The primary &amp;amp; secondary navigation view classes are representations of the navigation within a given context. The instances of these navigation views will be capable of accepting navigation items appended to them within plugins; however, plugins will not be able to remove existing navigation_node‘s.&lt;br /&gt;
&lt;br /&gt;
Custom label added via plugin&lt;br /&gt;
[[File:Primary.png]]&lt;br /&gt;
&lt;br /&gt;
An example of the above would be the following where &amp;quot;Custom label&amp;quot; has been added by an arbitrary plugin to the primary navigation of a Moodle instance:&lt;br /&gt;
&lt;br /&gt;
Note: In this example we will be using simple strings, During implementation the navigation_node class should be used.&lt;br /&gt;
&lt;br /&gt;
$primarynav = $PAGE-&amp;gt;secondarynavigationview&lt;br /&gt;
$customlabel = $secondnav-&amp;gt;register(&#039;Custom label&#039;)&lt;br /&gt;
&lt;br /&gt;
To add further navigation items underneath the &amp;quot;Custom label&amp;quot; navigation item you could then do the following:&lt;br /&gt;
&lt;br /&gt;
$customlabel-&amp;gt;register_child(&#039;Secondary label&#039;)&lt;br /&gt;
$doclabels = $customlabel-&amp;gt;register_child(&#039;Docs&#039;)&lt;br /&gt;
$doclabels-&amp;gt;register(&#039;Indepth docs&#039;)&lt;br /&gt;
&lt;br /&gt;
After the following the following would be represented within the primary navigation after the default navigation items:&lt;br /&gt;
* Custom label&lt;br /&gt;
** Secondary label&lt;br /&gt;
** Docs&lt;br /&gt;
*** Indepth docs&lt;br /&gt;
=== Consideration given to third party plugins ===&lt;br /&gt;
It is highly likely that the new navigation classes will be using functions from settings_navigation such as load_module_settings(). This provides access to callbacks that are already implemented for both course module plugins and local plugins that modify what navigation_node’s populate the either navigation view.&lt;br /&gt;
&lt;br /&gt;
This means that both core and third party Moodle theme plugins will not be able to mutate / modify any received new navigation views as the only accessible functions publicly defined would be to fetch a representation of the navigation to be output by the theme in a template.&lt;br /&gt;
&lt;br /&gt;
The process for calling these new navigation views is similar to existing methods of calling navigation, there&#039;ll be a new properties added to the lib/pagelib.php called primarynavigationview &amp;amp; secondarynavigationview. These properties will be used in conjunction with magic_get_*navview() to create a new primary_navigation_view or secondary_navigation_view and trigger the initialization method.&lt;br /&gt;
To view a similar calling method, view how the navigation is called within any of the columns files within the boost theme where it calls flatnav.&lt;br /&gt;
=== Further reading ===&lt;br /&gt;
More technical discussion can be found within issues in the navigation epic MDL-69588 or in the specification document (releasing soon)&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_4.0_navigation_improvements&amp;diff=60539</id>
		<title>Moodle 4.0 navigation improvements</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_4.0_navigation_improvements&amp;diff=60539"/>
		<updated>2021-08-06T04:00:59Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Secondary navigation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|state = In progress&lt;br /&gt;
|name = Update general Moodle navigation&lt;br /&gt;
|tracker = MDL-69588 (epic)&lt;br /&gt;
|discussion = [https://moodle.org/mod/forum/discuss.php?d=418328 Navigation for Moodle 4.0]&lt;br /&gt;
|assignee = Team Alpha&lt;br /&gt;
}}&lt;br /&gt;
{{Template:Moodle 4.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
With the incoming release of Moodle 4.0, it is our desire to improve the user experience surrounding the navigation of courses, modules and other key areas by reducing the cognitive load upon users when navigating. These improvements will only be made to the existing primary Moodle theme: Boost. Whilst the primary focus is upon Boost it is our goal that the theme Classic will retain its current functionality.&lt;br /&gt;
The overall aim of this project is to create a simplified navigation hierarchy where:&lt;br /&gt;
* Users no longer feel overwhelmed by numerous pathways to get to a single destination&lt;br /&gt;
* Navigation pathways follow common patterns all throughout Moodle&lt;br /&gt;
* Navigation options presented to the user are contextually relevant; so that users intuitively and quickly learn how to get to where they need to be&lt;br /&gt;
* Navigation has a consistent look and feel between desktop sized viewports &amp;amp; mobile sized viewports&lt;br /&gt;
The focus of this project is on the student and teacher navigation experience.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Prototype / mock-ups ==&lt;br /&gt;
=== Primary navigation ===&lt;br /&gt;
Across all of Moodle the header of the site will be changed for 4.0 with important navigation elements being rendered within the header of Moodle.&lt;br /&gt;
With this change to navigation new active and hover states will be created to inform users of where they currently are and where they are navigating to at a glance.&lt;br /&gt;
&lt;br /&gt;
When the amount of navigation items exceeds the width of the viewport width then a new dynamic menu item will appear that navigation elements overflow into.&lt;br /&gt;
&lt;br /&gt;
On mobile devices it is expected that within Moodle the primary navigation will be rendered as a navigation drawer in the same fashion as the current navigation drawer.&lt;br /&gt;
&lt;br /&gt;
The image below shows a prototype for Moodle 4.0 with navigation within the header for the page, it also includes custom menu elements to demonstrate that existing functionality is being accounted for.&lt;br /&gt;
==== Desktop primary navigation ====&lt;br /&gt;
[[File:Primary.png]]&lt;br /&gt;
==== Mobile primary navigation ====&lt;br /&gt;
Primary navigation (mobile device inactive)&lt;br /&gt;
[[File:Primary_mobile_inactive.png]]&lt;br /&gt;
&lt;br /&gt;
Primary navigation (mobile device active)&lt;br /&gt;
[[File:Primary_mobile_active.png]]&lt;br /&gt;
=== Secondary navigation ===&lt;br /&gt;
Navigation items will now appear as tabs within the context header (Course header, Site admin header, etc...) and similar to the primary navigation the active element will have an indicator below the active tab and have hover styling that indicates the potential tab item that’ll be navigated to.&lt;br /&gt;
&lt;br /&gt;
Also similar to the primary navigation a dynamic “More” menu will be implemented to accommodate navigation elements when the viewport width reduces to a point where elements can not feasibly be shown within the menu area. At most 5 tabs will be shown excluding the &#039;More&#039; menu/tab. Any extra tabs will now reside within the &#039;More&#039; menu.&lt;br /&gt;
&lt;br /&gt;
The below image shows the secondary navigation within the page header, this will look similar to the above primary navigation image.&lt;br /&gt;
==== Desktop secondary navigation ====&lt;br /&gt;
[[File:Secondary.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Page header (Context header) ===&lt;br /&gt;
Work here will primarily focus on user interactions with the context header such as automatic hiding and displaying of elements depending on the users&#039; scrolling and page position. Other changes will include rearranging elements, modifying font sizing, weight and spacing around the current page name.&lt;br /&gt;
&lt;br /&gt;
The below image shows the page header on a mobile device as the desktop viewport examples can be seen in the prior images.&lt;br /&gt;
==== Mobile view page header ====&lt;br /&gt;
[[File:Mobile_context.png]]&lt;br /&gt;
== User stories ==&lt;br /&gt;
These are the user stories that this project aims to address.&lt;br /&gt;
=== For the student ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Student user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to easily move between courses and activities so that I can focus on learning.&lt;br /&gt;
| I should be able to easily see my list of courses in a predictable place and be able to jump from one course to another or one activity to another at speed.&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to view my grades within a course so that I know how I am doing.&lt;br /&gt;
| Within the course context I should be able to click straight through to my grade overview.&lt;br /&gt;
|-&lt;br /&gt;
| As a learner, I want to view my grades for a forum activity, so that I can receive feedback on my participation.&lt;br /&gt;
| Within a forum activity I should be able to view my grades using the existing forum grading functionality.&lt;br /&gt;
|}&lt;br /&gt;
=== For the course creator / teacher ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Course creator / teacher user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily move between courses and activities so that I can focus on course creation or facilitation.&lt;br /&gt;
| I should be able to easily see my list of courses in a predictable place and be able to jump from one course to another at speed.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access the course settings so that I can make changes as necessary.&lt;br /&gt;
| Within a course, the course settings should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access activity settings so that I can make changes as necessary.&lt;br /&gt;
| Within a course activity or resource, the settings should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access course reports so that I can review my students&#039; activity.&lt;br /&gt;
| Within a course, the reports should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily access the course gradebook so that I can check my students&#039; grades.&lt;br /&gt;
| Within a course, the gradebook should be easily available.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to easily grade a student&#039;s forum posts, so that I can provide them with feedback on their participation.&lt;br /&gt;
| Within a forum activity, I can open the forum grading functionality and give each students a grade.&lt;br /&gt;
|-&lt;br /&gt;
| As a teacher, I want to be able to easily add new content or modify existing content in a course so that I can update the course as necessary.&lt;br /&gt;
| Within a course, I can easily turn on course editing to add or edit activities and resources.&lt;br /&gt;
|}&lt;br /&gt;
=== For the administrator ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;Administrator user stories&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As a site administrator, I want to be able to easily access site administration settings so that I can make changes as necessary.&lt;br /&gt;
| Links to the site administration settings still appear in easily findable locations for site administrators.&lt;br /&gt;
|}&lt;br /&gt;
=== Common user stories ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &#039;&#039;&#039;User story&#039;&#039;&#039;&lt;br /&gt;
! &#039;&#039;&#039;Acceptance criteria / confirmation&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to see other participants within a course so that I can contact them.&lt;br /&gt;
| Within the course I can easily find a navigation item for participants.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to be able to navigate around the site using assistive technologies.&lt;br /&gt;
| The new navigation meets WCAG 2.1 AA and can be used with screen readers and other assistive technologies.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to see an overview of all of my courses so that I can easily access a particular course.&lt;br /&gt;
| I can navigate to a page that contains the courses I am currently enrolled in or have access to.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to easily navigate to a course I am enrolled in so that I can continue my learning.&lt;br /&gt;
| I can easily find my desired course to review its content.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to quickly navigate to the site home page so that I can find other relevant content.&lt;br /&gt;
| I am able to navigate to the site home page easily and quickly.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to be able to go from one activity back to the course page so that I can easily find another activity.&lt;br /&gt;
| As any user, I should be able to use the context header bar within an activity or resource to navigate back to the course page.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I want to navigate back to the section the activity is in so that I can find other activities in the same section.&lt;br /&gt;
| As any user, I should be able to use the context header bar within an activity to navigate back to the section of the course that the current activity is placed in.&lt;br /&gt;
|-&lt;br /&gt;
| As any user, I can search a forum so that I can find relevant posts or discussions before making a new post.&lt;br /&gt;
| I can still search forums in a similar or identical way as I currently can (pre Moodle 4.0).&lt;br /&gt;
|}&lt;br /&gt;
== Code architecture ==&lt;br /&gt;
Navigation views are a way to distinguish from the actual navigation of the system. Global and settings navigation are a true source of the internal navigation system. The views are for display purposes and can be interpreted by the different themes as they please.&lt;br /&gt;
&lt;br /&gt;
As a developer you can register your new navigation item against different views for example &lt;br /&gt;
* &#039;primary&#039; navigation items across the top of the page with the site header&lt;br /&gt;
* &#039;secondary&#039; navigation items across the top of the page content within the context header&lt;br /&gt;
As seen in the diagram below, the current idea is to create a view based class system where *_navigation_view classes extend the existing navigation_node class. The idea behind this new structure is that the system and third party theme developers can easily fetch a representation of the current navigation within a given context and immediately render out only the view they want as opposed to fetching the entire navigation for the page.&lt;br /&gt;
&lt;br /&gt;
New classes that extend existing classes&lt;br /&gt;
[[File:view_diagram.jpg&lt;br /&gt;
=== Technical design of *_navigation_view ===&lt;br /&gt;
The primary &amp;amp; secondary navigation view classes are representations of the navigation within a given context. The instances of these navigation views will be capable of accepting navigation items appended to them within plugins; however, plugins will not be able to remove existing navigation_node‘s.&lt;br /&gt;
&lt;br /&gt;
Custom label added via plugin&lt;br /&gt;
[[File:Primary.png]]&lt;br /&gt;
&lt;br /&gt;
An example of the above would be the following where &amp;quot;Custom label&amp;quot; has been added by an arbitrary plugin to the primary navigation of a Moodle instance:&lt;br /&gt;
&lt;br /&gt;
Note: In this example we will be using simple strings, During implementation the navigation_node class should be used.&lt;br /&gt;
&lt;br /&gt;
$primarynav = $PAGE-&amp;gt;secondarynavigationview&lt;br /&gt;
$customlabel = $secondnav-&amp;gt;register(&#039;Custom label&#039;)&lt;br /&gt;
&lt;br /&gt;
To add further navigation items underneath the &amp;quot;Custom label&amp;quot; navigation item you could then do the following:&lt;br /&gt;
&lt;br /&gt;
$customlabel-&amp;gt;register_child(&#039;Secondary label&#039;)&lt;br /&gt;
$doclabels = $customlabel-&amp;gt;register_child(&#039;Docs&#039;)&lt;br /&gt;
$doclabels-&amp;gt;register(&#039;Indepth docs&#039;)&lt;br /&gt;
&lt;br /&gt;
After the following the following would be represented within the primary navigation after the default navigation items:&lt;br /&gt;
* Custom label&lt;br /&gt;
** Secondary label&lt;br /&gt;
** Docs&lt;br /&gt;
*** Indepth docs&lt;br /&gt;
=== Consideration given to third party plugins ===&lt;br /&gt;
It is highly likely that the new navigation classes will be using functions from settings_navigation such as load_module_settings(). This provides access to callbacks that are already implemented for both course module plugins and local plugins that modify what navigation_node’s populate the either navigation view.&lt;br /&gt;
&lt;br /&gt;
This means that both core and third party Moodle theme plugins will not be able to mutate / modify any received new navigation views as the only accessible functions publicly defined would be to fetch a representation of the navigation to be output by the theme in a template.&lt;br /&gt;
&lt;br /&gt;
The process for calling these new navigation views is similar to existing methods of calling navigation, there&#039;ll be a new properties added to the lib/pagelib.php called primarynavigationview &amp;amp; secondarynavigationview. These properties will be used in conjunction with magic_get_*navview() to create a new primary_navigation_view or secondary_navigation_view and trigger the initialization method.&lt;br /&gt;
To view a similar calling method, view how the navigation is called within any of the columns files within the boost theme where it calls flatnav.&lt;br /&gt;
=== Further reading ===&lt;br /&gt;
More technical discussion can be found within issues in the navigation epic MDL-69588 or in the specification document (releasing soon)&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:linkedin_scopes_defined.png&amp;diff=59128</id>
		<title>File:linkedin scopes defined.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:linkedin_scopes_defined.png&amp;diff=59128"/>
		<updated>2021-07-05T07:41:38Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:linkedin_auth_page.png&amp;diff=59127</id>
		<title>File:linkedin auth page.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:linkedin_auth_page.png&amp;diff=59127"/>
		<updated>2021-07-05T07:40:52Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:linkedin_added_products.png&amp;diff=59126</id>
		<title>File:linkedin added products.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:linkedin_added_products.png&amp;diff=59126"/>
		<updated>2021-07-05T07:35:57Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:linkedin_products_prior_selection.png&amp;diff=59125</id>
		<title>File:linkedin products prior selection.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:linkedin_products_prior_selection.png&amp;diff=59125"/>
		<updated>2021-07-05T07:33:36Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: List of linkedin products prior to selection&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;List of linkedin products prior to selection&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:linkedin_app_creation.png&amp;diff=59124</id>
		<title>File:linkedin app creation.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:linkedin_app_creation.png&amp;diff=59124"/>
		<updated>2021-07-05T07:20:42Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: Initial page of the linkedin app creation process&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Initial page of the linkedin app creation process&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_libraries_credits&amp;diff=58773</id>
		<title>Moodle libraries credits</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_libraries_credits&amp;diff=58773"/>
		<updated>2021-05-11T06:47:25Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: Existing thirdparty lib missing from list.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Some of Moodle&#039;s libraries were written by other people, and are being redistributed as part of Moodle under their respective open source licenses that thankfully allow us to do so. Thanks to the authors of all these excellent products - without them Moodle would be missing important functionality. Copyright information for each package is included below:&lt;br /&gt;
&lt;br /&gt;
==ADOdb==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/adodb&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Database abstraction library for MySQL, PostgreSQL, MSSQL, Oracle, Interbase, Foxpro, Access, ADO, Sybase, DB2 and ODBC.&lt;br /&gt;
&lt;br /&gt;
Version: 5.20.14&lt;br /&gt;
&lt;br /&gt;
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.&lt;br /&gt;
&lt;br /&gt;
@copyright (c) 2014      Damien Regad, Mark Newnham and the ADOdb community&lt;br /&gt;
&lt;br /&gt;
License: Dual LGPL and BSD-style&lt;br /&gt;
&lt;br /&gt;
http://adodb.sourceforge.net&lt;br /&gt;
&lt;br /&gt;
==Bennu==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/bennu&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Bennu is an object-oriented library written in PHP that implements the iCalendar standard (RFC 2445).&lt;br /&gt;
&lt;br /&gt;
Version: 0.1 (customized since then)&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2005, Jon Papaioannou&lt;br /&gt;
&lt;br /&gt;
License: LGPL 2.1+&lt;br /&gt;
&lt;br /&gt;
http://bennu.sourceforge.net/&lt;br /&gt;
&lt;br /&gt;
==Amazon S3==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;repository/s3/S3.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A standalone Amazon S3 (REST) client for PHP 5.2.x using CURL that does not require PEAR. &lt;br /&gt;
&lt;br /&gt;
Version: 0.5.1&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2013, Donovan Schönknecht&lt;br /&gt;
&lt;br /&gt;
License: BSD 2-Clause&lt;br /&gt;
&lt;br /&gt;
https://github.com/tpyo/amazon-s3-php-class/releases&lt;br /&gt;
&lt;br /&gt;
==CAS==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;auth/cas/CAS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
phpCAS library to support CAS authentication plugin&lt;br /&gt;
&lt;br /&gt;
Version: 1.3.7&lt;br /&gt;
&lt;br /&gt;
Copyright Jasig&lt;br /&gt;
&lt;br /&gt;
License: Apache License 2.0&lt;br /&gt;
&lt;br /&gt;
https://wiki.jasig.org/display/CASC/phpCAS&lt;br /&gt;
&lt;br /&gt;
==Chart.js==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/amd/src/chartjs-lazy.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Simple yet flexible JavaScript charting for designers &amp;amp; developers&lt;br /&gt;
&lt;br /&gt;
Version: 2.9.4&lt;br /&gt;
&lt;br /&gt;
Copyright 2016 Nick Downie&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
http://www.chartjs.org&lt;br /&gt;
&lt;br /&gt;
==CodeMirror==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/editor/atto/plugins/html/yui/src/codemirror&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
CodeMirror is a versatile text editor implemented in JavaScript for the browser.&lt;br /&gt;
&lt;br /&gt;
Version: 5.59.4&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/codemirror/CodeMirror&lt;br /&gt;
&lt;br /&gt;
==Emoji-data==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/emoji-data&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library to parse easily data and spritesheets for emoji&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/iamcal/emoji-data/&lt;br /&gt;
&lt;br /&gt;
==EvalMath==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/evalmath&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to safely evaluate math expressions&lt;br /&gt;
&lt;br /&gt;
Copyright Miles Kaufmann&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
http://www.twmagic.com/&lt;br /&gt;
&lt;br /&gt;
==Flexitour==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;admin/tool/usertours/amd/src/tour.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
A JS library for tours&lt;br /&gt;
&lt;br /&gt;
© 2016 Andrew Nicols and contributors&lt;br /&gt;
&lt;br /&gt;
License: GPLv3&lt;br /&gt;
&lt;br /&gt;
https://github.com/andrewnicols/flexitour&lt;br /&gt;
&lt;br /&gt;
==FLV player==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;filter/mediaplugin/flvplayer.swf&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Flash movie to play FLV files&lt;br /&gt;
&lt;br /&gt;
Copyright Jeroen Wijering &lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.jeroenwijering.com&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
== GeoIp2 ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/maxmind/GeoIp2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library for processing of GeoIP data files&lt;br /&gt;
&lt;br /&gt;
Version: 2.10.0&lt;br /&gt;
&lt;br /&gt;
Copyright MaxMind&lt;br /&gt;
&lt;br /&gt;
License: Apache 2.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/maxmind/GeoIP2-php&lt;br /&gt;
&lt;br /&gt;
== GeoPattern==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/geopattern-php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library for creating beautiful generative background images from a string&lt;br /&gt;
&lt;br /&gt;
Version: 1.1.1&lt;br /&gt;
&lt;br /&gt;
Copyright 2015 Leaf Corcoran&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/RedeyeGroup/geopattern-php&lt;br /&gt;
&lt;br /&gt;
==Google APIs==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/google&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Library Google APIs Client Library for PHP&lt;br /&gt;
&lt;br /&gt;
Version: 1.1.7&lt;br /&gt;
&lt;br /&gt;
License: Apache License Version 2.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/google/google-api-php-client&lt;br /&gt;
&lt;br /&gt;
==Graph Class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/graphlib.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to draw line, point, bar, and area graphs, including numeric x-axis and double y-axis.&lt;br /&gt;
&lt;br /&gt;
Version: 1.6.3 (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2000  Herman Veluwenkamp (&#039;&#039;hermanV AT mindless DOT com&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
==H5P==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/h5p&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The general H5P library&lt;br /&gt;
&lt;br /&gt;
Version: 1.24&lt;br /&gt;
&lt;br /&gt;
Copyright © Joubel&lt;br /&gt;
&lt;br /&gt;
License: GPL-3.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/h5p/h5p-php-library/&lt;br /&gt;
&lt;br /&gt;
==Horde==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/horde&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library used by the inbound e-mail handling system.&lt;br /&gt;
&lt;br /&gt;
Version: 5.2.22&lt;br /&gt;
&lt;br /&gt;
Copyright © Horde LLC&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://www.horde.org/&lt;br /&gt;
&lt;br /&gt;
==html2text==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/html2text&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP script to convert HTML into an approximate text equivalent&lt;br /&gt;
&lt;br /&gt;
Version: 4.2.1&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2005-2007 Jon Abernathy &amp;lt;jon@chuggnutt.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
https://github.com/mtibben/html2text.git&lt;br /&gt;
&lt;br /&gt;
==htmlArea==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/editor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Javascript/HTML script to put a GUI editor in textareas on Internet Explorer and Mozilla&lt;br /&gt;
&lt;br /&gt;
Version: 3.0 beta (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002  interactivetools.com, inc.&lt;br /&gt;
&lt;br /&gt;
License: htmlArea License (based on BSD license)&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==HTML Purifier==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/htmlpurifier&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Filters HTML.&lt;br /&gt;
&lt;br /&gt;
Version: 4.13.0&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
==IP-Atlas==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/ipatlas&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP scripts to show the location of an IP address on a map.&lt;br /&gt;
&lt;br /&gt;
Version: 1.0 (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002   Ivan Kozik&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.xpenguin.com/ip-atlas.php&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==Jabber - XMPPHP==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jabber&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP library for XMPP (aka Jabber, Google Talk, etc).&lt;br /&gt;
&lt;br /&gt;
Version: 0.1rc2-r77&lt;br /&gt;
&lt;br /&gt;
Copyright: 2008  Nathanael C. Fritz&lt;br /&gt;
&lt;br /&gt;
License: GPL&lt;br /&gt;
&lt;br /&gt;
http://code.google.com/p/xmpphp&lt;br /&gt;
&lt;br /&gt;
==jQuery==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jquery&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
jQuery is a fast, small, and feature-rich JavaScript library widely used on moodle.&lt;br /&gt;
&lt;br /&gt;
Version: 3.4.1&lt;br /&gt;
&lt;br /&gt;
Copyright: 2016 The jQuery Foundation&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://jquery.com&lt;br /&gt;
&lt;br /&gt;
==jQuery migrate==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jquery/jquery-migrate-1.4.0.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library used migrate older jQuery code to jQuery 3.0.&lt;br /&gt;
&lt;br /&gt;
Version: 1.4.0&lt;br /&gt;
&lt;br /&gt;
Copyright: 2016 The jQuery Foundation and other contributors&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/jquery/jquery-migrate&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==jQuery UI==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jquery/ui-1.12.1/&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
jQuery UI is a set of user interface interactions, effects, widgets, and themes built on top of the jQuery library.&lt;br /&gt;
&lt;br /&gt;
Version: 1.12.1&lt;br /&gt;
&lt;br /&gt;
Copyright: 2016 The jQuery Foundation and other contributors&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/jquery/jquery-migrate&lt;br /&gt;
&lt;br /&gt;
==Services_JSON==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Allows PHP-&amp;gt;JS communication via JSON&lt;br /&gt;
&lt;br /&gt;
Version: 1.3.1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005 Michal Migurski&lt;br /&gt;
&lt;br /&gt;
License: Modified BSD (GPL-compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/pepr/pepr-proposal-show.php?id=198&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==JWT==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/php-jwt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to RFC 7519&lt;br /&gt;
&lt;br /&gt;
Version: 5.0.0&lt;br /&gt;
&lt;br /&gt;
Copyright © 2011, Neuman Vong&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
https://github.com/firebase/php-jwt&lt;br /&gt;
&lt;br /&gt;
==ENUM==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/php-enum&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP Enum implementation inspired from SplEnum&lt;br /&gt;
&lt;br /&gt;
Version: 1.7.6&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2015 My C-Labs&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/myclabs/php-enum&lt;br /&gt;
&lt;br /&gt;
==kses==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/kses.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
HTML/XHTML filter that only allows some elements and attributes&lt;br /&gt;
&lt;br /&gt;
Version: 0.2.2&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002, 2003, 2005   Ulf Harnhammar&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://sourceforge.net/projects/kses&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==less.php==&lt;br /&gt;
&lt;br /&gt;
The less.php is a PHP port of the official LESS processor used by moodle themes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/lessphp&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Version: 1.7.0.10&lt;br /&gt;
&lt;br /&gt;
License: Apache 2.0&lt;br /&gt;
&lt;br /&gt;
http://lessphp.typesettercms.com/&lt;br /&gt;
&lt;br /&gt;
Copyright:  Matt Agar and Martin Jantošovič&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==loglevel.js==&lt;br /&gt;
&lt;br /&gt;
Minimal lightweight simple logging for JavaScript.&lt;br /&gt;
&lt;br /&gt;
Version 1.6.6&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2019 Tim Perry&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/pimterry/loglevel/&lt;br /&gt;
&lt;br /&gt;
==LTI Tool Provider Library for PHP==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/ltiprovider/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PHP library for communicating with learning tools as per the LTI specification.&lt;br /&gt;
&lt;br /&gt;
Version: 3.0.2&lt;br /&gt;
&lt;br /&gt;
© 2016 IMS Global Learning Consortium Inc. All Rights Reserved. Trademark Policy - (www.imsglobal.org/trademarks)&lt;br /&gt;
&lt;br /&gt;
License: Apache 2&lt;br /&gt;
&lt;br /&gt;
https://github.com/IMSGlobal/LTI-Tool-Provider-Library-PHP&lt;br /&gt;
&lt;br /&gt;
==MathJax==&lt;br /&gt;
&lt;br /&gt;
JavaScript filter library for displaying LaTeX, AsciiMath notation, and MathML.&lt;br /&gt;
&lt;br /&gt;
Not actually included in Moodle. Instead, Moodle [[:en:MathJax filter|has a setting]] for where the library is located to be loaded from. It is currently pointing to the Cloudflare CDN by default.&lt;br /&gt;
&lt;br /&gt;
© Copyright 2009 - 2017 The MathJax Consortium&lt;br /&gt;
&lt;br /&gt;
* Default MathJax version: 2.7.2 (Moodle 3.4)&lt;br /&gt;
* License: Apache 2.0&lt;br /&gt;
* Homepage: https://www.mathjax.org/&lt;br /&gt;
&lt;br /&gt;
==MatthiasMullie\Minify==&lt;br /&gt;
CSS &amp;amp; JavaScript minifier, in PHP&lt;br /&gt;
&lt;br /&gt;
Version 1.3.61&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/matthiasmullie/minify&lt;br /&gt;
&lt;br /&gt;
==MaxMind DB Reader==&lt;br /&gt;
lib/maxmind/MaxMind/&lt;br /&gt;
&lt;br /&gt;
PHP API for reading MaxMind DB files&lt;br /&gt;
&lt;br /&gt;
Version: 1.5.1&lt;br /&gt;
&lt;br /&gt;
Copyright MaxMind&lt;br /&gt;
&lt;br /&gt;
License: Apache 2.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/maxmind/MaxMind-DB-Reader-php/&lt;br /&gt;
&lt;br /&gt;
==mimeTeX==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;filter/tex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Compiled C program to convert TeX into GIFs&lt;br /&gt;
&lt;br /&gt;
Version: 1.74&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002-2004   John Forkosh Associates, Inc&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.forkosh.com/mimetex.html&lt;br /&gt;
&lt;br /&gt;
==Mustache.js==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/amd/src/mustache.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
JS library for displaying mustache templates.&lt;br /&gt;
&lt;br /&gt;
Version: 3.0.1&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2009 Chris Wanstrath (Ruby)&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010-2014 Jan Lehnardt (JavaScript)&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010-2015 The mustache.js community&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/janl/mustache.js/releases&lt;br /&gt;
&lt;br /&gt;
==Mustache==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/mustache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PHP library for displaying mustache templates.&lt;br /&gt;
&lt;br /&gt;
Version: 2.12.0&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010-2016 Justin Hileman&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/bobthecow/mustache.php/releases&lt;br /&gt;
&lt;br /&gt;
==mp3player==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/mp3player&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Flash movie to play streaming MP3s&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005   Andrew Walker&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==overlibmws==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/overlib.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Javascript library to enable DHTML popups, floating windows, events etc&lt;br /&gt;
&lt;br /&gt;
Version: July 2004&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002-2004   Foteos Macrides&lt;br /&gt;
&lt;br /&gt;
Copyright © 1998-2004   Erik Bosrup&lt;br /&gt;
&lt;br /&gt;
License: Artistic Open Source License&lt;br /&gt;
&lt;br /&gt;
http://www.macridesweb.com/oltest/&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PclZip==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pclzip&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to create, manage and unpack zip files.&lt;br /&gt;
&lt;br /&gt;
Version: 2.4 RC1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Vincent Blavet (&#039;&#039;vincent AT phpconcept DOT net&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.phpconcept.net&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PEAR OLE Classes==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to write Excel files&lt;br /&gt;
&lt;br /&gt;
Version: 0.5&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Xavier Noguer&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/OLE&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PEAR Spreadsheet_Excel_Writer==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to write Excel files&lt;br /&gt;
&lt;br /&gt;
Version: 0.9.1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Xavier Noguer and Mika Tuupola&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/Spreadsheet_Excel_Writer&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_Quickform==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to write forms&lt;br /&gt;
&lt;br /&gt;
Version: 3.2.6&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Bertrand Mansion, Adam Daniel, Alexey Borzov&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_Quickform&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_Quickform_Renderer_Tableless==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to render forms without tables&lt;br /&gt;
&lt;br /&gt;
Version: 0.3.4&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005 Mark Wiesemann&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_Quickform_Renderer_Tableless&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_QuickForm_DHTMLRulesTableless==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to render validation notices with dhtml&lt;br /&gt;
&lt;br /&gt;
Version: 0.1.2&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005 Alexey Borzov, Adam Daniel, Bertrand Mansion, Justin Patrin, Mark Wiesemann&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_Common==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class with many common HTML functions (used by HTML Quickform)&lt;br /&gt;
&lt;br /&gt;
Version: 0.3.4&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Adam Daniel, Bertrand Mansion, Klaus Guenther, Alexey Borzov&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_Common&lt;br /&gt;
&lt;br /&gt;
==PEAR XML_Parser==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class implementing one handy (sax-expat) XML parser&lt;br /&gt;
&lt;br /&gt;
Version: 1.3.2&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004-2008 The PHP Group &amp;amp; Stephan Schmidt&lt;br /&gt;
&lt;br /&gt;
License: New BSD License&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/XML_Parser&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PHP-CSS-Parser==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/php-css-parser&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A Parser for CSS Files written in PHP.&lt;br /&gt;
&lt;br /&gt;
Version: 8.3.0&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2011 Raphael Schweikert, http://sabberworm.com/&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/sabberworm/PHP-CSS-Parser&lt;br /&gt;
&lt;br /&gt;
==PHPExcel==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/phpexcel/PHPExcel.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library to read, write and create spreadsheet documents in PHP.&lt;br /&gt;
&lt;br /&gt;
Version 1.8.1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2006 - 2015 PHPExcel&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
https://github.com/PHPOffice/PHPExcel&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PhpSpreadsheet==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/phpspreadsheet&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library to read, write and create spreadsheet documents in PHP.&lt;br /&gt;
&lt;br /&gt;
Version 1.7.0&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
https://github.com/PHPOffice/PhpSpreadsheet&lt;br /&gt;
&lt;br /&gt;
==PHP mailer==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/class.phpmailer.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class for sending email using either sendmail, PHP mail(), or SMTP.  Methods are based upon the standard AspEmail(tm) classes.&lt;br /&gt;
&lt;br /&gt;
Version 6.0.7&lt;br /&gt;
&lt;br /&gt;
Copyright © 2003 Brent R. Matzelle (&#039;&#039;bmatzelle AT yahoo DOT com&#039;&#039;)&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://phpmailer.sourceforge.net&lt;br /&gt;
https://github.com/PHPMailer/PHPMailer/releases&lt;br /&gt;
&lt;br /&gt;
==PHP Markdown==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/markdown.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Functions to convert from the Markdown text format into clean XHTML.&lt;br /&gt;
&lt;br /&gt;
Version: 1.8.0 (with modifications)&lt;br /&gt;
&lt;br /&gt;
 * @copyright 2004-2016 Michel Fortin &amp;lt;https://michelf.com/projects/php-markdown/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 * @copyright (Original Markdown) 2004-2006 John Gruber &amp;lt;https://daringfireball.net/projects/markdown/&amp;gt;&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
http://www.michelf.com/projects/php-markdown/&lt;br /&gt;
&lt;br /&gt;
==PHP-ML==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/mlbackend/php/phpml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Machine learning library used to generate data for the Analytics system.&lt;br /&gt;
&lt;br /&gt;
Version: 0.8.0&lt;br /&gt;
&lt;br /&gt;
 * @copyright 2016-2018 Arkadiusz Kondas &amp;lt;arkadiusz.kondas[at]gmail&amp;gt;&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://php-ml.readthedocs.io/&lt;br /&gt;
&lt;br /&gt;
==Popper.js==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;admin/tool/usertours/amd/src/popper.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
A kickass library used to created Poppers in web applications&lt;br /&gt;
&lt;br /&gt;
Version: 1.12.6&lt;br /&gt;
&lt;br /&gt;
© 2016 Federico Zivolo and contributors&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/FezVrasta/popper.js&lt;br /&gt;
&lt;br /&gt;
==RTLCSS for PHP==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/rtlcss&amp;quot;&lt;br /&gt;
&lt;br /&gt;
RTLCSS is a framework for converting Left-To-Right (LTR) Cascading Style Sheets(CSS) to Right-To-Left (RTL).&lt;br /&gt;
&lt;br /&gt;
© 2016 Frédéric Massart&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/moodlehq/rtlcss-php&lt;br /&gt;
&lt;br /&gt;
==RequireJS==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/lib/requirejs/&#039;&#039;	&lt;br /&gt;
&lt;br /&gt;
RequireJS is a JavaScript file and module loader.&lt;br /&gt;
&lt;br /&gt;
Version 2.3.5&lt;br /&gt;
&lt;br /&gt;
License: new BSD or MIT&lt;br /&gt;
&lt;br /&gt;
http://requirejs.org/&lt;br /&gt;
&lt;br /&gt;
==scssphp==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/lib/scssphp/&#039;&#039;	&lt;br /&gt;
&lt;br /&gt;
scssphp is a compiler for SCSS written in PHP.&lt;br /&gt;
&lt;br /&gt;
Version: 1.0.2&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2015 Leaf Corcoran&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
http://leafo.github.io/scssphp&lt;br /&gt;
&lt;br /&gt;
==SimplePie==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;/lib/simplepie&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Simple Pie helps with blogs.&lt;br /&gt;
&lt;br /&gt;
Version 1.5.2&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
https://github.com/simplepie/simplepie&lt;br /&gt;
&lt;br /&gt;
==Snoopy==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/snoopy&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A PHP net client&lt;br /&gt;
&lt;br /&gt;
Version: 1.0&lt;br /&gt;
&lt;br /&gt;
Copyright © 1999-2000 Monte Ohrt (&#039;&#039;monte AT ispi DOT net&#039;&#039;)&lt;br /&gt;
License: GNU LGPL&lt;br /&gt;
&lt;br /&gt;
http://snoopy.sourceforge.com&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==SMTP class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/class.smtp.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class that can be used to connect and communicate with any SMTP server. It implements all the SMTP functions defined in RFC821 except TURN.&lt;br /&gt;
&lt;br /&gt;
Version: 03/26/2001&lt;br /&gt;
&lt;br /&gt;
Copyright © 2001  Chris Ryan (&#039;&#039;chris AT greatbridge DOT com&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==Spike PHPCoverage==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/spikephpcoverage&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP code coverage reporting tool&lt;br /&gt;
&lt;br /&gt;
Version: 0.8.2 (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004 SpikeSource Inc&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://developer.spikesource.com/projects/phpcoverage&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==Spout==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/spout&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Library for importing and exporting csv / excel / ODS files.&lt;br /&gt;
&lt;br /&gt;
Version 3.0.1&lt;br /&gt;
&lt;br /&gt;
License: Apache&lt;br /&gt;
&lt;br /&gt;
https://github.com/box/spout/&lt;br /&gt;
&lt;br /&gt;
==TCPDF Class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/tcpdf&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to generate PDF files&lt;br /&gt;
&lt;br /&gt;
Version: 6.2.26&lt;br /&gt;
&lt;br /&gt;
Copyright Olivier PLATHEY&lt;br /&gt;
&lt;br /&gt;
License: Freeware&lt;br /&gt;
&lt;br /&gt;
http://www.setasign.com/products/fpdi/downloads&lt;br /&gt;
&lt;br /&gt;
==Typo3 Character Set Class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/typo3&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class for conversion between charsets and multibyte-savy operations with strings.&lt;br /&gt;
&lt;br /&gt;
Version: 4.7.19&lt;br /&gt;
&lt;br /&gt;
Copyright © 2003-2005 Kasper Skaarhoj&lt;br /&gt;
&lt;br /&gt;
Licence: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://typo3.org/&lt;br /&gt;
&lt;br /&gt;
==Video.js==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;amd/src/video-lazy.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
JavaScript library that makes it easier to work with and build on HTML5 video&lt;br /&gt;
&lt;br /&gt;
Version: 7.7.6&lt;br /&gt;
&lt;br /&gt;
Copyright Brightcove, Inc&lt;br /&gt;
&lt;br /&gt;
Licence: Apache&lt;br /&gt;
&lt;br /&gt;
http://videojs.com/&lt;br /&gt;
&lt;br /&gt;
==XHProf==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/xhprof&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A Hierarchical Profiler for PHP&lt;br /&gt;
&lt;br /&gt;
Version: 0.9.4&lt;br /&gt;
&lt;br /&gt;
Copyright © 2009 Phacility&lt;br /&gt;
&lt;br /&gt;
Licence: Apache&lt;br /&gt;
&lt;br /&gt;
https://github.com/phacility/xhprof&lt;br /&gt;
&lt;br /&gt;
==Yahoo User Interface==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/yui&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Yahoo! User Interface Library is a set of utilities and controls, in JavaScript, for building richly interactive web applications using techniques such as DOM scripting, DHTML and AJAX. The YUI Library also includes several core CSS resources.Set of user-interface components using AJAX, DHTML etc.  We use it for all our AJAX-related stuff.&lt;br /&gt;
&lt;br /&gt;
CVS version: 3.17.2&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2006, Yahoo! Inc.&lt;br /&gt;
&lt;br /&gt;
Licence: BSD&lt;br /&gt;
&lt;br /&gt;
http://developer.yahoo.com/yui/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Credits]]&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_libraries_credits&amp;diff=58772</id>
		<title>Moodle libraries credits</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_libraries_credits&amp;diff=58772"/>
		<updated>2021-05-11T06:35:46Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* HTML Purifier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Some of Moodle&#039;s libraries were written by other people, and are being redistributed as part of Moodle under their respective open source licenses that thankfully allow us to do so. Thanks to the authors of all these excellent products - without them Moodle would be missing important functionality. Copyright information for each package is included below:&lt;br /&gt;
&lt;br /&gt;
==ADOdb==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/adodb&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Database abstraction library for MySQL, PostgreSQL, MSSQL, Oracle, Interbase, Foxpro, Access, ADO, Sybase, DB2 and ODBC.&lt;br /&gt;
&lt;br /&gt;
Version: 5.20.14&lt;br /&gt;
&lt;br /&gt;
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.&lt;br /&gt;
&lt;br /&gt;
@copyright (c) 2014      Damien Regad, Mark Newnham and the ADOdb community&lt;br /&gt;
&lt;br /&gt;
License: Dual LGPL and BSD-style&lt;br /&gt;
&lt;br /&gt;
http://adodb.sourceforge.net&lt;br /&gt;
&lt;br /&gt;
==Bennu==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/bennu&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Bennu is an object-oriented library written in PHP that implements the iCalendar standard (RFC 2445).&lt;br /&gt;
&lt;br /&gt;
Version: 0.1 (customized since then)&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2005, Jon Papaioannou&lt;br /&gt;
&lt;br /&gt;
License: LGPL 2.1+&lt;br /&gt;
&lt;br /&gt;
http://bennu.sourceforge.net/&lt;br /&gt;
&lt;br /&gt;
==Amazon S3==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;repository/s3/S3.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A standalone Amazon S3 (REST) client for PHP 5.2.x using CURL that does not require PEAR. &lt;br /&gt;
&lt;br /&gt;
Version: 0.5.1&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2013, Donovan Schönknecht&lt;br /&gt;
&lt;br /&gt;
License: BSD 2-Clause&lt;br /&gt;
&lt;br /&gt;
https://github.com/tpyo/amazon-s3-php-class/releases&lt;br /&gt;
&lt;br /&gt;
==CAS==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;auth/cas/CAS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
phpCAS library to support CAS authentication plugin&lt;br /&gt;
&lt;br /&gt;
Version: 1.3.7&lt;br /&gt;
&lt;br /&gt;
Copyright Jasig&lt;br /&gt;
&lt;br /&gt;
License: Apache License 2.0&lt;br /&gt;
&lt;br /&gt;
https://wiki.jasig.org/display/CASC/phpCAS&lt;br /&gt;
&lt;br /&gt;
==Chart.js==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/amd/src/chartjs-lazy.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Simple yet flexible JavaScript charting for designers &amp;amp; developers&lt;br /&gt;
&lt;br /&gt;
Version: 2.9.4&lt;br /&gt;
&lt;br /&gt;
Copyright 2016 Nick Downie&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
http://www.chartjs.org&lt;br /&gt;
&lt;br /&gt;
==Emoji-data==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/emoji-data&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library to parse easily data and spritesheets for emoji&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/iamcal/emoji-data/&lt;br /&gt;
&lt;br /&gt;
==EvalMath==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/evalmath&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to safely evaluate math expressions&lt;br /&gt;
&lt;br /&gt;
Copyright Miles Kaufmann&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
http://www.twmagic.com/&lt;br /&gt;
&lt;br /&gt;
==Flexitour==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;admin/tool/usertours/amd/src/tour.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
A JS library for tours&lt;br /&gt;
&lt;br /&gt;
© 2016 Andrew Nicols and contributors&lt;br /&gt;
&lt;br /&gt;
License: GPLv3&lt;br /&gt;
&lt;br /&gt;
https://github.com/andrewnicols/flexitour&lt;br /&gt;
&lt;br /&gt;
==FLV player==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;filter/mediaplugin/flvplayer.swf&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Flash movie to play FLV files&lt;br /&gt;
&lt;br /&gt;
Copyright Jeroen Wijering &lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.jeroenwijering.com&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
== GeoIp2 ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/maxmind/GeoIp2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library for processing of GeoIP data files&lt;br /&gt;
&lt;br /&gt;
Version: 2.10.0&lt;br /&gt;
&lt;br /&gt;
Copyright MaxMind&lt;br /&gt;
&lt;br /&gt;
License: Apache 2.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/maxmind/GeoIP2-php&lt;br /&gt;
&lt;br /&gt;
== GeoPattern==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/geopattern-php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library for creating beautiful generative background images from a string&lt;br /&gt;
&lt;br /&gt;
Version: 1.1.1&lt;br /&gt;
&lt;br /&gt;
Copyright 2015 Leaf Corcoran&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/RedeyeGroup/geopattern-php&lt;br /&gt;
&lt;br /&gt;
==Google APIs==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/google&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Library Google APIs Client Library for PHP&lt;br /&gt;
&lt;br /&gt;
Version: 1.1.7&lt;br /&gt;
&lt;br /&gt;
License: Apache License Version 2.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/google/google-api-php-client&lt;br /&gt;
&lt;br /&gt;
==Graph Class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/graphlib.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to draw line, point, bar, and area graphs, including numeric x-axis and double y-axis.&lt;br /&gt;
&lt;br /&gt;
Version: 1.6.3 (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2000  Herman Veluwenkamp (&#039;&#039;hermanV AT mindless DOT com&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
==H5P==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/h5p&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The general H5P library&lt;br /&gt;
&lt;br /&gt;
Version: 1.24&lt;br /&gt;
&lt;br /&gt;
Copyright © Joubel&lt;br /&gt;
&lt;br /&gt;
License: GPL-3.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/h5p/h5p-php-library/&lt;br /&gt;
&lt;br /&gt;
==Horde==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/horde&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library used by the inbound e-mail handling system.&lt;br /&gt;
&lt;br /&gt;
Version: 5.2.22&lt;br /&gt;
&lt;br /&gt;
Copyright © Horde LLC&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://www.horde.org/&lt;br /&gt;
&lt;br /&gt;
==html2text==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/html2text&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP script to convert HTML into an approximate text equivalent&lt;br /&gt;
&lt;br /&gt;
Version: 4.2.1&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2005-2007 Jon Abernathy &amp;lt;jon@chuggnutt.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
https://github.com/mtibben/html2text.git&lt;br /&gt;
&lt;br /&gt;
==htmlArea==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/editor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Javascript/HTML script to put a GUI editor in textareas on Internet Explorer and Mozilla&lt;br /&gt;
&lt;br /&gt;
Version: 3.0 beta (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002  interactivetools.com, inc.&lt;br /&gt;
&lt;br /&gt;
License: htmlArea License (based on BSD license)&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==HTML Purifier==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/htmlpurifier&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Filters HTML.&lt;br /&gt;
&lt;br /&gt;
Version: 4.13.0&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
==IP-Atlas==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/ipatlas&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP scripts to show the location of an IP address on a map.&lt;br /&gt;
&lt;br /&gt;
Version: 1.0 (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002   Ivan Kozik&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.xpenguin.com/ip-atlas.php&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==Jabber - XMPPHP==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jabber&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP library for XMPP (aka Jabber, Google Talk, etc).&lt;br /&gt;
&lt;br /&gt;
Version: 0.1rc2-r77&lt;br /&gt;
&lt;br /&gt;
Copyright: 2008  Nathanael C. Fritz&lt;br /&gt;
&lt;br /&gt;
License: GPL&lt;br /&gt;
&lt;br /&gt;
http://code.google.com/p/xmpphp&lt;br /&gt;
&lt;br /&gt;
==jQuery==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jquery&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
jQuery is a fast, small, and feature-rich JavaScript library widely used on moodle.&lt;br /&gt;
&lt;br /&gt;
Version: 3.4.1&lt;br /&gt;
&lt;br /&gt;
Copyright: 2016 The jQuery Foundation&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://jquery.com&lt;br /&gt;
&lt;br /&gt;
==jQuery migrate==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jquery/jquery-migrate-1.4.0.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library used migrate older jQuery code to jQuery 3.0.&lt;br /&gt;
&lt;br /&gt;
Version: 1.4.0&lt;br /&gt;
&lt;br /&gt;
Copyright: 2016 The jQuery Foundation and other contributors&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/jquery/jquery-migrate&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==jQuery UI==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jquery/ui-1.12.1/&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
jQuery UI is a set of user interface interactions, effects, widgets, and themes built on top of the jQuery library.&lt;br /&gt;
&lt;br /&gt;
Version: 1.12.1&lt;br /&gt;
&lt;br /&gt;
Copyright: 2016 The jQuery Foundation and other contributors&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/jquery/jquery-migrate&lt;br /&gt;
&lt;br /&gt;
==Services_JSON==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Allows PHP-&amp;gt;JS communication via JSON&lt;br /&gt;
&lt;br /&gt;
Version: 1.3.1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005 Michal Migurski&lt;br /&gt;
&lt;br /&gt;
License: Modified BSD (GPL-compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/pepr/pepr-proposal-show.php?id=198&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==JWT==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/php-jwt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to RFC 7519&lt;br /&gt;
&lt;br /&gt;
Version: 5.0.0&lt;br /&gt;
&lt;br /&gt;
Copyright © 2011, Neuman Vong&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
https://github.com/firebase/php-jwt&lt;br /&gt;
&lt;br /&gt;
==ENUM==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/php-enum&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP Enum implementation inspired from SplEnum&lt;br /&gt;
&lt;br /&gt;
Version: 1.7.6&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2015 My C-Labs&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/myclabs/php-enum&lt;br /&gt;
&lt;br /&gt;
==kses==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/kses.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
HTML/XHTML filter that only allows some elements and attributes&lt;br /&gt;
&lt;br /&gt;
Version: 0.2.2&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002, 2003, 2005   Ulf Harnhammar&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://sourceforge.net/projects/kses&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==less.php==&lt;br /&gt;
&lt;br /&gt;
The less.php is a PHP port of the official LESS processor used by moodle themes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/lessphp&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Version: 1.7.0.10&lt;br /&gt;
&lt;br /&gt;
License: Apache 2.0&lt;br /&gt;
&lt;br /&gt;
http://lessphp.typesettercms.com/&lt;br /&gt;
&lt;br /&gt;
Copyright:  Matt Agar and Martin Jantošovič&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==loglevel.js==&lt;br /&gt;
&lt;br /&gt;
Minimal lightweight simple logging for JavaScript.&lt;br /&gt;
&lt;br /&gt;
Version 1.6.6&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2019 Tim Perry&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/pimterry/loglevel/&lt;br /&gt;
&lt;br /&gt;
==LTI Tool Provider Library for PHP==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/ltiprovider/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PHP library for communicating with learning tools as per the LTI specification.&lt;br /&gt;
&lt;br /&gt;
Version: 3.0.2&lt;br /&gt;
&lt;br /&gt;
© 2016 IMS Global Learning Consortium Inc. All Rights Reserved. Trademark Policy - (www.imsglobal.org/trademarks)&lt;br /&gt;
&lt;br /&gt;
License: Apache 2&lt;br /&gt;
&lt;br /&gt;
https://github.com/IMSGlobal/LTI-Tool-Provider-Library-PHP&lt;br /&gt;
&lt;br /&gt;
==MathJax==&lt;br /&gt;
&lt;br /&gt;
JavaScript filter library for displaying LaTeX, AsciiMath notation, and MathML.&lt;br /&gt;
&lt;br /&gt;
Not actually included in Moodle. Instead, Moodle [[:en:MathJax filter|has a setting]] for where the library is located to be loaded from. It is currently pointing to the Cloudflare CDN by default.&lt;br /&gt;
&lt;br /&gt;
© Copyright 2009 - 2017 The MathJax Consortium&lt;br /&gt;
&lt;br /&gt;
* Default MathJax version: 2.7.2 (Moodle 3.4)&lt;br /&gt;
* License: Apache 2.0&lt;br /&gt;
* Homepage: https://www.mathjax.org/&lt;br /&gt;
&lt;br /&gt;
==MatthiasMullie\Minify==&lt;br /&gt;
CSS &amp;amp; JavaScript minifier, in PHP&lt;br /&gt;
&lt;br /&gt;
Version 1.3.61&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/matthiasmullie/minify&lt;br /&gt;
&lt;br /&gt;
==MaxMind DB Reader==&lt;br /&gt;
lib/maxmind/MaxMind/&lt;br /&gt;
&lt;br /&gt;
PHP API for reading MaxMind DB files&lt;br /&gt;
&lt;br /&gt;
Version: 1.5.1&lt;br /&gt;
&lt;br /&gt;
Copyright MaxMind&lt;br /&gt;
&lt;br /&gt;
License: Apache 2.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/maxmind/MaxMind-DB-Reader-php/&lt;br /&gt;
&lt;br /&gt;
==mimeTeX==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;filter/tex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Compiled C program to convert TeX into GIFs&lt;br /&gt;
&lt;br /&gt;
Version: 1.74&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002-2004   John Forkosh Associates, Inc&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.forkosh.com/mimetex.html&lt;br /&gt;
&lt;br /&gt;
==Mustache.js==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/amd/src/mustache.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
JS library for displaying mustache templates.&lt;br /&gt;
&lt;br /&gt;
Version: 3.0.1&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2009 Chris Wanstrath (Ruby)&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010-2014 Jan Lehnardt (JavaScript)&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010-2015 The mustache.js community&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/janl/mustache.js/releases&lt;br /&gt;
&lt;br /&gt;
==Mustache==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/mustache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PHP library for displaying mustache templates.&lt;br /&gt;
&lt;br /&gt;
Version: 2.12.0&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010-2016 Justin Hileman&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/bobthecow/mustache.php/releases&lt;br /&gt;
&lt;br /&gt;
==mp3player==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/mp3player&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Flash movie to play streaming MP3s&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005   Andrew Walker&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==overlibmws==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/overlib.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Javascript library to enable DHTML popups, floating windows, events etc&lt;br /&gt;
&lt;br /&gt;
Version: July 2004&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002-2004   Foteos Macrides&lt;br /&gt;
&lt;br /&gt;
Copyright © 1998-2004   Erik Bosrup&lt;br /&gt;
&lt;br /&gt;
License: Artistic Open Source License&lt;br /&gt;
&lt;br /&gt;
http://www.macridesweb.com/oltest/&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PclZip==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pclzip&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to create, manage and unpack zip files.&lt;br /&gt;
&lt;br /&gt;
Version: 2.4 RC1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Vincent Blavet (&#039;&#039;vincent AT phpconcept DOT net&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.phpconcept.net&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PEAR OLE Classes==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to write Excel files&lt;br /&gt;
&lt;br /&gt;
Version: 0.5&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Xavier Noguer&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/OLE&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PEAR Spreadsheet_Excel_Writer==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to write Excel files&lt;br /&gt;
&lt;br /&gt;
Version: 0.9.1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Xavier Noguer and Mika Tuupola&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/Spreadsheet_Excel_Writer&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_Quickform==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to write forms&lt;br /&gt;
&lt;br /&gt;
Version: 3.2.6&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Bertrand Mansion, Adam Daniel, Alexey Borzov&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_Quickform&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_Quickform_Renderer_Tableless==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to render forms without tables&lt;br /&gt;
&lt;br /&gt;
Version: 0.3.4&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005 Mark Wiesemann&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_Quickform_Renderer_Tableless&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_QuickForm_DHTMLRulesTableless==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to render validation notices with dhtml&lt;br /&gt;
&lt;br /&gt;
Version: 0.1.2&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005 Alexey Borzov, Adam Daniel, Bertrand Mansion, Justin Patrin, Mark Wiesemann&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_Common==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class with many common HTML functions (used by HTML Quickform)&lt;br /&gt;
&lt;br /&gt;
Version: 0.3.4&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Adam Daniel, Bertrand Mansion, Klaus Guenther, Alexey Borzov&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_Common&lt;br /&gt;
&lt;br /&gt;
==PEAR XML_Parser==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class implementing one handy (sax-expat) XML parser&lt;br /&gt;
&lt;br /&gt;
Version: 1.3.2&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004-2008 The PHP Group &amp;amp; Stephan Schmidt&lt;br /&gt;
&lt;br /&gt;
License: New BSD License&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/XML_Parser&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PHP-CSS-Parser==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/php-css-parser&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A Parser for CSS Files written in PHP.&lt;br /&gt;
&lt;br /&gt;
Version: 8.3.0&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2011 Raphael Schweikert, http://sabberworm.com/&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/sabberworm/PHP-CSS-Parser&lt;br /&gt;
&lt;br /&gt;
==PHPExcel==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/phpexcel/PHPExcel.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library to read, write and create spreadsheet documents in PHP.&lt;br /&gt;
&lt;br /&gt;
Version 1.8.1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2006 - 2015 PHPExcel&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
https://github.com/PHPOffice/PHPExcel&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PhpSpreadsheet==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/phpspreadsheet&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library to read, write and create spreadsheet documents in PHP.&lt;br /&gt;
&lt;br /&gt;
Version 1.7.0&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
https://github.com/PHPOffice/PhpSpreadsheet&lt;br /&gt;
&lt;br /&gt;
==PHP mailer==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/class.phpmailer.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class for sending email using either sendmail, PHP mail(), or SMTP.  Methods are based upon the standard AspEmail(tm) classes.&lt;br /&gt;
&lt;br /&gt;
Version 6.0.7&lt;br /&gt;
&lt;br /&gt;
Copyright © 2003 Brent R. Matzelle (&#039;&#039;bmatzelle AT yahoo DOT com&#039;&#039;)&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://phpmailer.sourceforge.net&lt;br /&gt;
https://github.com/PHPMailer/PHPMailer/releases&lt;br /&gt;
&lt;br /&gt;
==PHP Markdown==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/markdown.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Functions to convert from the Markdown text format into clean XHTML.&lt;br /&gt;
&lt;br /&gt;
Version: 1.8.0 (with modifications)&lt;br /&gt;
&lt;br /&gt;
 * @copyright 2004-2016 Michel Fortin &amp;lt;https://michelf.com/projects/php-markdown/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 * @copyright (Original Markdown) 2004-2006 John Gruber &amp;lt;https://daringfireball.net/projects/markdown/&amp;gt;&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
http://www.michelf.com/projects/php-markdown/&lt;br /&gt;
&lt;br /&gt;
==PHP-ML==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/mlbackend/php/phpml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Machine learning library used to generate data for the Analytics system.&lt;br /&gt;
&lt;br /&gt;
Version: 0.8.0&lt;br /&gt;
&lt;br /&gt;
 * @copyright 2016-2018 Arkadiusz Kondas &amp;lt;arkadiusz.kondas[at]gmail&amp;gt;&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://php-ml.readthedocs.io/&lt;br /&gt;
&lt;br /&gt;
==Popper.js==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;admin/tool/usertours/amd/src/popper.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
A kickass library used to created Poppers in web applications&lt;br /&gt;
&lt;br /&gt;
Version: 1.12.6&lt;br /&gt;
&lt;br /&gt;
© 2016 Federico Zivolo and contributors&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/FezVrasta/popper.js&lt;br /&gt;
&lt;br /&gt;
==RTLCSS for PHP==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/rtlcss&amp;quot;&lt;br /&gt;
&lt;br /&gt;
RTLCSS is a framework for converting Left-To-Right (LTR) Cascading Style Sheets(CSS) to Right-To-Left (RTL).&lt;br /&gt;
&lt;br /&gt;
© 2016 Frédéric Massart&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/moodlehq/rtlcss-php&lt;br /&gt;
&lt;br /&gt;
==RequireJS==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/lib/requirejs/&#039;&#039;	&lt;br /&gt;
&lt;br /&gt;
RequireJS is a JavaScript file and module loader.&lt;br /&gt;
&lt;br /&gt;
Version 2.3.5&lt;br /&gt;
&lt;br /&gt;
License: new BSD or MIT&lt;br /&gt;
&lt;br /&gt;
http://requirejs.org/&lt;br /&gt;
&lt;br /&gt;
==scssphp==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/lib/scssphp/&#039;&#039;	&lt;br /&gt;
&lt;br /&gt;
scssphp is a compiler for SCSS written in PHP.&lt;br /&gt;
&lt;br /&gt;
Version: 1.0.2&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2015 Leaf Corcoran&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
http://leafo.github.io/scssphp&lt;br /&gt;
&lt;br /&gt;
==SimplePie==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;/lib/simplepie&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Simple Pie helps with blogs.&lt;br /&gt;
&lt;br /&gt;
Version 1.5.2&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
https://github.com/simplepie/simplepie&lt;br /&gt;
&lt;br /&gt;
==Snoopy==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/snoopy&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A PHP net client&lt;br /&gt;
&lt;br /&gt;
Version: 1.0&lt;br /&gt;
&lt;br /&gt;
Copyright © 1999-2000 Monte Ohrt (&#039;&#039;monte AT ispi DOT net&#039;&#039;)&lt;br /&gt;
License: GNU LGPL&lt;br /&gt;
&lt;br /&gt;
http://snoopy.sourceforge.com&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==SMTP class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/class.smtp.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class that can be used to connect and communicate with any SMTP server. It implements all the SMTP functions defined in RFC821 except TURN.&lt;br /&gt;
&lt;br /&gt;
Version: 03/26/2001&lt;br /&gt;
&lt;br /&gt;
Copyright © 2001  Chris Ryan (&#039;&#039;chris AT greatbridge DOT com&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==Spike PHPCoverage==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/spikephpcoverage&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP code coverage reporting tool&lt;br /&gt;
&lt;br /&gt;
Version: 0.8.2 (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004 SpikeSource Inc&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://developer.spikesource.com/projects/phpcoverage&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==Spout==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/spout&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Library for importing and exporting csv / excel / ODS files.&lt;br /&gt;
&lt;br /&gt;
Version 3.0.1&lt;br /&gt;
&lt;br /&gt;
License: Apache&lt;br /&gt;
&lt;br /&gt;
https://github.com/box/spout/&lt;br /&gt;
&lt;br /&gt;
==TCPDF Class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/tcpdf&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to generate PDF files&lt;br /&gt;
&lt;br /&gt;
Version: 6.2.26&lt;br /&gt;
&lt;br /&gt;
Copyright Olivier PLATHEY&lt;br /&gt;
&lt;br /&gt;
License: Freeware&lt;br /&gt;
&lt;br /&gt;
http://www.setasign.com/products/fpdi/downloads&lt;br /&gt;
&lt;br /&gt;
==Typo3 Character Set Class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/typo3&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class for conversion between charsets and multibyte-savy operations with strings.&lt;br /&gt;
&lt;br /&gt;
Version: 4.7.19&lt;br /&gt;
&lt;br /&gt;
Copyright © 2003-2005 Kasper Skaarhoj&lt;br /&gt;
&lt;br /&gt;
Licence: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://typo3.org/&lt;br /&gt;
&lt;br /&gt;
==Video.js==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;amd/src/video-lazy.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
JavaScript library that makes it easier to work with and build on HTML5 video&lt;br /&gt;
&lt;br /&gt;
Version: 7.7.6&lt;br /&gt;
&lt;br /&gt;
Copyright Brightcove, Inc&lt;br /&gt;
&lt;br /&gt;
Licence: Apache&lt;br /&gt;
&lt;br /&gt;
http://videojs.com/&lt;br /&gt;
&lt;br /&gt;
==XHProf==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/xhprof&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A Hierarchical Profiler for PHP&lt;br /&gt;
&lt;br /&gt;
Version: 0.9.4&lt;br /&gt;
&lt;br /&gt;
Copyright © 2009 Phacility&lt;br /&gt;
&lt;br /&gt;
Licence: Apache&lt;br /&gt;
&lt;br /&gt;
https://github.com/phacility/xhprof&lt;br /&gt;
&lt;br /&gt;
==Yahoo User Interface==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/yui&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Yahoo! User Interface Library is a set of utilities and controls, in JavaScript, for building richly interactive web applications using techniques such as DOM scripting, DHTML and AJAX. The YUI Library also includes several core CSS resources.Set of user-interface components using AJAX, DHTML etc.  We use it for all our AJAX-related stuff.&lt;br /&gt;
&lt;br /&gt;
CVS version: 3.17.2&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2006, Yahoo! Inc.&lt;br /&gt;
&lt;br /&gt;
Licence: BSD&lt;br /&gt;
&lt;br /&gt;
http://developer.yahoo.com/yui/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Credits]]&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_libraries_credits&amp;diff=58771</id>
		<title>Moodle libraries credits</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_libraries_credits&amp;diff=58771"/>
		<updated>2021-05-11T06:33:42Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: /* Chart.js */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Some of Moodle&#039;s libraries were written by other people, and are being redistributed as part of Moodle under their respective open source licenses that thankfully allow us to do so. Thanks to the authors of all these excellent products - without them Moodle would be missing important functionality. Copyright information for each package is included below:&lt;br /&gt;
&lt;br /&gt;
==ADOdb==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/adodb&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Database abstraction library for MySQL, PostgreSQL, MSSQL, Oracle, Interbase, Foxpro, Access, ADO, Sybase, DB2 and ODBC.&lt;br /&gt;
&lt;br /&gt;
Version: 5.20.14&lt;br /&gt;
&lt;br /&gt;
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.&lt;br /&gt;
&lt;br /&gt;
@copyright (c) 2014      Damien Regad, Mark Newnham and the ADOdb community&lt;br /&gt;
&lt;br /&gt;
License: Dual LGPL and BSD-style&lt;br /&gt;
&lt;br /&gt;
http://adodb.sourceforge.net&lt;br /&gt;
&lt;br /&gt;
==Bennu==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/bennu&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Bennu is an object-oriented library written in PHP that implements the iCalendar standard (RFC 2445).&lt;br /&gt;
&lt;br /&gt;
Version: 0.1 (customized since then)&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2005, Jon Papaioannou&lt;br /&gt;
&lt;br /&gt;
License: LGPL 2.1+&lt;br /&gt;
&lt;br /&gt;
http://bennu.sourceforge.net/&lt;br /&gt;
&lt;br /&gt;
==Amazon S3==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;repository/s3/S3.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A standalone Amazon S3 (REST) client for PHP 5.2.x using CURL that does not require PEAR. &lt;br /&gt;
&lt;br /&gt;
Version: 0.5.1&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2013, Donovan Schönknecht&lt;br /&gt;
&lt;br /&gt;
License: BSD 2-Clause&lt;br /&gt;
&lt;br /&gt;
https://github.com/tpyo/amazon-s3-php-class/releases&lt;br /&gt;
&lt;br /&gt;
==CAS==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;auth/cas/CAS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
phpCAS library to support CAS authentication plugin&lt;br /&gt;
&lt;br /&gt;
Version: 1.3.7&lt;br /&gt;
&lt;br /&gt;
Copyright Jasig&lt;br /&gt;
&lt;br /&gt;
License: Apache License 2.0&lt;br /&gt;
&lt;br /&gt;
https://wiki.jasig.org/display/CASC/phpCAS&lt;br /&gt;
&lt;br /&gt;
==Chart.js==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/amd/src/chartjs-lazy.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Simple yet flexible JavaScript charting for designers &amp;amp; developers&lt;br /&gt;
&lt;br /&gt;
Version: 2.9.4&lt;br /&gt;
&lt;br /&gt;
Copyright 2016 Nick Downie&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
http://www.chartjs.org&lt;br /&gt;
&lt;br /&gt;
==Emoji-data==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/emoji-data&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library to parse easily data and spritesheets for emoji&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/iamcal/emoji-data/&lt;br /&gt;
&lt;br /&gt;
==EvalMath==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/evalmath&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to safely evaluate math expressions&lt;br /&gt;
&lt;br /&gt;
Copyright Miles Kaufmann&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
http://www.twmagic.com/&lt;br /&gt;
&lt;br /&gt;
==Flexitour==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;admin/tool/usertours/amd/src/tour.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
A JS library for tours&lt;br /&gt;
&lt;br /&gt;
© 2016 Andrew Nicols and contributors&lt;br /&gt;
&lt;br /&gt;
License: GPLv3&lt;br /&gt;
&lt;br /&gt;
https://github.com/andrewnicols/flexitour&lt;br /&gt;
&lt;br /&gt;
==FLV player==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;filter/mediaplugin/flvplayer.swf&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Flash movie to play FLV files&lt;br /&gt;
&lt;br /&gt;
Copyright Jeroen Wijering &lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.jeroenwijering.com&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
== GeoIp2 ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/maxmind/GeoIp2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library for processing of GeoIP data files&lt;br /&gt;
&lt;br /&gt;
Version: 2.10.0&lt;br /&gt;
&lt;br /&gt;
Copyright MaxMind&lt;br /&gt;
&lt;br /&gt;
License: Apache 2.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/maxmind/GeoIP2-php&lt;br /&gt;
&lt;br /&gt;
== GeoPattern==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/geopattern-php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library for creating beautiful generative background images from a string&lt;br /&gt;
&lt;br /&gt;
Version: 1.1.1&lt;br /&gt;
&lt;br /&gt;
Copyright 2015 Leaf Corcoran&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/RedeyeGroup/geopattern-php&lt;br /&gt;
&lt;br /&gt;
==Google APIs==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/google&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Library Google APIs Client Library for PHP&lt;br /&gt;
&lt;br /&gt;
Version: 1.1.7&lt;br /&gt;
&lt;br /&gt;
License: Apache License Version 2.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/google/google-api-php-client&lt;br /&gt;
&lt;br /&gt;
==Graph Class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/graphlib.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to draw line, point, bar, and area graphs, including numeric x-axis and double y-axis.&lt;br /&gt;
&lt;br /&gt;
Version: 1.6.3 (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2000  Herman Veluwenkamp (&#039;&#039;hermanV AT mindless DOT com&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
==H5P==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/h5p&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The general H5P library&lt;br /&gt;
&lt;br /&gt;
Version: 1.24&lt;br /&gt;
&lt;br /&gt;
Copyright © Joubel&lt;br /&gt;
&lt;br /&gt;
License: GPL-3.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/h5p/h5p-php-library/&lt;br /&gt;
&lt;br /&gt;
==Horde==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/horde&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library used by the inbound e-mail handling system.&lt;br /&gt;
&lt;br /&gt;
Version: 5.2.22&lt;br /&gt;
&lt;br /&gt;
Copyright © Horde LLC&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://www.horde.org/&lt;br /&gt;
&lt;br /&gt;
==html2text==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/html2text&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP script to convert HTML into an approximate text equivalent&lt;br /&gt;
&lt;br /&gt;
Version: 4.2.1&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2005-2007 Jon Abernathy &amp;lt;jon@chuggnutt.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
https://github.com/mtibben/html2text.git&lt;br /&gt;
&lt;br /&gt;
==htmlArea==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/editor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Javascript/HTML script to put a GUI editor in textareas on Internet Explorer and Mozilla&lt;br /&gt;
&lt;br /&gt;
Version: 3.0 beta (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002  interactivetools.com, inc.&lt;br /&gt;
&lt;br /&gt;
License: htmlArea License (based on BSD license)&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==HTML Purifier==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/htmlpurifier&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Filters HTML.&lt;br /&gt;
&lt;br /&gt;
Version: 4.10.0&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
==IP-Atlas==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/ipatlas&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP scripts to show the location of an IP address on a map.&lt;br /&gt;
&lt;br /&gt;
Version: 1.0 (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002   Ivan Kozik&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.xpenguin.com/ip-atlas.php&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==Jabber - XMPPHP==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jabber&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP library for XMPP (aka Jabber, Google Talk, etc).&lt;br /&gt;
&lt;br /&gt;
Version: 0.1rc2-r77&lt;br /&gt;
&lt;br /&gt;
Copyright: 2008  Nathanael C. Fritz&lt;br /&gt;
&lt;br /&gt;
License: GPL&lt;br /&gt;
&lt;br /&gt;
http://code.google.com/p/xmpphp&lt;br /&gt;
&lt;br /&gt;
==jQuery==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jquery&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
jQuery is a fast, small, and feature-rich JavaScript library widely used on moodle.&lt;br /&gt;
&lt;br /&gt;
Version: 3.4.1&lt;br /&gt;
&lt;br /&gt;
Copyright: 2016 The jQuery Foundation&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://jquery.com&lt;br /&gt;
&lt;br /&gt;
==jQuery migrate==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jquery/jquery-migrate-1.4.0.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library used migrate older jQuery code to jQuery 3.0.&lt;br /&gt;
&lt;br /&gt;
Version: 1.4.0&lt;br /&gt;
&lt;br /&gt;
Copyright: 2016 The jQuery Foundation and other contributors&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/jquery/jquery-migrate&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==jQuery UI==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/jquery/ui-1.12.1/&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
jQuery UI is a set of user interface interactions, effects, widgets, and themes built on top of the jQuery library.&lt;br /&gt;
&lt;br /&gt;
Version: 1.12.1&lt;br /&gt;
&lt;br /&gt;
Copyright: 2016 The jQuery Foundation and other contributors&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/jquery/jquery-migrate&lt;br /&gt;
&lt;br /&gt;
==Services_JSON==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/json&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Allows PHP-&amp;gt;JS communication via JSON&lt;br /&gt;
&lt;br /&gt;
Version: 1.3.1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005 Michal Migurski&lt;br /&gt;
&lt;br /&gt;
License: Modified BSD (GPL-compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/pepr/pepr-proposal-show.php?id=198&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==JWT==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/php-jwt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to RFC 7519&lt;br /&gt;
&lt;br /&gt;
Version: 5.0.0&lt;br /&gt;
&lt;br /&gt;
Copyright © 2011, Neuman Vong&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
https://github.com/firebase/php-jwt&lt;br /&gt;
&lt;br /&gt;
==ENUM==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/php-enum&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP Enum implementation inspired from SplEnum&lt;br /&gt;
&lt;br /&gt;
Version: 1.7.6&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2015 My C-Labs&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/myclabs/php-enum&lt;br /&gt;
&lt;br /&gt;
==kses==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/kses.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
HTML/XHTML filter that only allows some elements and attributes&lt;br /&gt;
&lt;br /&gt;
Version: 0.2.2&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002, 2003, 2005   Ulf Harnhammar&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://sourceforge.net/projects/kses&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==less.php==&lt;br /&gt;
&lt;br /&gt;
The less.php is a PHP port of the official LESS processor used by moodle themes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/lessphp&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Version: 1.7.0.10&lt;br /&gt;
&lt;br /&gt;
License: Apache 2.0&lt;br /&gt;
&lt;br /&gt;
http://lessphp.typesettercms.com/&lt;br /&gt;
&lt;br /&gt;
Copyright:  Matt Agar and Martin Jantošovič&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==loglevel.js==&lt;br /&gt;
&lt;br /&gt;
Minimal lightweight simple logging for JavaScript.&lt;br /&gt;
&lt;br /&gt;
Version 1.6.6&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2019 Tim Perry&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/pimterry/loglevel/&lt;br /&gt;
&lt;br /&gt;
==LTI Tool Provider Library for PHP==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/ltiprovider/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PHP library for communicating with learning tools as per the LTI specification.&lt;br /&gt;
&lt;br /&gt;
Version: 3.0.2&lt;br /&gt;
&lt;br /&gt;
© 2016 IMS Global Learning Consortium Inc. All Rights Reserved. Trademark Policy - (www.imsglobal.org/trademarks)&lt;br /&gt;
&lt;br /&gt;
License: Apache 2&lt;br /&gt;
&lt;br /&gt;
https://github.com/IMSGlobal/LTI-Tool-Provider-Library-PHP&lt;br /&gt;
&lt;br /&gt;
==MathJax==&lt;br /&gt;
&lt;br /&gt;
JavaScript filter library for displaying LaTeX, AsciiMath notation, and MathML.&lt;br /&gt;
&lt;br /&gt;
Not actually included in Moodle. Instead, Moodle [[:en:MathJax filter|has a setting]] for where the library is located to be loaded from. It is currently pointing to the Cloudflare CDN by default.&lt;br /&gt;
&lt;br /&gt;
© Copyright 2009 - 2017 The MathJax Consortium&lt;br /&gt;
&lt;br /&gt;
* Default MathJax version: 2.7.2 (Moodle 3.4)&lt;br /&gt;
* License: Apache 2.0&lt;br /&gt;
* Homepage: https://www.mathjax.org/&lt;br /&gt;
&lt;br /&gt;
==MatthiasMullie\Minify==&lt;br /&gt;
CSS &amp;amp; JavaScript minifier, in PHP&lt;br /&gt;
&lt;br /&gt;
Version 1.3.61&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/matthiasmullie/minify&lt;br /&gt;
&lt;br /&gt;
==MaxMind DB Reader==&lt;br /&gt;
lib/maxmind/MaxMind/&lt;br /&gt;
&lt;br /&gt;
PHP API for reading MaxMind DB files&lt;br /&gt;
&lt;br /&gt;
Version: 1.5.1&lt;br /&gt;
&lt;br /&gt;
Copyright MaxMind&lt;br /&gt;
&lt;br /&gt;
License: Apache 2.0&lt;br /&gt;
&lt;br /&gt;
https://github.com/maxmind/MaxMind-DB-Reader-php/&lt;br /&gt;
&lt;br /&gt;
==mimeTeX==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;filter/tex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Compiled C program to convert TeX into GIFs&lt;br /&gt;
&lt;br /&gt;
Version: 1.74&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002-2004   John Forkosh Associates, Inc&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.forkosh.com/mimetex.html&lt;br /&gt;
&lt;br /&gt;
==Mustache.js==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/amd/src/mustache.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
JS library for displaying mustache templates.&lt;br /&gt;
&lt;br /&gt;
Version: 3.0.1&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2009 Chris Wanstrath (Ruby)&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010-2014 Jan Lehnardt (JavaScript)&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010-2015 The mustache.js community&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/janl/mustache.js/releases&lt;br /&gt;
&lt;br /&gt;
==Mustache==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/mustache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PHP library for displaying mustache templates.&lt;br /&gt;
&lt;br /&gt;
Version: 2.12.0&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2010-2016 Justin Hileman&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/bobthecow/mustache.php/releases&lt;br /&gt;
&lt;br /&gt;
==mp3player==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/mp3player&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Flash movie to play streaming MP3s&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005   Andrew Walker&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==overlibmws==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/overlib.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Javascript library to enable DHTML popups, floating windows, events etc&lt;br /&gt;
&lt;br /&gt;
Version: July 2004&lt;br /&gt;
&lt;br /&gt;
Copyright © 2002-2004   Foteos Macrides&lt;br /&gt;
&lt;br /&gt;
Copyright © 1998-2004   Erik Bosrup&lt;br /&gt;
&lt;br /&gt;
License: Artistic Open Source License&lt;br /&gt;
&lt;br /&gt;
http://www.macridesweb.com/oltest/&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PclZip==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pclzip&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to create, manage and unpack zip files.&lt;br /&gt;
&lt;br /&gt;
Version: 2.4 RC1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Vincent Blavet (&#039;&#039;vincent AT phpconcept DOT net&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
License: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://www.phpconcept.net&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PEAR OLE Classes==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to write Excel files&lt;br /&gt;
&lt;br /&gt;
Version: 0.5&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Xavier Noguer&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/OLE&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PEAR Spreadsheet_Excel_Writer==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to write Excel files&lt;br /&gt;
&lt;br /&gt;
Version: 0.9.1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Xavier Noguer and Mika Tuupola&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/Spreadsheet_Excel_Writer&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_Quickform==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to write forms&lt;br /&gt;
&lt;br /&gt;
Version: 3.2.6&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Bertrand Mansion, Adam Daniel, Alexey Borzov&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_Quickform&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_Quickform_Renderer_Tableless==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to render forms without tables&lt;br /&gt;
&lt;br /&gt;
Version: 0.3.4&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005 Mark Wiesemann&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_Quickform_Renderer_Tableless&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_QuickForm_DHTMLRulesTableless==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to render validation notices with dhtml&lt;br /&gt;
&lt;br /&gt;
Version: 0.1.2&lt;br /&gt;
&lt;br /&gt;
Copyright © 2005 Alexey Borzov, Adam Daniel, Bertrand Mansion, Justin Patrin, Mark Wiesemann&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless&lt;br /&gt;
&lt;br /&gt;
==PEAR HTML_Common==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class with many common HTML functions (used by HTML Quickform)&lt;br /&gt;
&lt;br /&gt;
Version: 0.3.4&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004  Adam Daniel, Bertrand Mansion, Klaus Guenther, Alexey Borzov&lt;br /&gt;
&lt;br /&gt;
License: PHP (plus special exemption for Moodle to make it compatible)&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/HTML_Common&lt;br /&gt;
&lt;br /&gt;
==PEAR XML_Parser==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/pear&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class implementing one handy (sax-expat) XML parser&lt;br /&gt;
&lt;br /&gt;
Version: 1.3.2&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004-2008 The PHP Group &amp;amp; Stephan Schmidt&lt;br /&gt;
&lt;br /&gt;
License: New BSD License&lt;br /&gt;
&lt;br /&gt;
http://pear.php.net/package/XML_Parser&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PHP-CSS-Parser==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/php-css-parser&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A Parser for CSS Files written in PHP.&lt;br /&gt;
&lt;br /&gt;
Version: 8.3.0&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2011 Raphael Schweikert, http://sabberworm.com/&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/sabberworm/PHP-CSS-Parser&lt;br /&gt;
&lt;br /&gt;
==PHPExcel==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/phpexcel/PHPExcel.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library to read, write and create spreadsheet documents in PHP.&lt;br /&gt;
&lt;br /&gt;
Version 1.8.1&lt;br /&gt;
&lt;br /&gt;
Copyright © 2006 - 2015 PHPExcel&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
https://github.com/PHPOffice/PHPExcel&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==PhpSpreadsheet==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/phpspreadsheet&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Library to read, write and create spreadsheet documents in PHP.&lt;br /&gt;
&lt;br /&gt;
Version 1.7.0&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
https://github.com/PHPOffice/PhpSpreadsheet&lt;br /&gt;
&lt;br /&gt;
==PHP mailer==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/class.phpmailer.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class for sending email using either sendmail, PHP mail(), or SMTP.  Methods are based upon the standard AspEmail(tm) classes.&lt;br /&gt;
&lt;br /&gt;
Version 6.0.7&lt;br /&gt;
&lt;br /&gt;
Copyright © 2003 Brent R. Matzelle (&#039;&#039;bmatzelle AT yahoo DOT com&#039;&#039;)&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://phpmailer.sourceforge.net&lt;br /&gt;
https://github.com/PHPMailer/PHPMailer/releases&lt;br /&gt;
&lt;br /&gt;
==PHP Markdown==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/markdown.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Functions to convert from the Markdown text format into clean XHTML.&lt;br /&gt;
&lt;br /&gt;
Version: 1.8.0 (with modifications)&lt;br /&gt;
&lt;br /&gt;
 * @copyright 2004-2016 Michel Fortin &amp;lt;https://michelf.com/projects/php-markdown/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 * @copyright (Original Markdown) 2004-2006 John Gruber &amp;lt;https://daringfireball.net/projects/markdown/&amp;gt;&lt;br /&gt;
All rights reserved.&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
http://www.michelf.com/projects/php-markdown/&lt;br /&gt;
&lt;br /&gt;
==PHP-ML==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/mlbackend/php/phpml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Machine learning library used to generate data for the Analytics system.&lt;br /&gt;
&lt;br /&gt;
Version: 0.8.0&lt;br /&gt;
&lt;br /&gt;
 * @copyright 2016-2018 Arkadiusz Kondas &amp;lt;arkadiusz.kondas[at]gmail&amp;gt;&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://php-ml.readthedocs.io/&lt;br /&gt;
&lt;br /&gt;
==Popper.js==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;admin/tool/usertours/amd/src/popper.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
A kickass library used to created Poppers in web applications&lt;br /&gt;
&lt;br /&gt;
Version: 1.12.6&lt;br /&gt;
&lt;br /&gt;
© 2016 Federico Zivolo and contributors&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/FezVrasta/popper.js&lt;br /&gt;
&lt;br /&gt;
==RTLCSS for PHP==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/rtlcss&amp;quot;&lt;br /&gt;
&lt;br /&gt;
RTLCSS is a framework for converting Left-To-Right (LTR) Cascading Style Sheets(CSS) to Right-To-Left (RTL).&lt;br /&gt;
&lt;br /&gt;
© 2016 Frédéric Massart&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
https://github.com/moodlehq/rtlcss-php&lt;br /&gt;
&lt;br /&gt;
==RequireJS==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/lib/requirejs/&#039;&#039;	&lt;br /&gt;
&lt;br /&gt;
RequireJS is a JavaScript file and module loader.&lt;br /&gt;
&lt;br /&gt;
Version 2.3.5&lt;br /&gt;
&lt;br /&gt;
License: new BSD or MIT&lt;br /&gt;
&lt;br /&gt;
http://requirejs.org/&lt;br /&gt;
&lt;br /&gt;
==scssphp==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/lib/scssphp/&#039;&#039;	&lt;br /&gt;
&lt;br /&gt;
scssphp is a compiler for SCSS written in PHP.&lt;br /&gt;
&lt;br /&gt;
Version: 1.0.2&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2015 Leaf Corcoran&lt;br /&gt;
&lt;br /&gt;
License: MIT&lt;br /&gt;
&lt;br /&gt;
http://leafo.github.io/scssphp&lt;br /&gt;
&lt;br /&gt;
==SimplePie==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;/lib/simplepie&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Simple Pie helps with blogs.&lt;br /&gt;
&lt;br /&gt;
Version 1.5.2&lt;br /&gt;
&lt;br /&gt;
License: BSD&lt;br /&gt;
&lt;br /&gt;
https://github.com/simplepie/simplepie&lt;br /&gt;
&lt;br /&gt;
==Snoopy==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/snoopy&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A PHP net client&lt;br /&gt;
&lt;br /&gt;
Version: 1.0&lt;br /&gt;
&lt;br /&gt;
Copyright © 1999-2000 Monte Ohrt (&#039;&#039;monte AT ispi DOT net&#039;&#039;)&lt;br /&gt;
License: GNU LGPL&lt;br /&gt;
&lt;br /&gt;
http://snoopy.sourceforge.com&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==SMTP class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/class.smtp.php&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class that can be used to connect and communicate with any SMTP server. It implements all the SMTP functions defined in RFC821 except TURN.&lt;br /&gt;
&lt;br /&gt;
Version: 03/26/2001&lt;br /&gt;
&lt;br /&gt;
Copyright © 2001  Chris Ryan (&#039;&#039;chris AT greatbridge DOT com&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==Spike PHPCoverage==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/spikephpcoverage&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
PHP code coverage reporting tool&lt;br /&gt;
&lt;br /&gt;
Version: 0.8.2 (with modifications)&lt;br /&gt;
&lt;br /&gt;
Copyright © 2004 SpikeSource Inc&lt;br /&gt;
&lt;br /&gt;
License: LGPL&lt;br /&gt;
&lt;br /&gt;
http://developer.spikesource.com/projects/phpcoverage&lt;br /&gt;
&lt;br /&gt;
(This library is not currently used in Moodle)&lt;br /&gt;
&lt;br /&gt;
==Spout==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;lib/spout&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Library for importing and exporting csv / excel / ODS files.&lt;br /&gt;
&lt;br /&gt;
Version 3.0.1&lt;br /&gt;
&lt;br /&gt;
License: Apache&lt;br /&gt;
&lt;br /&gt;
https://github.com/box/spout/&lt;br /&gt;
&lt;br /&gt;
==TCPDF Class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/tcpdf&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class to generate PDF files&lt;br /&gt;
&lt;br /&gt;
Version: 6.2.26&lt;br /&gt;
&lt;br /&gt;
Copyright Olivier PLATHEY&lt;br /&gt;
&lt;br /&gt;
License: Freeware&lt;br /&gt;
&lt;br /&gt;
http://www.setasign.com/products/fpdi/downloads&lt;br /&gt;
&lt;br /&gt;
==Typo3 Character Set Class==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/typo3&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Class for conversion between charsets and multibyte-savy operations with strings.&lt;br /&gt;
&lt;br /&gt;
Version: 4.7.19&lt;br /&gt;
&lt;br /&gt;
Copyright © 2003-2005 Kasper Skaarhoj&lt;br /&gt;
&lt;br /&gt;
Licence: GNU GPL&lt;br /&gt;
&lt;br /&gt;
http://typo3.org/&lt;br /&gt;
&lt;br /&gt;
==Video.js==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;amd/src/video-lazy.js&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
JavaScript library that makes it easier to work with and build on HTML5 video&lt;br /&gt;
&lt;br /&gt;
Version: 7.7.6&lt;br /&gt;
&lt;br /&gt;
Copyright Brightcove, Inc&lt;br /&gt;
&lt;br /&gt;
Licence: Apache&lt;br /&gt;
&lt;br /&gt;
http://videojs.com/&lt;br /&gt;
&lt;br /&gt;
==XHProf==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/xhprof&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A Hierarchical Profiler for PHP&lt;br /&gt;
&lt;br /&gt;
Version: 0.9.4&lt;br /&gt;
&lt;br /&gt;
Copyright © 2009 Phacility&lt;br /&gt;
&lt;br /&gt;
Licence: Apache&lt;br /&gt;
&lt;br /&gt;
https://github.com/phacility/xhprof&lt;br /&gt;
&lt;br /&gt;
==Yahoo User Interface==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;lib/yui&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Yahoo! User Interface Library is a set of utilities and controls, in JavaScript, for building richly interactive web applications using techniques such as DOM scripting, DHTML and AJAX. The YUI Library also includes several core CSS resources.Set of user-interface components using AJAX, DHTML etc.  We use it for all our AJAX-related stuff.&lt;br /&gt;
&lt;br /&gt;
CVS version: 3.17.2&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2006, Yahoo! Inc.&lt;br /&gt;
&lt;br /&gt;
Licence: BSD&lt;br /&gt;
&lt;br /&gt;
http://developer.yahoo.com/yui/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Credits]]&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=55926</id>
		<title>lib/formslib.php Form Definition</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=55926"/>
		<updated>2019-04-16T04:03:42Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: Spelling mistake&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Formslib}}&lt;br /&gt;
== &#039;&#039;definition()&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
The definition of the elements to be included in the form, their &#039;types&#039; (PARAM_*), helpbuttons included, etc. is all included in a function you must define in your class.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;definition()&#039;&#039; is used to define the elements in the form and &#039;&#039;&#039;this definition will be used for validating data submitted as well as for printing the form.&#039;&#039;&#039; For select and checkbox type elements only data that could have been selected will be allowed. And only data that corresponds to a form element in the definition will be accepted as submitted data.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;definition()&#039;&#039; should include all elements that are going to be used on form, some elements may be removed or tweaked later in &#039;&#039;definition_after_data()&#039;&#039;. Please do not create conditional elements in &#039;&#039;definition()&#039;&#039;, the definition() should not directly depend on the submitted data.&lt;br /&gt;
&lt;br /&gt;
Note that the definition function is called when the form class is instantiated. There is no option to (say) manipulate data in the class (that may affect the rendering of the form) between instantiating the form and calling any other methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&amp;quot;$CFG-&amp;gt;libdir/formslib.php&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
class simplehtml_form extends moodleform {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG;&lt;br /&gt;
       &lt;br /&gt;
        $mform = $this-&amp;gt;_form; // Don&#039;t forget the underscore! &lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement()... // Add elements to your form&lt;br /&gt;
            ...&lt;br /&gt;
    }                           // Close the function&lt;br /&gt;
}                               // Close the class&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
===Passing parameters to the Form===&lt;br /&gt;
&lt;br /&gt;
The constructor for &#039;&#039;moodleform&#039;&#039; allows a number of parameters including one (&#039;&#039;$customdata&#039;&#039;) to permit an array of arbitrary data to be passed to your form. &lt;br /&gt;
&lt;br /&gt;
For example, you can pass the data &amp;quot;$email&amp;quot; and &amp;quot;$username&amp;quot; to the Form&#039;s class for use inside (say) the definition.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
 $mform_simple = new simplehtml_form( null, array(&#039;email&#039;=&amp;gt;$email, &#039;username&#039;=&amp;gt;$username ) );&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
(the first parameter is $action, &#039;&#039;null&#039;&#039; will cause the form action to be determined automatically)&lt;br /&gt;
&lt;br /&gt;
Secondly, inside the form definition you can use those parameters to set the default values to some of the form&#039;s fields&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
 $mform-&amp;gt;addElement(&#039;text&#039;, &#039;email&#039;, get_string(&#039;email&#039;), &#039;maxlength=&amp;quot;100&amp;quot; size=&amp;quot;25&amp;quot; &#039;);&lt;br /&gt;
 $mform-&amp;gt;setType(&#039;email&#039;, PARAM_NOTAGS);&lt;br /&gt;
 $mform-&amp;gt;addRule(&#039;email&#039;, get_string(&#039;missingemail&#039;), &#039;required&#039;, null, &#039;server&#039;);&lt;br /&gt;
 // Set default value by using a passed parameter&lt;br /&gt;
 $mform-&amp;gt;setDefault(&#039;email&#039;,$this-&amp;gt;_customdata[&#039;email&#039;]);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Use Fieldsets to group Form Elements==&lt;br /&gt;
&lt;br /&gt;
You use code like this to open a fieldset with a &#039;&#039;legend&#039;&#039;. &amp;lt;br /&amp;gt;&lt;br /&gt;
(&#039;&#039;&#039;Note&#039;&#039;&#039;: Some themes turn off legends on admin setting pages by using CSS: &amp;lt;nowiki&amp;gt;#adminsettings legend {display:none;}&amp;lt;/nowiki&amp;gt;.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;header&#039;, &#039;nameforyourheaderelement&#039;, get_string(&#039;titleforlegened&#039;, &#039;modulename&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can&#039;t yet nest these visible fieldsets unfortunately. But in fact groups of elements are wrapped in invisible fieldsets.&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.5}}&lt;br /&gt;
Since Moodle 2.5 fieldsets without any required fields are collapsed by default. To display these fieldsets on page load, use:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $mform-&amp;gt;setExpanded(&#039;foo&#039;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You close a fieldset with moodle_form&#039;s closeHeaderBefore method. You tell closeHeaderBefore the element before you wish to end the fieldset. A fieldset is automatically closed if you open a new one. You need to use this code only if you want to close a fieldset and the subsequent form elements are not to be enclosed by a visible fieldset (they are still enclosed with an invisibe one with no legend) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==addElement==&lt;br /&gt;
&lt;br /&gt;
Use the addElement method to add an element to a form. The first few arguments are always the same. The first param is the type of the element to add. The second is the elementname to use which is normally the html name of the element in the form. The third is often the text for the label for the element.&lt;br /&gt;
&lt;br /&gt;
Some examples are below :&lt;br /&gt;
=== button ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;button&#039;, &#039;intro&#039;, get_string(&amp;quot;buttonlabel&amp;quot;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A button element. If you want a submit or cancel button see &#039;submit&#039; element.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== autocomplete ===&lt;br /&gt;
{{Moodle 3.1}}&lt;br /&gt;
Available since Moodle 3.1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$searchareas = \core_search\manager::get_search_areas_list(true);                                                           &lt;br /&gt;
$areanames = array();                                                                                                       &lt;br /&gt;
foreach ($searchareas as $areaid =&amp;gt; $searcharea) {                                                                          &lt;br /&gt;
    $areanames[$areaid] = $searcharea-&amp;gt;get_visible_name();                                                                  &lt;br /&gt;
}                                                                                                                           &lt;br /&gt;
$options = array(                                                                                                           &lt;br /&gt;
    &#039;multiple&#039; =&amp;gt; true,                                                                                                     &lt;br /&gt;
    &#039;noselectionstring&#039; =&amp;gt; get_string(&#039;allareas&#039;, &#039;search&#039;),                                                                &lt;br /&gt;
);         &lt;br /&gt;
$mform-&amp;gt;addElement(&#039;autocomplete&#039;, &#039;areaids&#039;, get_string(&#039;searcharea&#039;, &#039;search&#039;), $areanames, $options);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The autocomplete element is an advanced form element that supports server-side searching - or simple filtering of a predefined list of options. Some benefits of using this form element are that it handles very large datasets extremely well - it has great accessibility built in - and it gives a good user experience. If you have so much data you need to build pagination into a page - you could probably come up with a better design using this. The simplest way to use it is compatible with the standard &#039;select&#039; form element. You give it a list of options and some parameters to configure how it behaves. The valid parameters for this simple mode of operation are:&lt;br /&gt;
* multiple (boolean - default false) - Allow more than one selected item. The data coming from the form will be an array in this case.&lt;br /&gt;
* noselectionstring (string - default &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;) - The text to display when nothing is selected.&lt;br /&gt;
* showsuggestions (boolean - default true) - Do not show the list of suggestions when the user starts typing.&lt;br /&gt;
* placeholder (string - default &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;) - The text to show in the search box when it is empty.&lt;br /&gt;
* casesensitive (boolean - default false) - Is the search case sensitive ?&lt;br /&gt;
* tags (boolean - default false) - This changes the behaviour so that the user can create new valid entries in the list by typing them and pressing enter.&lt;br /&gt;
* ajax (string - default &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;) - This string is the name of an AMD module that can fetch and format results.&lt;br /&gt;
&lt;br /&gt;
More explanation on the &#039;ajax&#039; option. This should be the name of an AMD module that implements 2 functions:&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
/**                                                                                                                         &lt;br /&gt;
 * Source of data for Ajax element.                                                                                         &lt;br /&gt;
 *                                                                                                                          &lt;br /&gt;
 * @param {String} selector The selector of the auto complete element.                                                      &lt;br /&gt;
 * @param {String} query The query string.                                                                                  &lt;br /&gt;
 * @param {Function} callback A callback function receiving an array of results.                                            &lt;br /&gt;
 * @return {Void}                                                                                                           &lt;br /&gt;
*/                                                                                                                         &lt;br /&gt;
transport: function(selector, query, callback) ...&lt;br /&gt;
&lt;br /&gt;
/**                                                                                                                         &lt;br /&gt;
 * Process the results for auto complete elements.                                                                          &lt;br /&gt;
 *                                                                                                                          &lt;br /&gt;
 * @param {String} selector The selector of the auto complete element.                                                      &lt;br /&gt;
 * @param {Array} results An array or results.                                                                              &lt;br /&gt;
 * @return {Array} New array of results.                                                                                    &lt;br /&gt;
 */                                                                                                                         &lt;br /&gt;
processResults: function(selector, results)...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A good example is here: [https://github.com/moodle/moodle/blob/MOODLE_31_STABLE/admin/tool/lp/amd/src/frameworks_datasource.js admin/tool/lp/amd/src/frameworks_datasource.js]&lt;br /&gt;
&lt;br /&gt;
When using the ajax option in an mform with validation etc - it is recommended to sub-class the php class &amp;quot;MoodleQuickForm_autocomplete&amp;quot; so that you can provide a list of name and&lt;br /&gt;
values to populate the form element if the form is re-displayed due to a validation error. An example is [https://github.com/moodle/moodle/blob/MOODLE_31_STABLE/admin/tool/lp/classes/form/framework_autocomplete.php admin/tool/lp/classes/form/framework_autocomplete.php].&lt;br /&gt;
&lt;br /&gt;
We have provided several useful subclasses of this form element already that are simple to use (course and tags).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
    // Course example.&lt;br /&gt;
    //  Valid options are:                                                                                     &lt;br /&gt;
    //                       &#039;multiple&#039; - boolean multi select                                                                      &lt;br /&gt;
    //                       &#039;exclude&#039; - array or int, list of course ids to never show                                             &lt;br /&gt;
    //                       &#039;requiredcapabilities&#039; - array of capabilities. Uses ANY to combine them.                              &lt;br /&gt;
    //                       &#039;limittoenrolled&#039; - boolean Limits to enrolled courses.                                                &lt;br /&gt;
    //                       &#039;includefrontpage&#039; - boolean Enables the frontpage to be selected.  &lt;br /&gt;
    $options = array(&#039;multiple&#039; =&amp;gt; true, &#039;includefrontpage&#039; =&amp;gt; true);                                                           &lt;br /&gt;
    $mform-&amp;gt;addElement(&#039;course&#039;, &#039;mappedcourses&#039;, get_string(&#039;courses&#039;), $options); &lt;br /&gt;
&lt;br /&gt;
    // Tags&lt;br /&gt;
    //  Valid options are:                                                                                     &lt;br /&gt;
    //                       &#039;showstandard&#039; - boolean One of the core_tag_tag constants to say which tags to display&lt;br /&gt;
    //                       &#039;component&#039; - string The component name and itemtype define the tag area&lt;br /&gt;
    //                       &#039;itemtype&#039; - string The component name and itemtype define the tag area&lt;br /&gt;
    $mform-&amp;gt;addElement(&#039;tags&#039;, &#039;interests&#039;, get_string(&#039;interestslist&#039;), array(&#039;itemtype&#039; =&amp;gt; &#039;user&#039;, &#039;component&#039; =&amp;gt; &#039;core&#039;));     &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== checkbox ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;checkbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a simple checkbox. The third parameter for this element is the label to display on the left side of the form. You can also supply a string as a fourth parameter to specify a label that will appear on the right of the element. Checkboxes and radio buttons can be grouped and have individual labels on their right.&lt;br /&gt;
&lt;br /&gt;
You can have a 5th parameter $attributes, as on other elements.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BEWARE:&#039;&#039;&#039; Unchecked checkboxes return nothing at all (as if they didn&#039;t exist). This can surprise the unwary. You may wish to use advcheckbox instead, which does return a value when not checked. &#039;Advcheckbox&#039; eliminates this problem. &lt;br /&gt;
&lt;br /&gt;
==== advcheckbox ====&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;advcheckbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;), &#039;Label displayed after checkbox&#039;, array(&#039;group&#039; =&amp;gt; 1), array(0, 1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similar to the checkbox above, but with some important improvements:&lt;br /&gt;
&lt;br /&gt;
# The (optional) 5th parameter is a normal $attributes array, normally used to set HTML attributes for the &amp;lt;input&amp;gt; element. However, a special value of &#039;group&#039; can be given, which will add a class name to the element, and enable its grouping for a [[lib/formslib.php_add_checkbox_controller|checkbox controller]]&lt;br /&gt;
#The (optional) 6th parameter is an array of values that will be associated with the checked/unchecked state of the checkbox. With a normal checkbox you cannot choose that value, and in fact an unchecked checkbox will not even be sent with the form data.&lt;br /&gt;
#It returns a 0 value when unchecked. Compare with the ordinary checkbox which does not return anything at all.&lt;br /&gt;
&lt;br /&gt;
=== choosecoursefile ===&lt;br /&gt;
{{Moodle 1.9}}&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;choosecoursefile&#039;, &#039;mediafile&#039;, get_string(&#039;mediafile&#039;, &#039;lesson&#039;), array(&#039;courseid&#039;=&amp;gt;$COURSE-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Choose a file from the course files area. The fourth option is a list of options for the element. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: This has been superceded by [[#filepicker|filepicker]] in Moodle 2.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
array(&#039;courseid&#039; =&amp;gt;null,  //if it is null (default then use global $COURSE&lt;br /&gt;
      &#039;height&#039;   =&amp;gt;500,   // height of the popup window&lt;br /&gt;
      &#039;width&#039;    =&amp;gt;750,   // width of the popup window&lt;br /&gt;
      &#039;options&#039;  =&amp;gt;&#039;none&#039;); //options string for the pop up window &lt;br /&gt;
                          //eg. &#039;menubar=0,location=0,scrollbars,resizable&#039;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also pass an optional 5th parameter of attributes, as for other elements. The most useful way of using that is something like &lt;br /&gt;
&amp;lt;code php&amp;gt;array(&#039;maxlength&#039; =&amp;gt; 255, &#039;size&#039; =&amp;gt; 48)&amp;lt;/code&amp;gt;&lt;br /&gt;
to control the maxlength / size of the text box (note size will default to 48 if not specified)&lt;br /&gt;
&lt;br /&gt;
Finally, as this element is a group containing two elements (button + value), you can add validation rules by using the &#039;&#039;&#039;addGroupRule()&#039;&#039;&#039; method in this (complex) way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;$mform-&amp;gt;addGroupRule(&#039;elementname&#039;, array(&#039;value&#039; =&amp;gt; array(array(list, of, rule, params, but, fieldname))));&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where: &#039;&#039;&#039;&amp;quot;elementname&amp;quot;&#039;&#039;&#039; is the name of the choosecoursefile group element, &#039;&#039;&#039;&amp;quot;value&amp;quot;&#039;&#039;&#039; is the name of the text field within the group and the &#039;&#039;&#039;&amp;quot;list, of, addrule, params, but, fieldname&amp;quot;&#039;&#039;&#039; is exactly that, the list of fields in the normal addRule() function but ommiting the first one, the fieldname.&lt;br /&gt;
&lt;br /&gt;
For example, the [http://cvs.moodle.org/moodle/mod/resource/type/file/resource.class.php?view=markup file/url resource type], uses one &amp;quot;choosecoursefile&amp;quot; element, and it controls the maximum length of the field (255) with this use of addGroupRule():&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;$mform-&amp;gt;addGroupRule(&#039;reference&#039;, array(&#039;value&#039; =&amp;gt; array(array(get_string(&#039;maximumchars&#039;, &#039;&#039;, 255), &#039;maxlength&#039;, 255, &#039;client&#039;))));&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== date_selector ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;date_selector&#039;, &#039;assesstimefinish&#039;, get_string(&#039;to&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a date selector. You can select a Day, Month and Year using a group of select boxes. The fourth param here is an array of options. The defaults for the options are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
array(&lt;br /&gt;
    &#039;startyear&#039; =&amp;gt; 1970, &lt;br /&gt;
    &#039;stopyear&#039;  =&amp;gt; 2020,&lt;br /&gt;
    &#039;timezone&#039;  =&amp;gt; 99,&lt;br /&gt;
    &#039;optional&#039;  =&amp;gt; false&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
=== date_time_selector ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;date_time_selector&#039;, &#039;assesstimestart&#039;, get_string(&#039;from&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a group of select boxes to select a date (Day Month and Year) and time (Hour and Minute). When submitted, submitted data is processed and a timestamp is passed to $form-&amp;gt;get_data(); the fourth param here is an array of options. The defaults for the options are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
array(&lt;br /&gt;
    &#039;startyear&#039; =&amp;gt; 1970, &lt;br /&gt;
    &#039;stopyear&#039;  =&amp;gt; 2020,&lt;br /&gt;
    &#039;timezone&#039;  =&amp;gt; 99,&lt;br /&gt;
    &#039;step&#039;      =&amp;gt; 5&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===duration===&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;duration&#039;, &#039;timelimit&#039;, get_string(&#039;timelimit&#039;, &#039;quiz&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This field type lets the user input an interval of time. It comprises a text field, where you can type a number, and a dropdown for selecting a unit (days, hours, minutes or seconds). When submitted the value is converted to a number of seconds.&lt;br /&gt;
&lt;br /&gt;
You can add a fourth parameter to give options. At the moment the only option supported is here is an array of options. The defaults for the options is:&lt;br /&gt;
&amp;lt;code php&amp;gt;array(&#039;optional&#039; =&amp;gt; true)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also pass an optional 5th parameter of attributes, as for other elements. The most useful way of using that is something like &lt;br /&gt;
&amp;lt;code php&amp;gt;array(&#039;size&#039; =&amp;gt; 5)&amp;lt;/code&amp;gt;&lt;br /&gt;
to control the size of the text box.&lt;br /&gt;
&lt;br /&gt;
=== editor ===&lt;br /&gt;
&lt;br /&gt;
This replaces the old htmleditor field type. It allows the user to enter rich text content in a variety of formats.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;editor&#039;, &#039;fieldname&#039;, get_string(&#039;labeltext&#039;, &#039;langfile&#039;));&lt;br /&gt;
$mform-&amp;gt;setType(&#039;fieldname&#039;, PARAM_RAW);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTE: It won&#039;t work properly without the setType() as shown.&lt;br /&gt;
&lt;br /&gt;
If you would like to let the user use the filepicker to upload images etc. that are used in the content, then see [[Using_the_File_API_in_Moodle_forms]].&lt;br /&gt;
&lt;br /&gt;
You can supply a fourth param to htmleditor of an array of options that are mostly related to file handling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
array(&lt;br /&gt;
    &#039;subdirs&#039;=&amp;gt;0,&lt;br /&gt;
    &#039;maxbytes&#039;=&amp;gt;0,&lt;br /&gt;
    &#039;maxfiles&#039;=&amp;gt;0,&lt;br /&gt;
    &#039;changeformat&#039;=&amp;gt;0,&lt;br /&gt;
    &#039;context&#039;=&amp;gt;null,&lt;br /&gt;
    &#039;noclean&#039;=&amp;gt;0,&lt;br /&gt;
    &#039;trusttext&#039;=&amp;gt;0,&lt;br /&gt;
    &#039;enable_filemanagement&#039; =&amp;gt; true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The option &#039;enable_filemanagement&#039; will display the file management button on true and remove it on false.&lt;br /&gt;
&lt;br /&gt;
To save the data if you don&#039;t care about files:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$formdata = $mform-&amp;gt;get_data();&lt;br /&gt;
$text     = $formdata-&amp;gt;fieldname[&#039;text&#039;];&lt;br /&gt;
$format   = $formdata-&amp;gt;fieldname[&#039;format&#039;];&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Because the text editor might be &amp;quot;Atto&amp;quot; (depending on user preferences) and Atto has an &amp;quot;autosave&amp;quot; feature - it requires that the combination of $PAGE-&amp;gt;url and this elementid are unique. If not, the autosaved text for a different form may be restored into this form.&lt;br /&gt;
&lt;br /&gt;
=== file ===&lt;br /&gt;
&lt;br /&gt;
File upload input box with browse button. In the form definition type&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
after form submission and validation use&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
      ...&lt;br /&gt;
    $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
      ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If there is no requirement to save the file, you can read the file contents directly into a string as follows...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $mform-&amp;gt;get_file_content(&#039;attachment&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need advanced settings such as required file, different max upload size or name of uploaded file&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;set_upload_manager(new upload_manager(&#039;attachment&#039;, true, false, $COURSE, false, 0, true, true, false));&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
            $mform-&amp;gt;addRule(&#039;attachment&#039;, null, &#039;required&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
      ...&lt;br /&gt;
    $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
    $newfilename = $mform-&amp;gt;get_new_filename();&lt;br /&gt;
      ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When porting old code it is also possible to use the upload manager directly for processing of uploaded files.&lt;br /&gt;
&lt;br /&gt;
Please note that if using set_upload_manager() it must be before addElement(&#039;file&#039;,..).&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
File uploading was rewritten in 2.0. Please see inline docs for now. This page will be updated when the new API stabilises.&lt;br /&gt;
&lt;br /&gt;
===filepicker===&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
General replacement of &#039;&#039;file&#039;&#039; element.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;filepicker&#039;, &#039;userfile&#039;, get_string(&#039;file&#039;), null, array(&#039;maxbytes&#039; =&amp;gt; $maxbytes, &#039;accepted_types&#039; =&amp;gt; &#039;*&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See also [[Using the File API in Moodle forms]]&lt;br /&gt;
&lt;br /&gt;
=== hidden ===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;hidden&#039;, &#039;reply&#039;, &#039;yes&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A hidden element. Set the element name (in this case &#039;&#039;&#039;reply&#039;&#039;&#039;) to the stated value (in this case &#039;&#039;&#039;yes&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== html ===&lt;br /&gt;
You can add arbitrary HTML to your Moodle form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;html&#039;, &#039;&amp;lt;div class=&amp;quot;qheader&amp;quot;&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [http://moodle.org/mod/forum/discuss.php?d=126935 &amp;quot;Question: Can I put a moodleform inside a table td?&amp;quot;] for a concrete example.&lt;br /&gt;
&lt;br /&gt;
=== htmleditor &amp;amp; format ===&lt;br /&gt;
&lt;br /&gt;
These elements are now deprecated. Please use the [[#editor|editor]] field type instead.&lt;br /&gt;
&lt;br /&gt;
===modgrade===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;modgrade&#039;, &#039;scale&#039;, get_string(&#039;grade&#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a custom element for selecting a grade for any activity module. The fourth argument is whether to include an option for no grade which has a value 0. This select box does include scales. The default is true, include no grade option.&lt;br /&gt;
&lt;br /&gt;
A helpbutton is automatically added.&lt;br /&gt;
&lt;br /&gt;
===modvisible===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;modvisible&#039;, &#039;visible&#039;, get_string(&#039;visible&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a custom element for selecting a grade visibility in an activity mod update form.&lt;br /&gt;
&lt;br /&gt;
===password===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;password&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===passwordunmask===&lt;br /&gt;
{{Moodle 1.9}}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;passwordunmask&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element with option to show the password in plaintext. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
=== radio ===&lt;br /&gt;
{{Moodle 2.3}}&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$radioarray=array();&lt;br /&gt;
$radioarray[] = $mform-&amp;gt;createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;yes&#039;), 1, $attributes);&lt;br /&gt;
$radioarray[] = $mform-&amp;gt;createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;no&#039;), 0, $attributes);&lt;br /&gt;
$mform-&amp;gt;addGroup($radioarray, &#039;radioar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second param names the radio button and should be the same for each button in the group in order to toggle correctly. Third param would be the label for the form element but is generally ignored as this element will always be in a group which has it&#039;s own label. Fourth param is a string, a label to be displayed on the right of the element. The fifth is the value for this radio button. $attributes can be a string or an array of attributes.&lt;br /&gt;
&lt;br /&gt;
It is possible to add help to individual radio buttons but this requires a custom template to be defined for the group elements. See MDL-15571.&lt;br /&gt;
&lt;br /&gt;
Since 2.3 it cannot be statically called anymore, so we need to call createElement from $mform reference.&lt;br /&gt;
&lt;br /&gt;
==== setDefault ====&lt;br /&gt;
&lt;br /&gt;
To set the default for a radio button group as above use the following :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;setDefault(&#039;yesno&#039;, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This would make the default &#039;no&#039;.&lt;br /&gt;
&lt;br /&gt;
===select===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;select&#039;, &#039;type&#039;, get_string(&#039;forumtype&#039;, &#039;forum&#039;), $FORUM_TYPES, $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fourth param for this element is an array of options for the select box. The keys are the values for the option and the value of the array is the text for the option. The fifth param $attributes is optional, see text element for description of attributes param.&lt;br /&gt;
&lt;br /&gt;
It is also possible to create a select with certain options disabled, using [http://stackoverflow.com/questions/2138089/how-can-i-use-quickform-to-add-disabled-select-options/2150275#2150275 this technique].&lt;br /&gt;
&lt;br /&gt;
You can set an &#039;onchange&#039; attribute when adding or creating the select element: &lt;br /&gt;
&lt;br /&gt;
$form-&amp;gt;addElement(&#039;select&#039;, &#039;iselTest&#039;, &#039;Test Select:&#039;, $arrayOfOptions, array(&#039;onchange&#039; =&amp;gt; &#039;javascript:myFunctionToDoSomething();&#039;));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====multi-select====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$select = $mform-&amp;gt;addElement(&#039;select&#039;, &#039;colors&#039;, get_string(&#039;colors&#039;), array(&#039;red&#039;, &#039;blue&#039;, &#039;green&#039;), $attributes);&lt;br /&gt;
$select-&amp;gt;setMultiple(true);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====setSelected=====&lt;br /&gt;
&lt;br /&gt;
To set the default selected item in a select element, you can use the &#039;setSelected&#039; method. The &#039;setSelected&#039; can either get a value or an array of values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$options = array(&lt;br /&gt;
    &#039;ff0000&#039; =&amp;gt; &#039;Red&#039;,&lt;br /&gt;
    &#039;00ff00&#039; =&amp;gt; &#039;Green&#039;,&lt;br /&gt;
    &#039;0000ff&#039; =&amp;gt; &#039;Blue&#039;&lt;br /&gt;
);&lt;br /&gt;
$select = $mform-&amp;gt;addElement(&#039;select&#039;, &#039;colors&#039;, get_string(&#039;colors&#039;), $options);&lt;br /&gt;
// This will select the colour blue.&lt;br /&gt;
$select-&amp;gt;setSelected(&#039;0000ff&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or for multiple-selection:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$skillsarray = array(&lt;br /&gt;
    &#039;val1&#039; =&amp;gt; &#039;Skill A&#039;,&lt;br /&gt;
    &#039;val2&#039; =&amp;gt; &#039;Skill B&#039;,&lt;br /&gt;
    &#039;val3&#039; =&amp;gt; &#039;Skill C&#039;&lt;br /&gt;
);&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;select&#039;, &#039;md_skills&#039;, get_string(&#039;skills&#039;, &#039;metadata&#039;), $skillsarray);&lt;br /&gt;
$mform-&amp;gt;getElement(&#039;md_skills&#039;)-&amp;gt;setMultiple(true);&lt;br /&gt;
// This will select the skills A and B.&lt;br /&gt;
$mform-&amp;gt;getElement(&#039;md_skills&#039;)-&amp;gt;setSelected(array(&#039;val1&#039;, &#039;val2&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However you probably don&#039;t want to do this. Instead you probably want to use setDefault, or set it using the form&#039;s setData method.&lt;br /&gt;
&lt;br /&gt;
===selectyesno===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;selectyesno&#039;, &#039;maxbytes&#039;, get_string(&#039;maxattachmentsize&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want a yes / no select box this one automatically translates itself and has value 1 for yes and 0 for no.&lt;br /&gt;
&lt;br /&gt;
===selectwithlink===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$options = array();&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;selectwithlink&#039;, &#039;scaleid&#039;, get_string(&#039;scale&#039;), $options, null, &lt;br /&gt;
    array(&#039;link&#039; =&amp;gt; $CFG-&amp;gt;wwwroot.&#039;/grade/edit/scale/edit.php?courseid=&#039;.$COURSE-&amp;gt;id, &#039;label&#039; =&amp;gt; get_string(&#039;scalescustomcreate&#039;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
select type element with options containing link&lt;br /&gt;
===static===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;static&#039;, &#039;description&#039;, get_string(&#039;description&#039;, &#039;exercise&#039;),&lt;br /&gt;
    get_string(&#039;descriptionofexercise&#039;, &#039;exercise&#039;, $COURSE-&amp;gt;students));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a static element. It should be used with care if it is used to display a static piece of text with a label. The third param is the label and the fourth is the static text itself.&lt;br /&gt;
&lt;br /&gt;
===submit, reset and cancel===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//normally you use add_action_buttons instead of this code&lt;br /&gt;
$buttonarray=array();&lt;br /&gt;
$buttonarray[] = $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
$buttonarray[] = $mform-&amp;gt;createElement(&#039;reset&#039;, &#039;resetbutton&#039;, get_string(&#039;revert&#039;));&lt;br /&gt;
$buttonarray[] = $mform-&amp;gt;createElement(&#039;cancel&#039;);&lt;br /&gt;
$mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, &#039; &#039;, false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &#039;Submit&#039; type element is a submit type form element which will submit the form. A &#039;Reset&#039; will not submit the form but will reset any changes the user has made to form contents. A &#039;Cancel&#039; element cancels form submission. You need to have a branch in your code before you check for get_data() to check if submission has been cancelled with is_cancelled(); See the example on the usage page.&lt;br /&gt;
&lt;br /&gt;
You should name your submit and reset buttons &#039;submitbutton&#039; and &#039;resetbutton&#039; or something similar (not &#039;submit&#039; and &#039;reset&#039;). This avoids problems in JavaScript of collisions between form element names and names of JavaScript methods of the form object.&lt;br /&gt;
&lt;br /&gt;
====add_action_buttons($cancel = true, $submitlabel=null);====&lt;br /&gt;
&lt;br /&gt;
You will normally use this helper function which is a method of moodleform to add all the &#039;action&#039; buttons to the end of your form. A boolean parameter allow you to specify whether to include a cancel button and specify the label for your submit button (pass the result of get_string). Default for the submit button label is get_string(&#039;savechanges&#039;). Note the &#039;&#039;&#039;$this&#039;&#039;&#039; not &#039;&#039;&#039;$mform&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;add_action_buttons();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===text===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;forumname&#039;, &#039;forum&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
For a simple text input element. (For text labels, use the &#039;static&#039; element.)  Your fourth parameter here can be a string or array of attributes for the text element. The following are equivalent :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$attributes=&#039;size=&amp;quot;20&amp;quot;&#039;;&lt;br /&gt;
$attributes=array(&#039;size&#039;=&amp;gt;&#039;20&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Generally you are encouraged to use CSS instead of using attributes for styling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A format element can be used as a format select box. It will be non-selectable if you&#039;re using an html editor.&lt;br /&gt;
&lt;br /&gt;
The third param for this element is $useHtmlEditor and it defaults to null in which case an html editor is used if the browser and user profile support it.&lt;br /&gt;
&lt;br /&gt;
===textarea===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;textarea&#039;, &#039;introduction&#039;, get_string(&amp;quot;introtext&amp;quot;, &amp;quot;survey&amp;quot;), &#039;wrap=&amp;quot;virtual&amp;quot; rows=&amp;quot;20&amp;quot; cols=&amp;quot;50&amp;quot;&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A textarea element. If you want an htmleditor use htmleditor element. Fourth element here is a string or array of attributes.&lt;br /&gt;
&lt;br /&gt;
===recaptcha===&lt;br /&gt;
{{Moodle 1.9}}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;recaptcha&#039;, &#039;recaptcha_field_name&#039;, $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use this recaptcha element to reduce the spam risk in your forms. Third element here is a string or array of attributes. Take care to get an API key from http://recaptcha.net/api/getkey before using this element.&lt;br /&gt;
&lt;br /&gt;
To check whether recaptcha is enabled at site level use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (!empty($CFG-&amp;gt;recaptchapublickey) &amp;amp;&amp;amp; !empty($CFG-&amp;gt;recaptchaprivatekey)) {&lt;br /&gt;
    //recaptcha is enabled&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===tags===&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;tags&#039;, &#039;field_name&#039;, $lable, $options, $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Used for editing a list of tags, for example on a blog post.&lt;br /&gt;
&lt;br /&gt;
There is only one option available, &#039;display&#039;, which should be set to one of the contstants MoodleQuickForm_tags::ONLYOFFICIAL, NOOFFICIAL or DEFAULTUI. This controls whether the official tags are listed for easy selection, or a text area where arbitrary tags may be typed, or both. The default is both.&lt;br /&gt;
&lt;br /&gt;
The value should be set/returned as an array of tags.&lt;br /&gt;
&lt;br /&gt;
===grading===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;grading&#039;, &#039;advancedgrading&#039;, get_string(&#039;grade&#039;).&#039;:&#039;, array(&#039;gradinginstance&#039; =&amp;gt; $gradinginstance));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Custom element for advanced grading plugins.&lt;br /&gt;
&lt;br /&gt;
When adding the &#039;grading&#039; element to the form, developer must pass an object of class gradingform_instance as $attributes[&#039;gradinginstance&#039;]. Otherwise an exception will be thrown.&lt;br /&gt;
&lt;br /&gt;
===questioncategory===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;questioncategory&#039;, &#039;category&#039;, get_string(&#039;category&#039;, &#039;question&#039;),&lt;br /&gt;
    array(&#039;contexts&#039;=&amp;gt;$contexts, &#039;top&#039;=&amp;gt;true, &#039;currentcat&#039;=&amp;gt;$currentcat, &#039;nochildrenof&#039;=&amp;gt;$currentcat));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Creates a drop down element to select a question category.&lt;br /&gt;
&lt;br /&gt;
Options are:&lt;br /&gt;
&#039;&#039;&#039;contexts&#039;&#039;&#039; - (required) context in which question appears&lt;br /&gt;
&#039;&#039;&#039;currentcat&#039;&#039;&#039; - (optional) course category&lt;br /&gt;
&#039;&#039;&#039;top&#039;&#039;&#039; - (optional) if true will put top categories on top&lt;br /&gt;
&#039;&#039;&#039;nochildrenof&#039;&#039;&#039; - (optional) Format categories into an indented list reflecting the tree structure&lt;br /&gt;
&lt;br /&gt;
=== filetypes ===&lt;br /&gt;
{{Moodle 3.4}}&lt;br /&gt;
Available since Moodle 3.4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;filetypes&#039;, &#039;allowedfiletypes&#039;, get_string(&#039;allowedfiletypes&#039;, &#039;tool_myplugin&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Creates  an input element allowing the user to specify file types for the given purpose. The typical scenario is a setting that allows the teacher define a list of allowed file types submitted by students.&lt;br /&gt;
&lt;br /&gt;
The element allows the user to either type the list of filetypes manually, or select the types from the list. Also supported is selecting the whole group of file types - such as &amp;quot;image&amp;quot;. The element integrates with the [[Core filetypes]] system so all default types and groups are presented, as well as those [[:en:Working with files#Site administration settings|defined locally by the admin]].&lt;br /&gt;
&lt;br /&gt;
As the list can be types in manually, the form processing code should always normalize it first via the provided utility methods:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$formdata = $mform-&amp;gt;get_data();&lt;br /&gt;
$filetypesutil = new \core_form\filetypes_util();&lt;br /&gt;
$allowedfiletypes = $filetypesutil-&amp;gt;normalize_file_types($formdata-&amp;gt;allowedfiletypes);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This always returns an array of recognized valid values. The original list can be separated by whitespace, end of lines, commas, colons and semicolons. During the normalization, values are converted to lowercase, empty valies and duplicates are removed. Glob evaluation is not supported.&lt;br /&gt;
&lt;br /&gt;
The normalization should also happen if the previously defined list had been saved to the database and re-read for actual usage. The normalization output value can be directly used as the accepted_types option for the filepicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$filetypesutil = new \core_form\filetypes_util();&lt;br /&gt;
$options[&#039;accepted_types&#039;] = $filetypesutil-&amp;gt;normalize_file_types($allowedfiletypes);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, user input is validated against the list of known file types and groups. This validation can be disabled via options.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Supported options&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
; onlytypes : Allow selection from these file types only; for example [&#039;onlytypes&#039; =&amp;gt; [&#039;web_image&#039;]].&lt;br /&gt;
; allowall : Allow to select &#039;All file types&#039;, defaults to true. Does not apply with onlytypes are set.&lt;br /&gt;
; allowunknown : Skip implicit validation against the list of known file types.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;filetypes&#039;, &#039;doctypes&#039;, get_string(&#039;doctypes&#039;, &#039;tool_myplugin&#039;), [&#039;onlytypes&#039; =&amp;gt; [&#039;document&#039;], &#039;allowunknown&#039; =&amp;gt; true]);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==addGroup==&lt;br /&gt;
&lt;br /&gt;
A &#039;group&#039; in formslib is just a group of elements that will have a label and will be included on one line. &lt;br /&gt;
&lt;br /&gt;
For example typical code to include a submit and cancel button on the same line : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$buttonarray=array();&lt;br /&gt;
$buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
$buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;cancel&#039;, get_string(&#039;cancel&#039;));&lt;br /&gt;
$mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You use the same arguments for createElement as you do for addElement. Any label for the element in the third argument is normally ignored (but not in the case of the submit buttons above where the third argument is not for a label but is the text for the button).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a bad example (don&#039;t do this for real, use the &#039;optional&#039; =&amp;gt; true option of the date element): putting a date_selector (which is itself a group of elements) and a checkbox on the same line, note that you can disable every element in the group using the group name &#039;availablefromgroup&#039; but it doesn&#039;t disable the controlling element the &#039;availablefromenabled&#039; checkbox:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$availablefromgroup=array();&lt;br /&gt;
$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;date_selector&#039;, &#039;availablefrom&#039;, &#039;&#039;);&lt;br /&gt;
$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;checkbox&#039;, &#039;availablefromenabled&#039;, &#039;&#039;, get_string(&#039;enable&#039;));&lt;br /&gt;
$mform-&amp;gt;addGroup($availablefromgroup, &#039;availablefromgroup&#039;, get_string(&#039;availablefromdate&#039;, &#039;data&#039;), &#039;&amp;amp;nbsp;&#039;, false);&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;availablefromgroup&#039;, &#039;availablefromenabled&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* If you want to put a group inside another array so that you can repeat items, use createElement instead of addGroup:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$group = $mform-&amp;gt;createElement(&#039;group&#039;, &#039;groupname&#039;, get_string(&#039;label&#039;), $groupitems);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* By default, groups modify the names of elements inside them by appending a number. This is often unhelpful, for example if you want to use disabledIf on the element. To prevent this behaviour, set the last parameter to false when creating a group.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$group = $mform-&amp;gt;createElement(&#039;group&#039;, &#039;groupname&#039;, get_string(&#039;label&#039;), $groupitems, null, false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==addRule==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addRule(&#039;elementname&#039;, get_string(&#039;error&#039;), &#039;rule type&#039;, &#039;extraruledata&#039;, &#039;server&#039;(default), false, false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first param(element) is an element name and second(message) is the error message that will be displayed to the user.&lt;br /&gt;
The third parameter(type) is the type of rule. The fourth param(format) is used for extra data needed with some rules such as minlength and regex. The fifth parameter(validation) validates input data on server or client side, if validation is done on client side then it will be checked on the server side as well.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 * @param    string     $element       Form element name&lt;br /&gt;
 * @param    string     $message       Message to display for invalid data&lt;br /&gt;
 * @param    string     $type          Rule type, use getRegisteredRules() to get types&lt;br /&gt;
 * @param    string     $format        (optional)Required for extra rule data&lt;br /&gt;
 * @param    string     $validation    (optional)Where to perform validation: &amp;quot;server&amp;quot;, &amp;quot;client&amp;quot;&lt;br /&gt;
 * @param    boolean    $reset         Client-side validation: reset the form element to its original value if there is an error?&lt;br /&gt;
 * @param    boolean    $force         Force the rule to be applied, even if the target form element does not exist&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Common Rule Types&#039;&#039;&#039;&lt;br /&gt;
* required &lt;br /&gt;
* maxlength&lt;br /&gt;
* minlength&lt;br /&gt;
* rangelength&lt;br /&gt;
* email&lt;br /&gt;
* regex&lt;br /&gt;
* lettersonly&lt;br /&gt;
* alphanumeric&lt;br /&gt;
* numeric&lt;br /&gt;
* nopunctuation&lt;br /&gt;
* nonzero&lt;br /&gt;
* callback&lt;br /&gt;
* compare&lt;br /&gt;
&lt;br /&gt;
===Server side and Client side===&lt;br /&gt;
In case you use the &#039;&#039;Client side&#039;&#039; validation option, you can mainly check for an empty or not input field. unless you write some &#039;&#039;Client side&#039;&#039; code which will probably be JavaScript functions to verify the data inside the input fields before it is submitted to the server. It could save some time if those functions are short, simple and quick to compute.&lt;br /&gt;
In case you need a more complex validation checks which relay on Moodle&#039;s internal PHP libraries (or other/external PHP libraries) you better use the &#039;&#039;Server side&#039;&#039; validation checks. Where you can query the DB, write complex PHP validation functions and much much more, that are not available (easily) when using JavaScript on the client&#039;s side.&lt;br /&gt;
&lt;br /&gt;
==setHelpButton==&lt;br /&gt;
{{Moodle 1.9}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;setHelpButton(&#039;lessondefault&#039;, array(&#039;lessondefault&#039;, get_string(&#039;lessondefault&#039;, &#039;lesson&#039;), &#039;lesson&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
First param is an elementname and the second param is an array of params that are passed to helpbutton in weblib.php. Params are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 * @param string $page  The keyword that defines a help page&lt;br /&gt;
 * @param string $title The title of links, rollover tips, alt tags etc&lt;br /&gt;
 *           &#039;Help with&#039; (or the language equivalent) will be prefixed and &#039;...&#039; will be stripped.&lt;br /&gt;
 * @param string $module Which module is the page defined in&lt;br /&gt;
 * @param mixed $image Use a help image for the link?  (true/false/&amp;quot;both&amp;quot;)&lt;br /&gt;
 * @param boolean $linktext If true, display the title next to the help icon.&lt;br /&gt;
 * @param string $text If defined then this text is used in the page, and&lt;br /&gt;
 *           the $page variable is ignored.&lt;br /&gt;
 * @param boolean $return If true then the output is returned as a string, if false it is printed to the current page.&lt;br /&gt;
 * @param string $imagetext The full text for the helpbutton icon. If empty use default help.gif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure you don&#039;t set boolean $return to false. &lt;br /&gt;
&lt;br /&gt;
You need to do use this method after addElement();&lt;br /&gt;
&lt;br /&gt;
==addHelpButton==&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addHelpButton(&#039;api_key_field&#039;, &#039;api_key&#039;, &#039;block_extsearch&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.0 the &amp;quot;setHelpButton&amp;quot; method has been deprecated in favor of the &amp;quot;addHelpButton&amp;quot; method, which has a simplified interface and uses $OUTPUT-&amp;gt;help_icon() on the back end. The following parameters are expected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * @param $elementname The name of the form element to add the help button for&lt;br /&gt;
 * @param $identifier The identifier for the help string and its title (see below)&lt;br /&gt;
 * @param $component The component name to look for the help string in&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Unlike in Moodle 1.9, it is no longer necessary to put your help pages in separate HTML files. Instead, the function looks for two strings:&lt;br /&gt;
&lt;br /&gt;
# get_string($identifier, $component) // The title of the help page&lt;br /&gt;
# get_string(&amp;quot;{$identifier}_help&amp;quot;, $component) // The content of the help page&lt;br /&gt;
&lt;br /&gt;
So you will need to have &#039;&#039;&#039;$identifier&#039;&#039;&#039; and &#039;&#039;&#039;{$identifier}_help&#039;&#039;&#039; defined in order for the help button to be created properly. For example the multiple choice question editing form has a button for shuffling the answers. &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addHelpButton(&#039;shuffleanswers&#039;, &#039;shuffleanswers&#039;, &#039;qtype_multichoice&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
and so the language file includes the strings&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;shuffleanswers&#039;] = &#039;Shuffle the choices?&#039;; &lt;br /&gt;
$string[&#039;shuffleanswers_help&#039;] = &#039;If enabled,.....&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You can also add the language string like&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;shuffleanswers_link&#039;] = &#039;question/shuffleanswers&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
to add a link to more help on Moodle docs. See [[String_API]] for more information about help icons.&lt;br /&gt;
&lt;br /&gt;
==setDefault==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;select&#039;, &#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), $grades);&lt;br /&gt;
$mform-&amp;gt;setHelpButton(&#039;grade&#039;, array(&#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), &#039;exercise&#039;));&lt;br /&gt;
$mform-&amp;gt;setDefault(&#039;grade&#039;, 100);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the default of the form value with setDefault($elementname, $value); where elementname is the elementname whose default you want to set and $value is the default to set. We set the defaults for the form in definition(). This default is what is used if no data is loaded into the form with set_data(); eg. on display of the form for an &#039;add&#039; rather than &#039;update&#039; function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;editor&#039;, &#039;desc&#039;, get_string(&#039;description&#039;));     &lt;br /&gt;
$mform-&amp;gt;setDefault(&#039;desc&#039;, array(&#039;text&#039;=&amp;gt;$defaulttext));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that when setting the default for an editor element you must use an array to define the default &amp;quot;text&amp;quot; value as shown above.&lt;br /&gt;
&lt;br /&gt;
==disabledIf==&lt;br /&gt;
&lt;br /&gt;
For any element or groups of element in a form you can conditionally disable the group or individual element depending on conditions.&lt;br /&gt;
&lt;br /&gt;
You can use $mform-&amp;gt;disabledIf($elementName, $dependentOn, $condition = &#039;notchecked&#039;, $value=&#039;1&#039;)&lt;br /&gt;
&lt;br /&gt;
* elementname can be a group. If you specify a group all elements in the group will be disabled (if dependentOn is in elementname group that is ignored and not disabled). These are the element names you&#039;ve used as the second argument in addElement or addGroup.&lt;br /&gt;
* dependentOn is the actual name of the element as it will appear in html. This can be different to the name used in addGroup particularly but also addElement where you&#039;re adding a complex element like a date_selector. Check the html of your page. You typically make the depedentOn a checkbox or select box.&lt;br /&gt;
* $condition will be &#039;notchecked&#039;, &#039;checked&#039;, &#039;noitemselected&#039;, &#039;eq&#039;, &#039;in&#039; or, if it is anything else, we test for &#039;neq&#039;.&lt;br /&gt;
** If $condition is &#039;eq&#039; or &#039;neq&#039; then we check the value of the dependentOn field and check for equality (==) or nonequality (!=) in js&lt;br /&gt;
** If $condition is &#039;checked&#039; or &#039;notchecked&#039; then we check to see if a checkbox is checked or not.&lt;br /&gt;
** If $condition is &#039;in&#039; then we check to see if a selected item is in the given list or not. (This was introduced in Moodle 2.7+)&lt;br /&gt;
** If $condition is &#039;noitemselected&#039; then we check to see whether nothing is selected in a dropdown list.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 // Disable my control unless a checkbox is checked.&lt;br /&gt;
 $mform-&amp;gt;disabledIf(&#039;mycontrol&#039;, &#039;somecheckbox&#039;);&lt;br /&gt;
 &lt;br /&gt;
 // Disable my control if a checkbox &#039;&#039;&#039;is&#039;&#039;&#039; checked.&lt;br /&gt;
 $mform-&amp;gt;disabledIf(&#039;mycontrol&#039;, &#039;somecheckbox&#039;, &#039;checked&#039;);&lt;br /&gt;
 &lt;br /&gt;
 // Disable my control when a dropdown has value 42.&lt;br /&gt;
 $mform-&amp;gt;disabledIf(&#039;mycontrol&#039;, &#039;someselect&#039;, &#039;eq&#039;, 42);&lt;br /&gt;
&lt;br /&gt;
 // Disable my control unless a dropdown has value 42.&lt;br /&gt;
 $mform-&amp;gt;disabledIf(&#039;mycontrol&#039;, &#039;someselect&#039;, &#039;neq&#039;, 42);&lt;br /&gt;
&lt;br /&gt;
The possible choices here are in the dependency manager in lib/form/form.js.&lt;br /&gt;
===A tricky case===&lt;br /&gt;
&lt;br /&gt;
You need to take care with disabledIf if you plan to use it with groups of checkboxes.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say you have a group of 5 checkboxes and you want to enable a depending item such as a drop down menu only when the first and the last checkboxes are selected.&lt;br /&gt;
&lt;br /&gt;
To fix ideas:&lt;br /&gt;
&lt;br /&gt;
If the selection in the checkboxes group is:&lt;br /&gt;
&lt;br /&gt;
 mycheck_01 == 1&lt;br /&gt;
 mycheck_02 == 0&lt;br /&gt;
 mycheck_03 == 0&lt;br /&gt;
 mycheck_04 == 0&lt;br /&gt;
 mycheck_05 == 1&lt;br /&gt;
&lt;br /&gt;
the depending item must be enabled while ANY OTHER COMBINATION must disable the drop down menu.&lt;br /&gt;
&lt;br /&gt;
The following code will, apparently, fail:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;dropdownmenu&#039;, &#039;mycheck_01&#039;, &#039;neq&#039;, &#039;1&#039;);&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;dropdownmenu&#039;, &#039;mycheck_02&#039;, &#039;neq&#039;, &#039;0&#039;);&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;dropdownmenu&#039;, &#039;mycheck_03&#039;, &#039;neq&#039;, &#039;0&#039;);&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;dropdownmenu&#039;, &#039;mycheck_04&#039;, &#039;neq&#039;, &#039;0&#039;);&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;dropdownmenu&#039;, &#039;mycheck_05&#039;, &#039;neq&#039;, &#039;1&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In fact, once you get the drop down menu enabled, you are free to unselect mycheck_01 whilst still having the depending item enabled.&lt;br /&gt;
This apparent bug occurs because a non-checked checkbox behaves like a non existing mform element. So the js code will not find the element &amp;quot;mycheck_01&amp;quot; and will not apply the corresponding rule.&lt;br /&gt;
&lt;br /&gt;
A working solution for this kind of issue seems to be:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;dropdownmenu&#039;, &#039;mycheck_01&#039;, &#039;notchecked&#039;);&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;dropdownmenu&#039;, &#039;mycheck_02&#039;, &#039;checked&#039;);&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;dropdownmenu&#039;, &#039;mycheck_03&#039;, &#039;checked&#039;);&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;dropdownmenu&#039;, &#039;mycheck_04&#039;, &#039;checked&#039;);&lt;br /&gt;
$mform-&amp;gt;disabledIf(&#039;dropdownmenu&#039;, &#039;mycheck_05&#039;, &#039;notchecked&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To see a failing example as the one described, try the attachments provided in MDL-38975. See also in MDL-38975 for the working solution in action with modifications suggested by Eloy.&lt;br /&gt;
&lt;br /&gt;
==hideIf==&lt;br /&gt;
{{Moodle 3.4}}&lt;br /&gt;
For any element or groups of element in a form you can conditionally hide the group or individual element depending on conditions.&lt;br /&gt;
This uses the same syntax as disabledIf just with hideIf instead.&lt;br /&gt;
&lt;br /&gt;
==setType==&lt;br /&gt;
&lt;br /&gt;
PARAM_* types are used to specify how a submitted variable should be cleaned. These should be used for get parameters such as id, course etc. which are used to load a page and also with setType(); method. Every form element should have a type specified except select, radio box and checkbox elements, these elements do a good job of cleaning themselves (only specified options are allowed as user input).&lt;br /&gt;
&lt;br /&gt;
===Most Commonly Used PARAM_* Types===&lt;br /&gt;
&lt;br /&gt;
These are the most commonly used PARAM_* types and their proper uses. More types can be seen in moodlelib.php starting around line 100.&lt;br /&gt;
&lt;br /&gt;
* PARAM_CLEAN is deprecated and you should try to use a more specific type.&lt;br /&gt;
* PARAM_TEXT should be used for cleaning data that is expected to contain multi-lang content. It will strip all html tags. But will still let tags for multilang support through.&lt;br /&gt;
* PARAM_NOTAGS should be used for cleaning data that is expected to be plain text. It will strip *all* html type tags. It will *not* let tags for multilang support through. This should be used for instance for email addresses where no multilang support is appropriate.&lt;br /&gt;
* PARAM_RAW means no cleaning whatsoever, it is used mostly for data from the html editor. Data from the editor is later cleaned before display using format_text() function. PARAM_RAW can also be used for data that is validated by some other way or printed by p() or s().&lt;br /&gt;
* PARAM_INT should be used for integers. PARAM_FLOAT is also available for decimal numbers but is not recommended for user input since it does not work for languages that use , as a decimal separator.&lt;br /&gt;
* PARAM_ACTION is an alias of PARAM_ALPHA and is used for hidden fields specifying form actions.&lt;br /&gt;
&lt;br /&gt;
==disable_form_change_checker==&lt;br /&gt;
&lt;br /&gt;
By default, any Moodle form will pop-up an &amp;quot;Are you sure?&amp;quot; alert if you make some changes and then try to leave the page without saving. Occasionally, that is undesirable, in which case you can call&lt;br /&gt;
&lt;br /&gt;
 $mform-&amp;gt;disable_form_change_checker()&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
* [http://www.midnighthax.com/quickform.php PEAR HTML QuickForm Getting Started Guide] by Keith Edmunds of Midnighthax.com&lt;br /&gt;
* [http://pear.php.net/manual/en/package.html.html-quickform.php PEAR::HTML_QuickForm manual]&lt;br /&gt;
&lt;br /&gt;
[[Category:Formslib]]&lt;br /&gt;
[[Category:Interfaces]]&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Favourites_API&amp;diff=55773</id>
		<title>Favourites API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Favourites_API&amp;diff=55773"/>
		<updated>2019-03-19T01:14:13Z</updated>

		<summary type="html">&lt;p&gt;Peterd17: The alias in the sql should match up with the argument passed in the preceding function&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Overview==&lt;br /&gt;
===What is a favourite?===&lt;br /&gt;
The favourites API allows you to mark items as favourites for a given user. Marking an item as a favourite is akin to adding a web page to your browser favourites (or bookmarks), or marking someone in your contacts as a favourite. The API provides a means to create, read and delete favourite items, allowing any component to favourite arbitrary items as they see fit.&lt;br /&gt;
&lt;br /&gt;
===What can be marked as a favourite?===&lt;br /&gt;
Almost any &#039;item&#039; can be marked as a favourite, provided it is something which can be identified by a unique integer id.&lt;br /&gt;
===Identifying items===&lt;br /&gt;
In order to store a favourite, and be able to uniquely identify it for later retrieval, 4 fields are required. These are: &#039;&#039;&#039;component&#039;&#039;&#039;, &#039;&#039;&#039;itemtype&#039;&#039;&#039;, &#039;&#039;&#039;itemid&#039;&#039;&#039; and &#039;&#039;&#039;contextid&#039;&#039;&#039;. You will see these in a range of API calls.&lt;br /&gt;
 &lt;br /&gt;
The &#039;&#039;&#039;itemid&#039;&#039;&#039; is a unique integer identifier of the item itself. This might be a course id, or conversation id, or the id of any entity in Moodle. In fact, it does not have to be the id of a record from the database either; it can be any arbitrary id, so long as the component storing the item knows what it represents.&lt;br /&gt;
&lt;br /&gt;
The two fields &#039;&#039;&#039;component&#039;&#039;&#039; and &#039;&#039;&#039;itemtype&#039;&#039;&#039; make up a pairing representing the &#039;&#039;type&#039;&#039; of each favourite. Within this pair, the &#039;&#039;&#039;component&#039;&#039;&#039; must be a valid [[Frankenstyle|frankenstyle]] component name and is the name of the component wishing to set/unset the item as a favourite. The &#039;&#039;&#039;itemtype&#039;&#039;&#039; can be any identifying string, provided it is unique within the respective component. The type pairing allows us to distinguish between favourites of different types (from different areas of Moodle), which may have identical itemid values. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;contextid&#039;&#039;&#039; is the id of the context in which the item is being marked as a favourite. For example, a user&#039;s course might be marked as a favourite at the course context, whereas a user&#039;s conversation with another user might be marked as a favourite at the user context. It&#039;s also possible that items of a certain &#039;&#039;type&#039;&#039; (remember, this is the {component, itemtype} pairing) will be marked as favourites in different contexts, based on the context of the item itself. For example, consider the case in messaging, in which we have a group conversation (one which is linked to a course group), and an individual conversation between two users. Setting the group conversation as a favourite would require the course context to be used, whereas doing the same for the individual conversation would require a user context. Which contextid to use is a decision that must be made by the component creating the favourite.&lt;br /&gt;
&lt;br /&gt;
==Using the API==&lt;br /&gt;
===Getting a service object===&lt;br /&gt;
Favourites relies on a service layer to provide functionality to consumers. Getting a service object is as simple as using the service factory methods.&lt;br /&gt;
&lt;br /&gt;
Assuming you have a user context, you can get a service scoped to a single user with:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The returned $ufservice is an object of type \core_favourites\local\service\user_favourite_service.&lt;br /&gt;
&lt;br /&gt;
===Creating a favourite===&lt;br /&gt;
Let&#039;s say we want to set a course as a favourite. Note: In core, this is done by using the favourite &#039;&#039;type&#039;&#039; {&#039;core_course&#039;, &#039;courses&#039;}. &lt;br /&gt;
&lt;br /&gt;
The service provides the method:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function create_favourite(string $component, string $itemtype, int $itemid, \context $context, int $ordering = null) : favourite;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
So, assuming we have the courseid and course context, we can create our favourite with:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$favourite = $ufservice-&amp;gt;create_favourite(&#039;core_course&#039;, &#039;courses&#039;, $course-&amp;gt;id, $coursecontext);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The returned $favourite is an object of type \core_favourites\local\entity\favourite.&lt;br /&gt;
&lt;br /&gt;
===Reading favourites===&lt;br /&gt;
There are several read actions supported by the service object.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function count_favourites_by_type(string $component, string $itemtype, \context $context = null) : int;&lt;br /&gt;
public function find_favourites_by_type(string $component, string $itemtype, int $limitfrom = 0, int $limitnum = 0) : array;&lt;br /&gt;
public function favourite_exists(string $component, string $itemtype, int $itemid, \context $context) : bool;&lt;br /&gt;
public function get_favourite(string $component, string $itemtype, int $itemid, \context $context) : favourite;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Deleting a favourite===&lt;br /&gt;
The service provides the method:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function delete_favourite(string $component, string $itemtype, int $itemid, \context $context);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
So, assuming we have the courseid and course context, we can remove the favourite with:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);&lt;br /&gt;
$ufservice-&amp;gt;delete_favourite(&#039;core_course&#039;, &#039;courses&#039;, $course-&amp;gt;id, $coursecontext);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Including favourites in external queries===&lt;br /&gt;
Most of the time, you should ask the service to find favourite items for you. Sometimes, however, rather than fetching the favourites from the service, you&#039;ll just want to include the relevant information in those records from an existing query. You might want to do this if dealing with performance sensitive code where additional queries are undesirable.&lt;br /&gt;
&lt;br /&gt;
The service lets you do this too, by providing the method:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function get_join_sql_by_type(string $component, string $itemtype, string $tablealias, string $joinitemid) : array;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
which can be used in such cases.&lt;br /&gt;
&lt;br /&gt;
For example, and for simplicity, let&#039;s say we have a query returning the ids and names of all courses within a given course category:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$sql = &amp;quot;SELECT c.id, c.name&lt;br /&gt;
          FROM {course} c&lt;br /&gt;
         WHERE c.category = :category&amp;quot;;&lt;br /&gt;
$params = [&#039;category&#039; =&amp;gt; 3];&lt;br /&gt;
&lt;br /&gt;
$courses = $DB-&amp;gt;get_records_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
we can then modify this using the get_join_sql_by_type() result to include favourite information.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);&lt;br /&gt;
list($favsql, $favparams) = $ufservice-&amp;gt;get_join_sql_by_type(&#039;core_course&#039;, &#039;courses&#039;, &#039;favalias&#039;, &#039;c.id&#039;);&lt;br /&gt;
&lt;br /&gt;
$sql = &amp;quot;SELECT c.id, c.name, favalias.id as favouriteid&lt;br /&gt;
          FROM {course} c&lt;br /&gt;
       $favsql&lt;br /&gt;
         WHERE c.category = :category&amp;quot;;&lt;br /&gt;
$params = [&#039;category&#039; =&amp;gt; 3] + $favparams;&lt;br /&gt;
&lt;br /&gt;
$courses = $DB-&amp;gt;get_records_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
We&#039;ve now included id of the favourite in the results via a LEFT JOIN, so as to preserve the original set of records.&lt;br /&gt;
&lt;br /&gt;
If you wish to select ONLY favourites, adding &amp;quot;AND favouriteid IS NOT NULL&amp;quot; to the query will achieve this.&lt;/div&gt;</summary>
		<author><name>Peterd17</name></author>
	</entry>
</feed>