<?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=Vmdef</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=Vmdef"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Vmdef"/>
	<updated>2026-06-16T14:56:28Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Prototypes&amp;diff=63934</id>
		<title>Prototypes</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Prototypes&amp;diff=63934"/>
		<updated>2023-07-03T16:07:04Z</updated>

		<summary type="html">&lt;p&gt;Vmdef: /* Download site migration prototype removed */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides links to prototype sites demonstrating new features that will be included in coming versions of Moodle.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We would love to hear what you think of these new features! After exploring the sites, please post your feedback in the [https://moodle.org/mod/forum/view.php?id=8052 Future major features forum].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New projects and prototype site demonstrations ==&lt;br /&gt;
=== Calendar usability improvements ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| As part of the UX improvements for Moodle 4.0, we are working on updates to the calendar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main aims for this project are to make the calendar, calendar block and subscription management more intuitive, easier to use and improve accessibility.&lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDL-71770 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
| [https://calendartest.prototype.moodledemo.net/ Calendar usability improvements demo]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== Course creation improvements ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| As part of the UX improvements for Moodle 4.0, we are working on making the like easier on creating and editing courses.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main aims for this project are to improve the user experience of creating and editing courses in Moodle helping teachers to create and organize their courses. Adding new cool features like course index will allow teachers an easy way to view course structure, add new sections and activities, reorganize them and so on.&lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDL-70907 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
| [https://createcourse.prototype.moodledemo.net/ Course creation improvements demo]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== Navigation update ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| We are updating the navigation around Moodle.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main aim is to reduce the cognitive load associated with navigating around a Moodle site. For anyone that is new to using our LMS, there are a lot of settings that are immediately present and possibly not relevant. We are going through and improving the layout of the navigation from the front page all the way to how different activities are displaying settings and buttons.&lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDL-69588 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
| [https://navigation.prototype.moodledemo.net/ Navigation prototype demo]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== Timeline block improvements ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| As part of the UX improvements for Moodle 4.0, we are working on improving the timeline block.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main aims for this project are to improve the layout of information within the timeline block to make it easier to extract important information, replace pagination with &amp;quot;show more&amp;quot; (lazy-loading) functionality, and to provide bug fixes that improve the overall usability of the block.&lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDL-72274 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
|[https://calendartest.prototype.moodledemo.net/ Timeline improvements demo](Note: The timeline features are demonstrated on the same Moodle site as the calendar improvements mentioned above).&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== Site admin presets ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| As part of the UX improvements for Moodle 4.0, we are working on helping administrators to enable/disable features and plugins easily to simplify their Moodle sites.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main aim is to adapt and integrate the [https://moodle.org/plugins/block_admin_presets third-party plugin &amp;quot;Admin presets&amp;quot;], created by David Monllaó and maintained by developers from [https://pimenko.com/ Pimenko]. &lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDL-72111 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
| [https://siteadminpresets.prototype.moodledemo.net/ Site admin presets demo]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
== How to contribute ==&lt;br /&gt;
=== [[File:logo moodle.png|frameless|100px]] &amp;lt;br /&amp;gt; Moodle User Experience (UX) Forums ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| As part of the UX 4.0 release, the UX team are establishing a presence on the Moodle.org platform in order to collaborate and communicate with the wider Moodle Community.&lt;br /&gt;
We&#039;re looking forward to working with you and sharing what we learn and what we do!&lt;br /&gt;
|-&lt;br /&gt;
| More&lt;br /&gt;
| User Experience Forum [https://moodle.org/course/view.php?id=17248 Want to shape the Moodle future with us?].&lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| Moodle UX 4.0 [https://tracker.moodle.org/projects/UX/issues/ tracker issues and epics]&lt;br /&gt;
|-&lt;br /&gt;
| Prototypes&lt;br /&gt;
| [https://www.figma.com/proto/A4d9WOUVxCqS93mvXVCr8P/4.0-UX-Demo?node-id=2394%3A15559&amp;amp;viewport=727%2C769%2C0.07944665849208832&amp;amp;scaling=scale-down 4.0 Desktop Navigation UX Project]&lt;br /&gt;
[https://www.figma.com/proto/A4d9WOUVxCqS93mvXVCr8P/4.0-UX-Demo?node-id=2392%3A11210&amp;amp;viewport=1413%2C310%2C0.31215807795524597&amp;amp;scaling=scale-down 4.0 Mobile Navigation UX Project]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== [[File:logo_moodle_tracker.jpg|frameless|100px]] &amp;lt;br /&amp;gt; Moodle Tracker ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| This is where we record and manage all issues related to Moodle and related systems.&lt;br /&gt;
It&#039;s not just for developers! :-) All users should use this system to report problems or new ideas for Moodle and help us make it better.&lt;br /&gt;
|-&lt;br /&gt;
| More&lt;br /&gt;
| Moodle Tracker [https://tracker.moodle.org/secure/Dashboard.jspa Want to shape the Moodle future with us?].&lt;br /&gt;
|}&lt;br /&gt;
=== [[File:mua-logo-small-onblue.png|frameless|100px]] &amp;lt;br /&amp;gt; Moodle Users Association ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| MUA&#039;s mission is to support the growth of Moodle by providing a strong and united voice to users, giving direction and resources for new developments.&lt;br /&gt;
|-&lt;br /&gt;
| More&lt;br /&gt;
| Join MUA [https://moodle.org/course/view.php?id=17248 Shape the future of Moodle today.].&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
== [[File:logo_moodle_dev.jpg|frameless|100px]] &amp;lt;br /&amp;gt; Other Moodle demo sites ==&lt;br /&gt;
=== QA Moodle Demo ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| It is updated daily at 13:00 UTC with the latest fixes for testers to test and do a final check for any problems.&lt;br /&gt;
Every hour (on the hour) the database and files are reset.&lt;br /&gt;
|-&lt;br /&gt;
| Moodle Version&lt;br /&gt;
| The latest Moodle dev release!&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
| Site&lt;br /&gt;
| &#039;&#039;&#039;[https://qa.moodledemo.net/ qa.moodledemo.net/]&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
=== School Moodle Demo ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| This demonstration site gives you the opportunity to explore Moodle in action as a manager, teacher, student, parent or privacy officer with realistic content.&lt;br /&gt;
This site is reset every hour on the hour so anything you &amp;quot;break&amp;quot; will get fixed.&lt;br /&gt;
|-&lt;br /&gt;
| Moodle Version&lt;br /&gt;
| The latest Moodle stable release!&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
| Site&lt;br /&gt;
| &#039;&#039;&#039;[https://school.moodledemo.net/ school.moodledemo.net/]&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
=== Sandbox Moodle Demo ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| This site is a plain installation of Moodle using the Boost theme.&lt;br /&gt;
This site is reset to its blank state every hour, on the hour.&lt;br /&gt;
|-&lt;br /&gt;
| Moodle Version&lt;br /&gt;
| The latest Moodle stable release!&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
| Site&lt;br /&gt;
| &#039;&#039;&#039;[https://sandbox.moodledemo.net/ sandbox.moodledemo.net/]&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Roadmap]] - for an overview of new features planned for the next release&lt;br /&gt;
* [[Releases]] - for all official releases of Moodle, grouped by branch in reverse chronological order&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vmdef</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Prototypes&amp;diff=63823</id>
		<title>Prototypes</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Prototypes&amp;diff=63823"/>
		<updated>2023-02-17T09:10:39Z</updated>

		<summary type="html">&lt;p&gt;Vmdef: Added download site prototype&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page provides links to prototype sites demonstrating new features that will be included in coming versions of Moodle.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We would love to hear what you think of these new features! After exploring the sites, please post your feedback in the [https://moodle.org/mod/forum/view.php?id=8052 Future major features forum].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New projects and prototype site demonstrations ==&lt;br /&gt;
=== Calendar usability improvements ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| As part of the UX improvements for Moodle 4.0, we are working on updates to the calendar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main aims for this project are to make the calendar, calendar block and subscription management more intuitive, easier to use and improve accessibility.&lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDL-71770 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
| [https://calendartest.prototype.moodledemo.net/ Calendar usability improvements demo]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== Course creation improvements ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| As part of the UX improvements for Moodle 4.0, we are working on making the like easier on creating and editing courses.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main aims for this project are to improve the user experience of creating and editing courses in Moodle helping teachers to create and organize their courses. Adding new cool features like course index will allow teachers an easy way to view course structure, add new sections and activities, reorganize them and so on.&lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDL-70907 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
| [https://createcourse.prototype.moodledemo.net/ Course creation improvements demo]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== Navigation update ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| We are updating the navigation around Moodle.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main aim is to reduce the cognitive load associated with navigating around a Moodle site. For anyone that is new to using our LMS, there are a lot of settings that are immediately present and possibly not relevant. We are going through and improving the layout of the navigation from the front page all the way to how different activities are displaying settings and buttons.&lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDL-69588 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
| [https://navigation.prototype.moodledemo.net/ Navigation prototype demo]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== Timeline block improvements ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| As part of the UX improvements for Moodle 4.0, we are working on improving the timeline block.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main aims for this project are to improve the layout of information within the timeline block to make it easier to extract important information, replace pagination with &amp;quot;show more&amp;quot; (lazy-loading) functionality, and to provide bug fixes that improve the overall usability of the block.&lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDL-72274 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
|[https://calendartest.prototype.moodledemo.net/ Timeline improvements demo](Note: The timeline features are demonstrated on the same Moodle site as the calendar improvements mentioned above).&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== Site admin presets ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| As part of the UX improvements for Moodle 4.0, we are working on helping administrators to enable/disable features and plugins easily to simplify their Moodle sites.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main aim is to adapt and integrate the [https://moodle.org/plugins/block_admin_presets third-party plugin &amp;quot;Admin presets&amp;quot;], created by David Monllaó and maintained by developers from [https://pimenko.com/ Pimenko]. &lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDL-72111 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
| [https://siteadminpresets.prototype.moodledemo.net/ Site admin presets demo]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== Download site migration ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| download.moodle.org is out of the K8&#039;s infrastructure and uses Moodle 3.5 version.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main objective of this project is to upgrade the Moodle instance and move it to the K8 infrastructure, where all the other sites are hosted. &lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| [https://tracker.moodle.org/browse/MDLSITE-7013 Tracker epic containing all related issues]&lt;br /&gt;
|-&lt;br /&gt;
| Prototype&lt;br /&gt;
| [https://download.prototype.moodledemo.net/ Download site demo]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.1&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
== How to contribute ==&lt;br /&gt;
=== [[File:logo moodle.png|frameless|100px]] &amp;lt;br /&amp;gt; Moodle User Experience (UX) Forums ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| As part of the UX 4.0 release, the UX team are establishing a presence on the Moodle.org platform in order to collaborate and communicate with the wider Moodle Community.&lt;br /&gt;
We&#039;re looking forward to working with you and sharing what we learn and what we do!&lt;br /&gt;
|-&lt;br /&gt;
| More&lt;br /&gt;
| User Experience Forum [https://moodle.org/course/view.php?id=17248 Want to shape the Moodle future with us?].&lt;br /&gt;
|-&lt;br /&gt;
| Project Tracker&lt;br /&gt;
| Moodle UX 4.0 [https://tracker.moodle.org/projects/UX/issues/ tracker issues and epics]&lt;br /&gt;
|-&lt;br /&gt;
| Prototypes&lt;br /&gt;
| [https://www.figma.com/proto/A4d9WOUVxCqS93mvXVCr8P/4.0-UX-Demo?node-id=2394%3A15559&amp;amp;viewport=727%2C769%2C0.07944665849208832&amp;amp;scaling=scale-down 4.0 Desktop Navigation UX Project]&lt;br /&gt;
[https://www.figma.com/proto/A4d9WOUVxCqS93mvXVCr8P/4.0-UX-Demo?node-id=2392%3A11210&amp;amp;viewport=1413%2C310%2C0.31215807795524597&amp;amp;scaling=scale-down 4.0 Mobile Navigation UX Project]&lt;br /&gt;
|-&lt;br /&gt;
| Target Version&lt;br /&gt;
| 4.0&lt;br /&gt;
|}&lt;br /&gt;
=== [[File:logo_moodle_tracker.jpg|frameless|100px]] &amp;lt;br /&amp;gt; Moodle Tracker ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| This is where we record and manage all issues related to Moodle and related systems.&lt;br /&gt;
It&#039;s not just for developers! :-) All users should use this system to report problems or new ideas for Moodle and help us make it better.&lt;br /&gt;
|-&lt;br /&gt;
| More&lt;br /&gt;
| Moodle Tracker [https://tracker.moodle.org/secure/Dashboard.jspa Want to shape the Moodle future with us?].&lt;br /&gt;
|}&lt;br /&gt;
=== [[File:mua-logo-small-onblue.png|frameless|100px]] &amp;lt;br /&amp;gt; Moodle Users Association ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| MUA&#039;s mission is to support the growth of Moodle by providing a strong and united voice to users, giving direction and resources for new developments.&lt;br /&gt;
|-&lt;br /&gt;
| More&lt;br /&gt;
| Join MUA [https://moodle.org/course/view.php?id=17248 Shape the future of Moodle today.].&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
== [[File:logo_moodle_dev.jpg|frameless|100px]] &amp;lt;br /&amp;gt; Other Moodle demo sites ==&lt;br /&gt;
=== QA Moodle Demo ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| It is updated daily at 13:00 UTC with the latest fixes for testers to test and do a final check for any problems.&lt;br /&gt;
Every hour (on the hour) the database and files are reset.&lt;br /&gt;
|-&lt;br /&gt;
| Moodle Version&lt;br /&gt;
| The latest Moodle dev release!&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
| Site&lt;br /&gt;
| &#039;&#039;&#039;[https://qa.moodledemo.net/ qa.moodledemo.net/]&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
=== School Moodle Demo ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| This demonstration site gives you the opportunity to explore Moodle in action as a manager, teacher, student, parent or privacy officer with realistic content.&lt;br /&gt;
This site is reset every hour on the hour so anything you &amp;quot;break&amp;quot; will get fixed.&lt;br /&gt;
|-&lt;br /&gt;
| Moodle Version&lt;br /&gt;
| The latest Moodle stable release!&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
| Site&lt;br /&gt;
| &#039;&#039;&#039;[https://school.moodledemo.net/ school.moodledemo.net/]&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
=== Sandbox Moodle Demo ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Description&lt;br /&gt;
| This site is a plain installation of Moodle using the Boost theme.&lt;br /&gt;
This site is reset to its blank state every hour, on the hour.&lt;br /&gt;
|-&lt;br /&gt;
| Moodle Version&lt;br /&gt;
| The latest Moodle stable release!&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
| Site&lt;br /&gt;
| &#039;&#039;&#039;[https://sandbox.moodledemo.net/ sandbox.moodledemo.net/]&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Roadmap]] - for an overview of new features planned for the next release&lt;br /&gt;
* [[Releases]] - for all official releases of Moodle, grouped by branch in reverse chronological order&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vmdef</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Travis_integration&amp;diff=57768</id>
		<title>Travis integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Travis_integration&amp;diff=57768"/>
		<updated>2020-08-12T15:44:51Z</updated>

		<summary type="html">&lt;p&gt;Vmdef: Settings update&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Moodle core ==&lt;br /&gt;
&lt;br /&gt;
=== Background ===&lt;br /&gt;
&lt;br /&gt;
Moodle is regularly tested against a matrix of Databases, PHP Versions, and operating systems, however many developers do not have the resources available to run on many of these combinations before pushing an issue for integration as they are time-consuming to both set up and to run.&lt;br /&gt;
&lt;br /&gt;
There are many Continuous Integration tools available to developers, and Travis-CI is just one of those available freely to the Open Source community.&lt;br /&gt;
&lt;br /&gt;
Since version 3.0, Moodle includes a Travis configuration file in its repository. This configuration file configures and controls a Travis build across a matrix of testing environments. This allows developers pushing patches to Moodle to have their code unit tested before it reaches integration. The hope is that the availability of this integration should reduce the number of unit test failures seen during Integration.&lt;br /&gt;
&lt;br /&gt;
Note: Moodle HQ uses the Jenkins CI platform internally and this should be seen as the canonical CI server for Moodle. The Travis integration provided is to provide early warning to developers of any issues with their code.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
Travis-CI is freely available and is usually configured to run automatically when pushing code, but it must be configured before first use.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this documentation, it is assumed that you are pushing to a public Moodle repository on GitHub. Other integrations are supported, but the free service available from Travis is only available to public repositories.&lt;br /&gt;
&lt;br /&gt;
=== Setup ===&lt;br /&gt;
&lt;br /&gt;
# [https://travis-ci.org/auth Sign in to Travis CI] using your GitHub account&lt;br /&gt;
# Once you’re signed in, and the initial synchronisation of your GitHub repositories has completed, go to your [https://travis-ci.org/profile profile page]&lt;br /&gt;
# Enable Travis CI for your clone of the Moodle repository [[File:moodle-travis-enable.png]]&lt;br /&gt;
# Click on the cog icon to configure the Integration&lt;br /&gt;
# Ensure that &amp;quot;Build pushed branches&amp;quot; is enabled [[File:moodle-travis-settings-2020.png]]&lt;br /&gt;
&lt;br /&gt;
=== How do I start a build? ===&lt;br /&gt;
&lt;br /&gt;
It won&#039;t build immediately after setup. Builds start automatically when you push a change.&lt;br /&gt;
&lt;br /&gt;
== Moodle plugins ==&lt;br /&gt;
&lt;br /&gt;
See [https://moodlehq.github.io/moodle-plugin-ci/ Moodle Plugin CI repository] for setup instructions.&lt;br /&gt;
&lt;br /&gt;
Related discussions:&lt;br /&gt;
* [https://moodle.org/mod/forum/discuss.php?d=323384 Adding Travis CI support into your plugin]&lt;br /&gt;
* [https://moodle.org/mod/forum/discuss.php?d=389744 Recent Travis-CI issues with plugins]&lt;br /&gt;
&lt;br /&gt;
=== Ignoring files and folders ===&lt;br /&gt;
&lt;br /&gt;
For some of the code analysis tools, it is important to ignore some files within the plugin because they might not be fixable, like a third party library. The all code analysis commands in this project ignore files and directories listed in the thirdpartylibs.xml plugin file. See https://docs.moodle.org/dev/Plugin_files#thirdpartylibs.xml for more info.&lt;br /&gt;
&lt;br /&gt;
==== Ignoring files ====&lt;br /&gt;
&lt;br /&gt;
Specifically for the codechecker command, you can ignore a single line, a section of a file or the whole file by using specific PHP comments. For details see this [[CodeSniffer]] wiki page.&lt;br /&gt;
In addition, you can ignore additional files by defining IGNORE_PATHS and/or IGNORE_NAMES environment variables in your .travis.yml file. These environment variables wont work for Grunt tasks, but will for everything else. Example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
env:&lt;br /&gt;
 global:&lt;br /&gt;
  - MOODLE_BRANCH=MOODLE_35_STABLE&lt;br /&gt;
  - IGNORE_PATHS=vendor/widget,javascript/min-lib.js&lt;br /&gt;
  - IGNORE_NAMES=*-m.js,bad_lib.php&lt;br /&gt;
 matrix:&lt;br /&gt;
  - DB=pgsql&lt;br /&gt;
  - DB=mysqli&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Both environment variables take a CSV value. For IGNORE_PATHS, it takes relative file paths to ignore. File paths can be a simple string like foo/bar or a regular expression like /^foo\/bar/. For IGNORE_NAMES, it takes file names to ignore. File names can be a simple string like foo.php, a glob like *.php or a regular expression like /\.php$/.&lt;br /&gt;
&lt;br /&gt;
If you need to specify ignore paths for a specific command, then you can define additional environment variables. The variable names are the same as above, but prefixed with COMMANDNAME_. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
env:&lt;br /&gt;
 global:&lt;br /&gt;
  - MOODLE_BRANCH=MOODLE_35_STABLE&lt;br /&gt;
  - IGNORE_PATHS=vendor/widget,javascript/min-lib.js&lt;br /&gt;
  - IGNORE_NAMES=*-m.js,bad_lib.php&lt;br /&gt;
  - PHPUNIT_IGNORE_PATHS=$IGNORE_PATHS,cli&lt;br /&gt;
 matrix:&lt;br /&gt;
  - DB=pgsql&lt;br /&gt;
  - DB=mysqli&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In the above example, we are adding the cli path to our ignore paths for the PHPUnit command (this is also how you can ignore files for code coverage). Please note that this is a complete override and there is no merging with IGNORE_PATHS and IGNORE_NAMES. So, in the above, the PHPUnit command would not ignore the file names defined in IGNORE_NAMES.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Talk:Travis Integration]] for previous Travis dev docs&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer tools]]&lt;/div&gt;</summary>
		<author><name>Vmdef</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:moodle-travis-settings-2020.png&amp;diff=57767</id>
		<title>File:moodle-travis-settings-2020.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:moodle-travis-settings-2020.png&amp;diff=57767"/>
		<updated>2020-08-12T15:43:08Z</updated>

		<summary type="html">&lt;p&gt;Vmdef: Travis CI settings for Moodle repositories&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Travis CI settings for Moodle repositories&lt;/div&gt;</summary>
		<author><name>Vmdef</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Travis_integration&amp;diff=57766</id>
		<title>Talk:Travis integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Travis_integration&amp;diff=57766"/>
		<updated>2020-08-12T15:39:13Z</updated>

		<summary type="html">&lt;p&gt;Vmdef: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Note|This page contains previous Travis dev docs. Please move relevant content to [[Travis Integration]] then this page can be deleted.}}&lt;br /&gt;
&lt;br /&gt;
[https://travis-ci.org Travis-ci] is a continuous integration server.&lt;br /&gt;
&lt;br /&gt;
= Moodle core =&lt;br /&gt;
&lt;br /&gt;
Moodle 3.0 comes bundled with a [https://github.com/moodle/moodle/blob/master/.travis.yml .travis.yml file] which executes Moodle&#039;s unit tests suite and PHP lint. More checkings might be added in future.&lt;br /&gt;
&lt;br /&gt;
For previous Moodle versions you can either use Moodle 3.0 .travis.yml file (you will probably have to adapt it) or use the following example ([https://github.com/ds125v/moodle-travis/blob/master/.travis.yml]) Signup on Travis, put the .travis.yml file into your repository, link the repository to Travis and Travis will run all your phpunit tests each time you push to your repository.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
language: php&lt;br /&gt;
php:&lt;br /&gt;
  - &amp;quot;5.4&amp;quot;&lt;br /&gt;
  - &amp;quot;5.3&amp;quot;&lt;br /&gt;
env:&lt;br /&gt;
 - DB=mysqli&lt;br /&gt;
 - DB=pgsql&lt;br /&gt;
before_script:&lt;br /&gt;
 - pear channel-discover pear.phpunit.de&lt;br /&gt;
 - pear channel-discover pear.symfony.com&lt;br /&gt;
 - pear install pear.phpunit.de/DbUnit&lt;br /&gt;
 - phpenv rehash&lt;br /&gt;
 - cp config-dist.php config.php&lt;br /&gt;
 - sh -c &amp;quot;sed -i -e s/&#039;password&#039;/&#039;&#039;/ -e s/example.com/localhost/ -e s%/home/example%$HOME% -e &#039;s%\(\$CFG.*phpu\)%\n\1%&#039; config.php&amp;quot;&lt;br /&gt;
 - sh -c &amp;quot;if [ &#039;$DB&#039; = &#039;mysqli&#039; ]; then mysql -e &#039;create database moodle default character set UTF8 collate UTF8_bin;&#039;; fi&amp;quot;&lt;br /&gt;
 - sh -c &amp;quot;if [ &#039;$DB&#039; = &#039;mysqli&#039; ]; then sed -i -e s/\&#039;pgsql\&#039;/\&#039;mysqli\&#039;/ -e s/\&#039;username\&#039;/\&#039;root\&#039;/ config.php; fi&amp;quot;&lt;br /&gt;
 - sh -c &amp;quot;if [ &#039;$DB&#039; = &#039;pgsql&#039; ]; then psql -c &#039;create database moodle;&#039; -U postgres; fi&amp;quot;&lt;br /&gt;
 - sh -c &amp;quot;if [ &#039;$DB&#039; = &#039;pgsql&#039; ]; then sed -i s/\&#039;username\&#039;/\&#039;postgres\&#039;/ config.php; fi&amp;quot;&lt;br /&gt;
 - mkdir -m777 $HOME/moodledata&lt;br /&gt;
 - php admin/tool/phpunit/cli/init.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Moodle plugins =&lt;br /&gt;
An example on how to run phpunit/behat tests on travis for a Moodle plugin (here the plugin is the [https://github.com/mouneyrac/moodle-auth_googleoauth2/blob/master/.travis.yml Oauth2 authentication plugin]):&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
before_install:&lt;br /&gt;
  - &amp;quot;export DISPLAY=:99.0&amp;quot;&lt;br /&gt;
  - &amp;quot;sh -e /etc/init.d/xvfb start&amp;quot;&lt;br /&gt;
language: php&lt;br /&gt;
php:&lt;br /&gt;
  - &amp;quot;5.4&amp;quot;&lt;br /&gt;
env:&lt;br /&gt;
 - DB=mysqli MOODLE_VERSION=MOODLE_25_STABLE&lt;br /&gt;
 - DB=mysqli MOODLE_VERSION=master&lt;br /&gt;
 - DB=pgsql MOODLE_VERSION=MOODLE_25_STABLE&lt;br /&gt;
 - DB=pgsql MOODLE_VERSION=master&lt;br /&gt;
before_script:&lt;br /&gt;
 - git clone git://github.com/moodle/moodle ../moodle &amp;amp;&amp;amp; cd ../moodle&lt;br /&gt;
 - git checkout $MOODLE_VERSION&lt;br /&gt;
 - sudo apt-get update &amp;gt; /dev/null&lt;br /&gt;
 - composer self-update&lt;br /&gt;
 - composer install --dev --prefer-dist&lt;br /&gt;
 - mv ../moodle-auth_googleoauth2 auth/googleoauth2&lt;br /&gt;
 - git clone git://github.com/mouneyrac/moodle-theme_easy theme/oauth2easy&lt;br /&gt;
 - pear channel-discover pear.phpunit.de&lt;br /&gt;
 - pear channel-discover pear.symfony.com&lt;br /&gt;
 - pear install pear.phpunit.de/DbUnit&lt;br /&gt;
 - phpenv rehash&lt;br /&gt;
 - cp config-dist.php config.php&lt;br /&gt;
 - sh -c &amp;quot;sed -i -e s/&#039;password&#039;/&#039;&#039;/ -e s/example.com/localhost/ -e s%/home/example%$HOME% -e &#039;s%\(\$CFG.*phpu\)%\n\1%&#039; config.php&amp;quot;&lt;br /&gt;
 - sh -c &amp;quot;sed -i -e s/&#039;password&#039;/&#039;&#039;/ -e s/example.com/localhost/ -e s%/home/example%$HOME% -e &#039;s%\(\$CFG.*bht\)%\n\1%&#039; config.php&amp;quot;&lt;br /&gt;
 - sh -c &amp;quot;if [ &#039;$DB&#039; = &#039;mysqli&#039; ]; then mysql -e &#039;create database moodle default character set UTF8 collate UTF8_bin;&#039;; fi&amp;quot;&lt;br /&gt;
 - sh -c &amp;quot;if [ &#039;$DB&#039; = &#039;mysqli&#039; ]; then sed -i -e s/\&#039;pgsql\&#039;/\&#039;mysqli\&#039;/ -e s/\&#039;username\&#039;/\&#039;root\&#039;/ config.php; fi&amp;quot;&lt;br /&gt;
 - sh -c &amp;quot;if [ &#039;$DB&#039; = &#039;pgsql&#039; ]; then psql -c &#039;create database moodle;&#039; -U postgres; fi&amp;quot;&lt;br /&gt;
 - sh -c &amp;quot;if [ &#039;$DB&#039; = &#039;pgsql&#039; ]; then sed -i s/\&#039;username\&#039;/\&#039;postgres\&#039;/ config.php; fi&amp;quot;&lt;br /&gt;
 - mkdir -m777 $HOME/moodledata&lt;br /&gt;
 - php admin/tool/phpunit/cli/init.php&lt;br /&gt;
 - &amp;quot;(php -S localhost:8000 &amp;amp;) 2&amp;gt; /dev/null &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
 - &amp;quot;wget http://selenium.googlecode.com/files/selenium-server-standalone-2.31.0.jar&amp;quot;&lt;br /&gt;
 - &amp;quot;(java -jar selenium-server-standalone-2.31.0.jar &amp;amp;) 2&amp;gt; /dev/null &amp;gt; /dev/null&amp;quot;&lt;br /&gt;
 - php admin/tool/behat/cli/init.php&lt;br /&gt;
script:&lt;br /&gt;
 - if [ $MOODLE_VERSION = &#039;master&#039; ]; then vendor/bin/behat --config /home/travis/bht_moodledata/behat/behat.yml --tags @auth_googleoauth2; fi&lt;br /&gt;
 - phpunit auth_googleoauth2_lib_testcase auth/googleoauth2/tests/lib_test.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Email notifications =&lt;br /&gt;
Add to https://docs.moodle.org/dev/Travis_integration#Setup when MDL-52407 is integrated and remove this note after.&lt;br /&gt;
# Email notifications will be sent by default to the committer and the commit author. If you want to turn off email notifications for this repository, you can define an environment variable with name MOODLE_EMAIL and no as value.&lt;br /&gt;
[[File:environment_variables.png|Define an environment variable]]&lt;br /&gt;
= See also =&lt;br /&gt;
[https://moodle.org/mod/forum/discuss.php?d=215998 The forum post with the original examples] from David Scotson and Jerome Mouneyrac.&lt;/div&gt;</summary>
		<author><name>Vmdef</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:environment_variables.png&amp;diff=57765</id>
		<title>File:environment variables.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:environment_variables.png&amp;diff=57765"/>
		<updated>2020-08-12T15:35:26Z</updated>

		<summary type="html">&lt;p&gt;Vmdef: Define an environment variable in Travis CI repository settings.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Define an environment variable in Travis CI repository settings.&lt;/div&gt;</summary>
		<author><name>Vmdef</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Filters&amp;diff=56427</id>
		<title>Filters</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Filters&amp;diff=56427"/>
		<updated>2019-09-09T12:39:24Z</updated>

		<summary type="html">&lt;p&gt;Vmdef: /* Giving your filter a name */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&#039;&#039;&#039;Please note:&#039;&#039;&#039; This page contains information for developers. You may prefer to read the [[:en:Filters| information about filters for teachers and administrators]].&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Filters&#039;&#039;&#039; are a way to automatically transform content before it is output. For example&lt;br /&gt;
* render embedded equations to images (the TeX filter)&lt;br /&gt;
* Links to media files can be automatically converted to an embedded applet for playing the media.&lt;br /&gt;
* Mentions of glossary terms can be automatically converted to links.&lt;br /&gt;
The possibilities are endless. There are a number of standard filters included with Moodle, or you can create your own. Filters are one of the easiest types of plugin to create. This page explains how.&lt;br /&gt;
&lt;br /&gt;
==Creating a basic filter==&lt;br /&gt;
&lt;br /&gt;
During this tutorial, we will build a simple example filter. We will make one that adds the word &#039;hello&#039; before every occurrence of the word &#039;world&#039;.&lt;br /&gt;
&lt;br /&gt;
1. Since our filter is not part of a module, we should put it inside the &#039;filter&#039; folder. Therefore, we create a directory called &#039;filter/helloworld&#039;.&lt;br /&gt;
&lt;br /&gt;
2. Inside that folder, we create a file called &#039;filter.php&#039;.&lt;br /&gt;
&lt;br /&gt;
3. Inside that PHP file, we define a class called filter_helloworld, that extends the moodle_text_filter class. (Note that the file doesn&#039;t end by closing the php section with the &#039;?&amp;gt;&#039; tag. This is standard for Moodle and is used to avoid problems with trailing whitespace.)&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
class filter_helloworld extends moodle_text_filter {&lt;br /&gt;
    // ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4. Inside that class, we have to define one method, called &#039;filter&#039;. This takes the HTML to be filtered as an argument. The method should then transform that, and return the processed text. Replace the &#039;// ...&#039; above with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class filter_helloworld extends moodle_text_filter {&lt;br /&gt;
    public function filter($text, array $options = array()) {&lt;br /&gt;
        return str_replace(&#039;world&#039;, &#039;hello world!&#039;, $text);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. version.php&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, and is required for newer moodle versions. For a full list of the attributes please see [[version.php]]. &lt;br /&gt;
Place the version.php in your &#039;filter/helloworld&#039; directory.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
$plugin-&amp;gt;version   = 2016052300;        // The current plugin version (Date: YYYYMMDDXX)&lt;br /&gt;
$plugin-&amp;gt;requires  = 2016051900;        // Requires this Moodle version&lt;br /&gt;
$plugin-&amp;gt;component = &#039;filter_helloworld&#039;; // Full name of the plugin (used for diagnostics)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
That is basically all there is to it!&lt;br /&gt;
&lt;br /&gt;
==Giving your filter a name==&lt;br /&gt;
&lt;br /&gt;
To try the new filter, you first have to log in as Administrator and enable it by going to the page Administration ► Plugins ► Filters ► Manage filters.&lt;br /&gt;
&lt;br /&gt;
When you do, you will find that your plugin does not have a name. We missed a step:&lt;br /&gt;
&lt;br /&gt;
6. Inside the &#039;filter/helloworld&#039; folder, create a folder called &#039;lang&#039;, and in there, create a folder called &#039;en&#039;.&lt;br /&gt;
&lt;br /&gt;
7. Inside there, create a file called &#039;filter_helloworld.php&#039;. That is, you have just created the file &#039;filter/helloworld/lang/en/filter_helloworld.php&#039;.&lt;br /&gt;
&lt;br /&gt;
8. In that file, put&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
$string[&#039;filtername&#039;] = &#039;Hello world!&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[String API]] for details.&lt;br /&gt;
&lt;br /&gt;
==Trying out your filter==&lt;br /&gt;
&lt;br /&gt;
We had just got to the [[Filters|filters administration screen]]. If you reload that page now, it should now show your filter with its proper name. Turn your filter on now.&lt;br /&gt;
&lt;br /&gt;
Filters are applied to all text that is printed with the [[Output functions|output functions]] format_text(), and, if you have turned on that option, format_string(). So, to see your filter in action, add some content containing the word &#039;world&#039; somewhere, for example, create a test course, and use the word in the course description. When you look at that course in the course listing, you should see that your filter has transformed it.&lt;br /&gt;
&lt;br /&gt;
==Adding a global settings screen==&lt;br /&gt;
&lt;br /&gt;
Some filters can benefit from some settings to let the administrator control how they work. Suppose we want to greet something other than &#039;world&#039;. To add global settings to the filter you need to:&lt;br /&gt;
&lt;br /&gt;
9. Create a file called &#039;filtersettings.php&#039; inside the &#039;filter/helloworld&#039; folder. Use standard &#039;settings.php&#039; file in Moodle 2.6 and later.&lt;br /&gt;
&lt;br /&gt;
10. In the &#039;filtersettings.php&#039; file, put something like:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_configtext(&#039;filter_helloworld/word&#039;,&lt;br /&gt;
        get_string(&#039;word&#039;, &#039;filter_helloworld&#039;),&lt;br /&gt;
        get_string(&#039;word_desc&#039;, &#039;filter_helloworld&#039;), &#039;world&#039;, PARAM_NOTAGS));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
11. In the language file &#039;filter/helloworld/lang/en/filter_helloworld.php&#039; add the necessary strings:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;word&#039;] = &#039;The thing to greet&#039;;&lt;br /&gt;
$string[&#039;word_desc&#039;] = &#039;The hello world filter will add the word \&#039;hello\&#039; in front of every occurrence of this word in any content.&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
12. Change the filter to use the new setting:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class filter_helloworld extends moodle_text_filter {&lt;br /&gt;
    public function filter($text, array $options = array()) {&lt;br /&gt;
        $word = get_config(&#039;filter_helloworld&#039;, &#039;word&#039;);&lt;br /&gt;
        return str_replace($word, &amp;quot;hello $word!&amp;quot;, $text);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In standard Moodle, the censor, mediaplugin and tex filters all provide good examples of of how filters use global configuration like this.&lt;br /&gt;
&lt;br /&gt;
==A note about performance==&lt;br /&gt;
&lt;br /&gt;
One important thing to remember when creating a filter is that the filter will be called to transform every bit of text output using format_text(), and possibly also format_string(). That means that you have to be careful, or you could cause big performance problems. If you have to get data out of the database, try to cache it so that you only do a fixed number of database queries per page load. The Glossary filter is an example of this. (I am not sure how good an example ;-))&lt;br /&gt;
&lt;br /&gt;
If your filter uses a special syntax or it is based on an appearance of&lt;br /&gt;
a substring in the text, it is recommend to perform a quick and cheap&lt;br /&gt;
&amp;lt;tt&amp;gt;strpos()&amp;lt;/tt&amp;gt; search first prior to executing the full regex-based search and replace.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Example of a filter that uses &amp;lt;a&amp;gt; links in some way.&lt;br /&gt;
 */&lt;br /&gt;
public function filter($text, array $options = array()) {&lt;br /&gt;
&lt;br /&gt;
    if (!is_string($text) or empty($text)) {&lt;br /&gt;
        // Non-string data can not be filtered anyway.&lt;br /&gt;
        return $text;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (stripos($text, &#039;&amp;lt;/a&amp;gt;&#039;) === false) {&lt;br /&gt;
        // Performance shortcut - if there is no &amp;lt;/a&amp;gt; tag, nothing can match.&lt;br /&gt;
        return $text;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Here we can perform some more complex operations with the &amp;lt;a&amp;gt;&lt;br /&gt;
    // links in the text.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Local configuration==&lt;br /&gt;
&lt;br /&gt;
In addition, in Moodle 2.0, filters can also have different configuration in each context. For example, the glossary filter could be changed so that in Forum A, you can choose to only link words from a particular glossary, say Glossary A, while in Forum B you choose to link words from Glossary B.&lt;br /&gt;
&lt;br /&gt;
To do that sort of thing, you need to add a file called filterlocalsettings.php. In it, you must define a [[lib/formslib.php|Moodle form]] that is a subclass of filter_local_settings_form. In addition to the standard formslib methods, you also need to define a save_changes method. There is not a good example of this in the standard Moodle install yet. To continue our example:&lt;br /&gt;
&lt;br /&gt;
13. Create a file called &#039;filterlocalsettings.php&#039; inside the &#039;filter/helloworld&#039; folder.&lt;br /&gt;
&lt;br /&gt;
14. In the &#039;filterlocalsettings.php&#039; file, put:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class helloworld_filter_local_settings_form extends filter_local_settings_form {&lt;br /&gt;
    protected function definition_inner($mform) {&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;word&#039;, get_string(&#039;word&#039;, &#039;filter_helloworld&#039;), array(&#039;size&#039; =&amp;gt; 20));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;word&#039;, PARAM_NOTAGS);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
15. Extend the filter to use the new setting, if it is present. The filter must be able to work if the setting is not set, for example by falling back to the global or default setting in this case&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
class filter_helloworld extends moodle_text_filter {&lt;br /&gt;
    public function filter($text, array $options = array()) {&lt;br /&gt;
        global $CFG;&lt;br /&gt;
        if (isset($this-&amp;gt;localconfig[&#039;word&#039;])) {&lt;br /&gt;
            $word = $this-&amp;gt;localconfig[&#039;word&#039;];&lt;br /&gt;
        } else {&lt;br /&gt;
            $word = $CFG-&amp;gt;filter_helloworld/word;&lt;br /&gt;
        }&lt;br /&gt;
        return str_replace($word, &amp;quot;hello $word!&amp;quot;, $text);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Two types of filter==&lt;br /&gt;
&lt;br /&gt;
In the past, Moodle supported two different types of filter:&lt;br /&gt;
* Stand-alone filters like the one we created above. These live in a folder inside the &#039;filter&#039; folder. For example, in &#039;filter/myfilter&#039;. &#039;filter/tex&#039; is an example of a core filter of this type.&lt;br /&gt;
* Filters that were part of an activity module. In this case, the filter code lives inside the &#039;mod/mymod&#039; folder. &#039;mod/glossary&#039; used to be an example of a core module with a filter.&lt;br /&gt;
The second option no longer exists in Moodle 2.5 and later. All filters live in the filter folder. Of course, a filter may depend on an associated other plugin, like mod_glossary. If so, you should declare that in the [[version.php]] file.&lt;br /&gt;
&lt;br /&gt;
==Dynamic content==&lt;br /&gt;
&lt;br /&gt;
From Moodle 2.7:&lt;br /&gt;
On (very few) pages - it is possible that page content is loaded by ajax *after* the page is loaded (e.g. equations in a glossary popup). In certain filter types (e.g. MathJax) javascript is required to be run on the output of the filter in order to do the final markup. For these types of filters, a javascript event is triggered when new content is added to the page (the content will have already been processed by the filter in php). The javascript for a filter can listen for these event notifications and reprocess the affected dom nodes. &lt;br /&gt;
&lt;br /&gt;
To subscribe to the event:&lt;br /&gt;
&lt;br /&gt;
        // Listen for events triggered when new text is added to a page that needs                                                  &lt;br /&gt;
        // processing by a filter.                                                                                                  &lt;br /&gt;
        Y.on(M.core.event.FILTER_CONTENT_UPDATED, this.contentUpdated, this);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To handle the event:&lt;br /&gt;
&lt;br /&gt;
    /**                                                                                                                             &lt;br /&gt;
     * Handle content updated events - typeset the new content.                                                                     &lt;br /&gt;
     * @method contentUpdated                                                                                                       &lt;br /&gt;
     * @param Y.Event - Custom event with &amp;quot;nodes&amp;quot; indicating the root of the updated nodes.                                         &lt;br /&gt;
     */                                                                                                                             &lt;br /&gt;
    contentUpdated: function(event) {                                                                                               &lt;br /&gt;
        var self = this;                                                                                                            &lt;br /&gt;
        Y.use(&#039;mathjax&#039;, function() {                                                                                               &lt;br /&gt;
            self._setLocale();                                                                                                      &lt;br /&gt;
            event.nodes.each(function (node) {                                                                                      &lt;br /&gt;
                node.all(&#039;.filter_mathjaxloader_equation&#039;).each(function(node) {                                                    &lt;br /&gt;
                    MathJax.Hub.Queue([&amp;quot;Typeset&amp;quot;, MathJax.Hub, node.getDOMNode()]);                                                 &lt;br /&gt;
                });                                                                                                                 &lt;br /&gt;
            });                                                                                                                     &lt;br /&gt;
        });                                                                                                                         &lt;br /&gt;
    }                      &lt;br /&gt;
&lt;br /&gt;
See: filter/mathjaxloader/yui/src/loader/js/loader.js&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Filters schema]] - a page containing some ideas and thoughts about modifications to the filters system&lt;br /&gt;
* [[:en:Filters]] user documentation about filters.&lt;br /&gt;
* [https://moodle.org/plugins/browse.php?list=category&amp;amp;id=7 - List of filters in the Plugins database].&lt;br /&gt;
*[https://github.com/richardjonesnz/moodle_filter_simplemodal - A simple modal filter template using AMD rather than YUI].&lt;br /&gt;
&lt;br /&gt;
[[Category:Filter]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Vmdef</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Filters&amp;diff=56426</id>
		<title>Filters</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Filters&amp;diff=56426"/>
		<updated>2019-09-09T12:35:25Z</updated>

		<summary type="html">&lt;p&gt;Vmdef: Removed the section &amp;quot;Before you start&amp;quot;. The Text cache lifetime setting doesn&amp;#039;t exist anymore. The only reference I&amp;#039;ve found is https://moodle.org/mod/forum/discuss.php?d=252426#p1140270.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&#039;&#039;&#039;Please note:&#039;&#039;&#039; This page contains information for developers. You may prefer to read the [[:en:Filters| information about filters for teachers and administrators]].&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Filters&#039;&#039;&#039; are a way to automatically transform content before it is output. For example&lt;br /&gt;
* render embedded equations to images (the TeX filter)&lt;br /&gt;
* Links to media files can be automatically converted to an embedded applet for playing the media.&lt;br /&gt;
* Mentions of glossary terms can be automatically converted to links.&lt;br /&gt;
The possibilities are endless. There are a number of standard filters included with Moodle, or you can create your own. Filters are one of the easiest types of plugin to create. This page explains how.&lt;br /&gt;
&lt;br /&gt;
==Creating a basic filter==&lt;br /&gt;
&lt;br /&gt;
During this tutorial, we will build a simple example filter. We will make one that adds the word &#039;hello&#039; before every occurrence of the word &#039;world&#039;.&lt;br /&gt;
&lt;br /&gt;
1. Since our filter is not part of a module, we should put it inside the &#039;filter&#039; folder. Therefore, we create a directory called &#039;filter/helloworld&#039;.&lt;br /&gt;
&lt;br /&gt;
2. Inside that folder, we create a file called &#039;filter.php&#039;.&lt;br /&gt;
&lt;br /&gt;
3. Inside that PHP file, we define a class called filter_helloworld, that extends the moodle_text_filter class. (Note that the file doesn&#039;t end by closing the php section with the &#039;?&amp;gt;&#039; tag. This is standard for Moodle and is used to avoid problems with trailing whitespace.)&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
class filter_helloworld extends moodle_text_filter {&lt;br /&gt;
    // ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4. Inside that class, we have to define one method, called &#039;filter&#039;. This takes the HTML to be filtered as an argument. The method should then transform that, and return the processed text. Replace the &#039;// ...&#039; above with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class filter_helloworld extends moodle_text_filter {&lt;br /&gt;
    public function filter($text, array $options = array()) {&lt;br /&gt;
        return str_replace(&#039;world&#039;, &#039;hello world!&#039;, $text);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. version.php&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, and is required for newer moodle versions. For a full list of the attributes please see [[version.php]]. &lt;br /&gt;
Place the version.php in your &#039;filter/helloworld&#039; directory.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
$plugin-&amp;gt;version   = 2016052300;        // The current plugin version (Date: YYYYMMDDXX)&lt;br /&gt;
$plugin-&amp;gt;requires  = 2016051900;        // Requires this Moodle version&lt;br /&gt;
$plugin-&amp;gt;component = &#039;filter_helloworld&#039;; // Full name of the plugin (used for diagnostics)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
That is basically all there is to it!&lt;br /&gt;
&lt;br /&gt;
==Giving your filter a name==&lt;br /&gt;
&lt;br /&gt;
To try the new filter, you first have to log in as Administrator and enable it by going to the page Administration ► Plugins ► Filters ► Manage filters.&lt;br /&gt;
&lt;br /&gt;
When you do, you will find that your plugin does not have a name. We missed a step:&lt;br /&gt;
&lt;br /&gt;
6. Inside the &#039;filter/helloworld&#039; folder, create a folder called &#039;lang&#039;, and in there, create a folder called &#039;en&#039;.&lt;br /&gt;
&lt;br /&gt;
7. Inside there, create a file called &#039;filter_helloworld.php&#039;. That is, you have just created the file &#039;filter/helloworld/lang/en/filter_helloworld.php&#039;.&lt;br /&gt;
&lt;br /&gt;
8. In that file, put&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
$string[&#039;filtername&#039;] = &#039;Hello world!&#039;;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Hello world!&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[String API]] for details.&lt;br /&gt;
&lt;br /&gt;
==Trying out your filter==&lt;br /&gt;
&lt;br /&gt;
We had just got to the [[Filters|filters administration screen]]. If you reload that page now, it should now show your filter with its proper name. Turn your filter on now.&lt;br /&gt;
&lt;br /&gt;
Filters are applied to all text that is printed with the [[Output functions|output functions]] format_text(), and, if you have turned on that option, format_string(). So, to see your filter in action, add some content containing the word &#039;world&#039; somewhere, for example, create a test course, and use the word in the course description. When you look at that course in the course listing, you should see that your filter has transformed it.&lt;br /&gt;
&lt;br /&gt;
==Adding a global settings screen==&lt;br /&gt;
&lt;br /&gt;
Some filters can benefit from some settings to let the administrator control how they work. Suppose we want to greet something other than &#039;world&#039;. To add global settings to the filter you need to:&lt;br /&gt;
&lt;br /&gt;
9. Create a file called &#039;filtersettings.php&#039; inside the &#039;filter/helloworld&#039; folder. Use standard &#039;settings.php&#039; file in Moodle 2.6 and later.&lt;br /&gt;
&lt;br /&gt;
10. In the &#039;filtersettings.php&#039; file, put something like:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_configtext(&#039;filter_helloworld/word&#039;,&lt;br /&gt;
        get_string(&#039;word&#039;, &#039;filter_helloworld&#039;),&lt;br /&gt;
        get_string(&#039;word_desc&#039;, &#039;filter_helloworld&#039;), &#039;world&#039;, PARAM_NOTAGS));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
11. In the language file &#039;filter/helloworld/lang/en/filter_helloworld.php&#039; add the necessary strings:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;word&#039;] = &#039;The thing to greet&#039;;&lt;br /&gt;
$string[&#039;word_desc&#039;] = &#039;The hello world filter will add the word \&#039;hello\&#039; in front of every occurrence of this word in any content.&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
12. Change the filter to use the new setting:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class filter_helloworld extends moodle_text_filter {&lt;br /&gt;
    public function filter($text, array $options = array()) {&lt;br /&gt;
        $word = get_config(&#039;filter_helloworld&#039;, &#039;word&#039;);&lt;br /&gt;
        return str_replace($word, &amp;quot;hello $word!&amp;quot;, $text);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In standard Moodle, the censor, mediaplugin and tex filters all provide good examples of of how filters use global configuration like this.&lt;br /&gt;
&lt;br /&gt;
==A note about performance==&lt;br /&gt;
&lt;br /&gt;
One important thing to remember when creating a filter is that the filter will be called to transform every bit of text output using format_text(), and possibly also format_string(). That means that you have to be careful, or you could cause big performance problems. If you have to get data out of the database, try to cache it so that you only do a fixed number of database queries per page load. The Glossary filter is an example of this. (I am not sure how good an example ;-))&lt;br /&gt;
&lt;br /&gt;
If your filter uses a special syntax or it is based on an appearance of&lt;br /&gt;
a substring in the text, it is recommend to perform a quick and cheap&lt;br /&gt;
&amp;lt;tt&amp;gt;strpos()&amp;lt;/tt&amp;gt; search first prior to executing the full regex-based search and replace.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Example of a filter that uses &amp;lt;a&amp;gt; links in some way.&lt;br /&gt;
 */&lt;br /&gt;
public function filter($text, array $options = array()) {&lt;br /&gt;
&lt;br /&gt;
    if (!is_string($text) or empty($text)) {&lt;br /&gt;
        // Non-string data can not be filtered anyway.&lt;br /&gt;
        return $text;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (stripos($text, &#039;&amp;lt;/a&amp;gt;&#039;) === false) {&lt;br /&gt;
        // Performance shortcut - if there is no &amp;lt;/a&amp;gt; tag, nothing can match.&lt;br /&gt;
        return $text;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Here we can perform some more complex operations with the &amp;lt;a&amp;gt;&lt;br /&gt;
    // links in the text.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Local configuration==&lt;br /&gt;
&lt;br /&gt;
In addition, in Moodle 2.0, filters can also have different configuration in each context. For example, the glossary filter could be changed so that in Forum A, you can choose to only link words from a particular glossary, say Glossary A, while in Forum B you choose to link words from Glossary B.&lt;br /&gt;
&lt;br /&gt;
To do that sort of thing, you need to add a file called filterlocalsettings.php. In it, you must define a [[lib/formslib.php|Moodle form]] that is a subclass of filter_local_settings_form. In addition to the standard formslib methods, you also need to define a save_changes method. There is not a good example of this in the standard Moodle install yet. To continue our example:&lt;br /&gt;
&lt;br /&gt;
13. Create a file called &#039;filterlocalsettings.php&#039; inside the &#039;filter/helloworld&#039; folder.&lt;br /&gt;
&lt;br /&gt;
14. In the &#039;filterlocalsettings.php&#039; file, put:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class helloworld_filter_local_settings_form extends filter_local_settings_form {&lt;br /&gt;
    protected function definition_inner($mform) {&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;word&#039;, get_string(&#039;word&#039;, &#039;filter_helloworld&#039;), array(&#039;size&#039; =&amp;gt; 20));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;word&#039;, PARAM_NOTAGS);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
15. Extend the filter to use the new setting, if it is present. The filter must be able to work if the setting is not set, for example by falling back to the global or default setting in this case&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
class filter_helloworld extends moodle_text_filter {&lt;br /&gt;
    public function filter($text, array $options = array()) {&lt;br /&gt;
        global $CFG;&lt;br /&gt;
        if (isset($this-&amp;gt;localconfig[&#039;word&#039;])) {&lt;br /&gt;
            $word = $this-&amp;gt;localconfig[&#039;word&#039;];&lt;br /&gt;
        } else {&lt;br /&gt;
            $word = $CFG-&amp;gt;filter_helloworld/word;&lt;br /&gt;
        }&lt;br /&gt;
        return str_replace($word, &amp;quot;hello $word!&amp;quot;, $text);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Two types of filter==&lt;br /&gt;
&lt;br /&gt;
In the past, Moodle supported two different types of filter:&lt;br /&gt;
* Stand-alone filters like the one we created above. These live in a folder inside the &#039;filter&#039; folder. For example, in &#039;filter/myfilter&#039;. &#039;filter/tex&#039; is an example of a core filter of this type.&lt;br /&gt;
* Filters that were part of an activity module. In this case, the filter code lives inside the &#039;mod/mymod&#039; folder. &#039;mod/glossary&#039; used to be an example of a core module with a filter.&lt;br /&gt;
The second option no longer exists in Moodle 2.5 and later. All filters live in the filter folder. Of course, a filter may depend on an associated other plugin, like mod_glossary. If so, you should declare that in the [[version.php]] file.&lt;br /&gt;
&lt;br /&gt;
==Dynamic content==&lt;br /&gt;
&lt;br /&gt;
From Moodle 2.7:&lt;br /&gt;
On (very few) pages - it is possible that page content is loaded by ajax *after* the page is loaded (e.g. equations in a glossary popup). In certain filter types (e.g. MathJax) javascript is required to be run on the output of the filter in order to do the final markup. For these types of filters, a javascript event is triggered when new content is added to the page (the content will have already been processed by the filter in php). The javascript for a filter can listen for these event notifications and reprocess the affected dom nodes. &lt;br /&gt;
&lt;br /&gt;
To subscribe to the event:&lt;br /&gt;
&lt;br /&gt;
        // Listen for events triggered when new text is added to a page that needs                                                  &lt;br /&gt;
        // processing by a filter.                                                                                                  &lt;br /&gt;
        Y.on(M.core.event.FILTER_CONTENT_UPDATED, this.contentUpdated, this);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To handle the event:&lt;br /&gt;
&lt;br /&gt;
    /**                                                                                                                             &lt;br /&gt;
     * Handle content updated events - typeset the new content.                                                                     &lt;br /&gt;
     * @method contentUpdated                                                                                                       &lt;br /&gt;
     * @param Y.Event - Custom event with &amp;quot;nodes&amp;quot; indicating the root of the updated nodes.                                         &lt;br /&gt;
     */                                                                                                                             &lt;br /&gt;
    contentUpdated: function(event) {                                                                                               &lt;br /&gt;
        var self = this;                                                                                                            &lt;br /&gt;
        Y.use(&#039;mathjax&#039;, function() {                                                                                               &lt;br /&gt;
            self._setLocale();                                                                                                      &lt;br /&gt;
            event.nodes.each(function (node) {                                                                                      &lt;br /&gt;
                node.all(&#039;.filter_mathjaxloader_equation&#039;).each(function(node) {                                                    &lt;br /&gt;
                    MathJax.Hub.Queue([&amp;quot;Typeset&amp;quot;, MathJax.Hub, node.getDOMNode()]);                                                 &lt;br /&gt;
                });                                                                                                                 &lt;br /&gt;
            });                                                                                                                     &lt;br /&gt;
        });                                                                                                                         &lt;br /&gt;
    }                      &lt;br /&gt;
&lt;br /&gt;
See: filter/mathjaxloader/yui/src/loader/js/loader.js&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Filters schema]] - a page containing some ideas and thoughts about modifications to the filters system&lt;br /&gt;
* [[:en:Filters]] user documentation about filters.&lt;br /&gt;
* [https://moodle.org/plugins/browse.php?list=category&amp;amp;id=7 - List of filters in the Plugins database].&lt;br /&gt;
*[https://github.com/richardjonesnz/moodle_filter_simplemodal - A simple modal filter template using AMD rather than YUI].&lt;br /&gt;
&lt;br /&gt;
[[Category:Filter]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Vmdef</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=XMLDB_defining_an_XML_structure&amp;diff=54844</id>
		<title>XMLDB defining an XML structure</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=XMLDB_defining_an_XML_structure&amp;diff=54844"/>
		<updated>2018-10-01T09:57:13Z</updated>

		<summary type="html">&lt;p&gt;Vmdef: /* Launching */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[XMLDB Documentation|XMLDB Documentation]] &amp;gt; [[XMLDB roadmap|Roadmap]] &amp;gt; Defining one XML structure&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Justification ==&lt;br /&gt;
&lt;br /&gt;
Before Moodle 1.7, all the DB install and upgrade was developed twice (once to handle MySQL installations and another to handle PostgreSQL installations). This approach, although working, has caused some headaches in the past, mainly because it was really difficult to keep both lines of development 100% on sync. Some developers do they work against one RDBMS and it was complex to develop to the other one (two test environments, skills on both databases, slower development cycle...). And all this was happening with &#039;&#039;only&#039;&#039; two supported RDBMS!&lt;br /&gt;
&lt;br /&gt;
One of the main objectives of Moodle 1.7 is to extend the the number of supported RDBMS to other flavours (more exactly, to Oracle and MSSQL). And the old approach (one line of development for each DB) could become an absolute nightmare. &lt;br /&gt;
&lt;br /&gt;
Because of this we have planned to build one structure to define all the DB objects used by Moodle. This structure will provide the necessary level of abstraction to be shared by all the RDBMS systems, so the &amp;quot;multiple lines of development&amp;quot; explained in the previous paragraph will be out forever, giving us one robust and well defined way to handle DB objects independently of the underlying RDBMS being used.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
&lt;br /&gt;
Initially all our best wishes were to use the [http://phplens.com/lens/adodb/docs-datadict.htm#xmlschema AdoDB XML Schema]. As Moodle is using ADOdb libraries to communicate with databases it sounded like the natural approach to solve the problem. But, finally, two reasons prevented us to use it:&lt;br /&gt;
&lt;br /&gt;
# Although working, it seems to be one feature in progress, with important changes/evolutions arriving at the time of write this document.&lt;br /&gt;
# Its lack of support for &amp;quot;prefixes&amp;quot; (one Moodle key feature, to allow multiple instances to run in the same server), would force us to create some awful tricks to generate the objects.&lt;br /&gt;
&lt;br /&gt;
So, finally, we decided to build our own XML files, with everything we need to define every object present in the DB.&lt;br /&gt;
&lt;br /&gt;
== The XMLDB editor ==&lt;br /&gt;
[[XMLDB_editor | Main article]]&lt;br /&gt;
&lt;br /&gt;
Although the XML is pretty simple to read (and to write), one of the major drawbacks was its easy and error-prone adoption by the developers. Also some problems with versioning systems getting crazy with XML files (thanks ML!) pointed us to the requirement to use one high-density format (it means, physically &#039;&#039;&#039;long lines&#039;&#039;&#039;) in our XML files. &lt;br /&gt;
&lt;br /&gt;
After some intense thoughts we decided to build one specialised editor for our XML format. This editor should be easy to use and provide support for all the objects present one Moodle DB. And it&#039;s done (and will support future enhancements easily, we hope).&lt;br /&gt;
&lt;br /&gt;
The XMLDB Editor makes the addition of tables/fields/keys/indexes practically a trivial task, allowing the developer to spend  the time coding and improving things instead of fighting against XML files and the errors caused by manual editing (of course, the developer is free to use such extra-time as desired, beers, dance, books, music...) ;-)&lt;br /&gt;
&lt;br /&gt;
All the new &#039;&#039;&#039;install.xml&#039;&#039;&#039; files, present under each &#039;&#039;&#039;db&#039;&#039;&#039; directory in Moodle can be edited (and we recommend it) with just some clicks and keystrokes. Those &#039;&#039;&#039;install.xml&#039;&#039;&#039; will contain all the info needed to generate the specific objects needed for each RDBMS supported. Obviously, such files, are the neutral replacement for all the *.sql files used until now.&lt;br /&gt;
&lt;br /&gt;
=== Launching ===&lt;br /&gt;
&lt;br /&gt;
Just login to your server as an administrator and, under the Development tab of the Administration Block, you&#039;ll see a new link pointing to the &amp;quot;XMLDB Editor&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
One &#039;&#039;&#039;important note&#039;&#039;&#039; is that, to be able to handle files properly, the web server needs write access to all those &amp;quot;db&amp;quot; directories where the &amp;quot;install.xml&amp;quot; files reside (and to the files themselves, of course). ;-)&lt;br /&gt;
&lt;br /&gt;
That&#039;s all!&lt;br /&gt;
&lt;br /&gt;
=== Use===&lt;br /&gt;
&lt;br /&gt;
We really think the XMLDB Editor is pretty easy to use, so here you won&#039;t see a complete guide to use it. We highly recommend you to play with it for a while, viewing how it works and how it modifies the &#039;&#039;&#039;install.xml&#039;&#039;&#039; files.&lt;br /&gt;
&lt;br /&gt;
It&#039;s organised in a top-botton structure, where you start &#039;&#039;&#039;loading&#039;&#039;&#039; (or &#039;&#039;&#039;creating&#039;&#039;&#039;) a new XMLDB file. Then, you can &#039;&#039;&#039;edit&#039;&#039;&#039; such file and its &#039;&#039;&#039;general structure&#039;&#039;&#039; will be showed. This structure have two type of elements, &#039;&#039;&#039;tables&#039;&#039;&#039; and &#039;&#039;&#039;statements&#039;&#039;&#039; and the XMLDB Editor allows you to &#039;&#039;&#039;add&#039;&#039;&#039;, &#039;&#039;&#039;edit&#039;&#039;&#039;, &#039;&#039;&#039;delete&#039;&#039;&#039;, and &#039;&#039;&#039;move&#039;&#039;&#039; them easily. Also, for initial creation of tables, one small but effective &#039;&#039;&#039;reverse-enginery&#039;&#039;&#039; tool has been developed (only under MySQL) allowing you to retrofit any table from the DB to the XMLDB Editor.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: If you can&#039;t click on the create links....&#039;&#039;&#039; you must first create the /db folder (as shown in the list, but it may not really exist) and then make sure it is writeable by the webserver&lt;br /&gt;
&lt;br /&gt;
While editing tables you will see their &#039;&#039;&#039;fields&#039;&#039;&#039;, &#039;&#039;&#039;keys&#039;&#039;&#039; and &#039;&#039;&#039;indexes&#039;&#039;&#039; and you&#039;ll be able to handle all them easily. Note that some fields can be no-editable. It uses to be because they are being used in some way (part of one key or index) and the idea is to warn you about that.&lt;br /&gt;
&lt;br /&gt;
Fields can be edited and you can specify their &#039;&#039;&#039;name&#039;&#039;&#039;, &#039;&#039;&#039;type&#039;&#039;&#039;, &#039;&#039;&#039;length&#039;&#039;&#039;, &#039;&#039;&#039;decimals&#039;&#039;&#039;, &#039;&#039;&#039;null-ability&#039;&#039;&#039;, &#039;&#039;&#039;defaults&#039;&#039;&#039; and so one. Exactly the same for both &#039;&#039;&#039;keys&#039;&#039;&#039; and &#039;&#039;&#039;indexes&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
While editing statements, you must think about them like &amp;quot;collections of sentences&amp;quot;. Once you select the &#039;&#039;&#039;type&#039;&#039;&#039; (only inserts are allowed for now) and &#039;&#039;&#039;table&#039;&#039;&#039; you are interested you&#039;ll be able to introduce the exact values easily, being able to &#039;&#039;&#039;duplicate&#039;&#039;&#039; them easily to gain some speed if you have a lot of sentences in your development. Sentences can be &#039;&#039;&#039;edited&#039;&#039;&#039; and &#039;&#039;&#039;deleted&#039;&#039;&#039; easily too.&lt;br /&gt;
&lt;br /&gt;
One interesting feature is that all the XMLDB Editor pages allow you to enter one &#039;&#039;&#039;comment&#039;&#039;&#039; about the item being modified (table, index, key, field, statement...). Use it at your entire needs, sure it helps other developers to understand a bit more the DB model.&lt;br /&gt;
&lt;br /&gt;
Please, don&#039;t forget to read and understand the next section, where we talk about &#039;&#039;&#039;some important guidelines&#039;&#039;&#039; to create and handle XMLDB files.&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
&lt;br /&gt;
Apart of the [[Database| Database Structures guidelines]], some more conventions should be followed:&lt;br /&gt;
&lt;br /&gt;
# About names:&lt;br /&gt;
## All lowercase names (tables, indexes, keys and fields).&lt;br /&gt;
## Table names and field names must use only a-z, 0-9 and _ chars. Table names can be at most 28 characters long; column names at most 30 characters.&lt;br /&gt;
## Key and index names under the XMLDB Files must be formed by concatenating the name of the fields present in the key/index with the &#039;&amp;quot;-&amp;quot; (minus) character.&lt;br /&gt;
## Primary key always must be named &amp;quot;primary&amp;quot; (this is one exception to the previous convention).&lt;br /&gt;
## It&#039;s highly recommended to avoid [[XMLDB_reserved_words|reserved words]] completely. We know we have some of them now but they should be completely out for next releases.&lt;br /&gt;
# About NULLS&lt;br /&gt;
## Avoid to create all the fields as NOT NULL with the &#039;&#039;silly&#039;&#039; default value &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt; (empty string). The underlying code used to create tables will handle it properly but the XMLDB structure must be REAL. Read more in the [[XMLDB_Problems#NOT_NULL_fields_using_a_DEFAULT_.27.27_clause|Problems Page]].&lt;br /&gt;
# About FOREIGN KEYS&lt;br /&gt;
## Under the tables of every XMLDB file, you must define the existing &#039;&#039;&#039;Foreign Keys&#039;&#039;&#039; (FK) properly. This will allow everybody to know a bit better the structure, allow to evolve to a better constrained system in the future and will provide the underlying code with the needed info to create the proper indexes. &lt;br /&gt;
## Note that, if you define any field combination as FK you won&#039;t have to create any index on that fields, the code will do it automatically! &lt;br /&gt;
## Respect Convention 1.3&lt;br /&gt;
# About UNIQUE KEYS&lt;br /&gt;
## Declare any fields as UNIQUE KEY (UK) only if they are going to be used as target for one FK. Create unique indexes instead.&lt;br /&gt;
## Respect Convention 1.3&lt;br /&gt;
&lt;br /&gt;
== One example: the assignment module ==&lt;br /&gt;
&lt;br /&gt;
Here we are going to examine the [http://cvs.moodle.org/moodle/mod/assignment/db/install.xml?view=markup current implementation of the XMLDB Schema for the assignment module] (a simple one). It has been completely generated with the XMLDB Editor but it&#039;s nice to know a bit more about the XML internals.&lt;br /&gt;
&lt;br /&gt;
As you can see the structure is pretty simple:&lt;br /&gt;
&lt;br /&gt;
* XMLDB&lt;br /&gt;
** TABLES, one or more, each one with&lt;br /&gt;
*** FIELDS&lt;br /&gt;
*** KEYS&lt;br /&gt;
*** INDEXES&lt;br /&gt;
** STATEMENTS, none or more, each one with&lt;br /&gt;
*** SENTENCES&lt;br /&gt;
&lt;br /&gt;
First of all you should note that all the elements contain the &#039;&#039;&#039;PREVIOUS&#039;&#039;&#039; and &#039;&#039;&#039;NEXT&#039;&#039;&#039; attributes. They allow us to keep everything ordered although it isn&#039;t meaningful at all from the RDBMS perspective. Also the &#039;&#039;&#039;COMMENT&#039;&#039;&#039; field is present everywhere to be used as desired.&lt;br /&gt;
&lt;br /&gt;
=== The TABLE element ===&lt;br /&gt;
&lt;br /&gt;
We can ignore the TABLE element, as it&#039;s simply one container for the internals (FIELDS, KEYS and INDEXES). Let&#039;s go to examine them a bit more:&lt;br /&gt;
&lt;br /&gt;
==== The FIELD element ====&lt;br /&gt;
&lt;br /&gt;
It maps with one field in the DB (obviously). For each field you can define its &#039;&#039;&#039;name&#039;&#039;&#039;, &#039;&#039;&#039;type&#039;&#039;&#039; (from a list of [[XMLDB column types|neutral types]]), &#039;&#039;&#039;length&#039;&#039;&#039;, &#039;&#039;&#039;decimals&#039;&#039;&#039; (for some types), &#039;&#039;&#039;notnull&#039;&#039;&#039; (true/false), &#039;&#039;&#039;unsigned&#039;&#039;&#039; (true/false), &#039;&#039;&#039;sequence&#039;&#039;&#039; (if it&#039;s autonumeric or serial, true/false) and &#039;&#039;&#039;default&#039;&#039;&#039; (to assign a default value).&lt;br /&gt;
&lt;br /&gt;
So, in our example, we have two tables, assignment and assignment_submissions, each one with its own fields, defining all the information related above. Please note that naming conventions are followed.&lt;br /&gt;
&lt;br /&gt;
==== The KEY element ====&lt;br /&gt;
&lt;br /&gt;
Here is where all the PRIMARY KEYS (PK), UNIQUE KEYS (UK) and FOREIGN KEYS (FK) will be defined. For each key we define its &#039;&#039;&#039;name&#039;&#039;&#039;, &#039;&#039;&#039;type&#039;&#039;&#039;, &#039;&#039;&#039;fields&#039;&#039;&#039; (that belongs to it) and optionally (if the key is one FK) the target &#039;&#039;&#039;reftable&#039;&#039;&#039; and &#039;&#039;&#039;reffields&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In our example, the assignment table has one (mandatory!) PK (called, &amp;quot;primary&amp;quot;, rules are rules) built with the &amp;quot;id&amp;quot; field. &lt;br /&gt;
&lt;br /&gt;
The other table, the &amp;quot;assignment_submissions&amp;quot; one, also has its PK (called &amp;quot;primary&amp;quot; once more) and one FK, with the field &amp;quot;assignment&amp;quot; pointing to the field &amp;quot;id&amp;quot; of the table &amp;quot;assignment&amp;quot;. Note that the FK follows the name conventions and its name is, simply, the name of the fields being part of it (&amp;quot;assignment&amp;quot;). Also, the FK has as target to one PK of the same module.&lt;br /&gt;
&lt;br /&gt;
Finally, note that there isn&#039;t any index created for all these keys. Moodle will generate them automatically when the table is created. All the keys will have their corresponding index. Point. ;-)&lt;br /&gt;
&lt;br /&gt;
==== The INDEX element ====&lt;br /&gt;
&lt;br /&gt;
Where all the indexes will be defined. For each index you can define its &#039;&#039;&#039;name&#039;&#039;&#039;, &#039;&#039;&#039;unique&#039;&#039;&#039; (true/false) and the &#039;&#039;&#039;fields&#039;&#039;&#039; (as a comma-separated string) that it comprises. Please note that naming conventions are followed.&lt;br /&gt;
&lt;br /&gt;
Also, some &amp;quot;obvious index&amp;quot;, like the one based in the &amp;quot;assignment&amp;quot; field of the &amp;quot;assignment_submissions&amp;quot; table doesn&#039;t exist. Yes, you know why: Because such column has been defined as a FK and the index will be automatically created (see previous section).&lt;br /&gt;
&lt;br /&gt;
=== The STATEMENT element ===&lt;br /&gt;
&lt;br /&gt;
This is the other &#039;&#039;&#039;big container&#039;&#039;&#039; in the XMLDB Schema (at the same level as the &#039;&#039;&#039;TABLES&#039;&#039;&#039; one) and we can define its &#039;&#039;&#039;name&#039;&#039;&#039;, &#039;&#039;&#039;type&#039;&#039;&#039; (only insert allowed for now) and &#039;&#039;&#039;table&#039;&#039;&#039; (against the sentences will be executed).&lt;br /&gt;
&lt;br /&gt;
Every statement is a collection of &#039;&#039;&#039;sentences&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
==== The SENTENCE element ====&lt;br /&gt;
&lt;br /&gt;
Each sentence implies one simple action to be performed against the DB and it can be defined as the &amp;quot;missing part of the SQL statement&amp;quot;. In our example, we have one statement, of type &amp;quot;insert&amp;quot; on table &amp;quot;log_display&amp;quot;. With this Moodle knows the initial part of the sentence, i.e:&lt;br /&gt;
&lt;br /&gt;
 INSERT INTO log_display &lt;br /&gt;
&lt;br /&gt;
and then the text will be added to create this:&lt;br /&gt;
&lt;br /&gt;
 INSERT INTO log_display &lt;br /&gt;
   (module, action, mtable, field) &lt;br /&gt;
 VALUES &lt;br /&gt;
   (&#039;assignment&#039;, &#039;view&#039;, &#039;assignment&#039;, &#039;name&#039;)&lt;br /&gt;
&lt;br /&gt;
There is one important trick when handling sentences, although they aren&#039;t in the assignment example. Take a look to the [http://cvs.moodle.org/moodle/lib/db/install.xml?view=co Core Tables XML Schema] (it&#039;s a huge one!). If you go near the end, to the statements section, you will see some sentences like this:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;SENTENCE TEXT=&amp;quot;....VALUES (&#039;user&#039;, &#039;view&#039;, &#039;user&#039;, &#039;CONCAT(firstname,&amp;quot; &amp;quot;,lastname)&#039;)&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such &amp;quot;CONCAT&amp;quot; function isn&#039;t standard at all (only MySQL supports it), but don&#039;t worry, we&#039;ll transform it to the correct concatenation operators for other RDBMS. Just be sure to use the syntax showed above.&lt;br /&gt;
&lt;br /&gt;
== DTD and XML schema ==&lt;br /&gt;
&lt;br /&gt;
Not sure if this will be usable for somebody but here you can find one [http://cvs.moodle.org/moodle/lib/xmldb/xmldb.dtd?view=co automatically generated DTD] for the XMLDB files. Also one [http://cvs.moodle.org/moodle/lib/xmldb/xmldb.xsd?view=co automatically generated XML Schema] is available. Any improvement/fix to them will be welcome!&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[XMLB List of files to create|List of files to create]]: The list of files to be created from scratch. Used to follow the progress.&lt;br /&gt;
* http://www.hitsw.com/xml_utilites/: One online XML-DTD-Schema converter.&lt;br /&gt;
&lt;br /&gt;
[[Category:XMLDB]]&lt;br /&gt;
[[Category:DB]]&lt;/div&gt;</summary>
		<author><name>Vmdef</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Deprecation&amp;diff=54508</id>
		<title>Deprecation</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Deprecation&amp;diff=54508"/>
		<updated>2018-07-11T11:03:44Z</updated>

		<summary type="html">&lt;p&gt;Vmdef: /* Step 1. Immediate action */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is deprecation? ==&lt;br /&gt;
&lt;br /&gt;
[http://en.wikipedia.org/wiki/Deprecation Deprecation], in its programming sense, is the process of taking older code and marking it as no longer being useful within the codebase, usually because it has been superseded by newer code. The deprecated code is not immediately removed from the codebase because doing so may cause regression errors.&lt;br /&gt;
&lt;br /&gt;
== Why is deprecation needed? ==&lt;br /&gt;
&lt;br /&gt;
In an open source project, the end use of the codebase varies. People may have customisations and plugins that depend on a function that has been targeted for deprecation. Rather than simply removing a function, we must gracefully deprecate the function over a period covered by a number of released versions.&lt;br /&gt;
&lt;br /&gt;
== What is Moodle&#039;s deprecation policy? ==&lt;br /&gt;
&lt;br /&gt;
* Deprecations should only be on master, not on stables (exceptions may be made for some external service integrations)&lt;br /&gt;
* Deprecations apply to all public APIs, classes, and files.&lt;br /&gt;
* Removal of a function, class, or file may only be considered after a minimum of 4 major releases since the deprecation. Example: anything deprecated in 3.2 means that it will be removed in 3.6&lt;br /&gt;
* All deprecations should emit debugging notices where possible&lt;br /&gt;
* All deprecations should be noted in the relevant upgrade.txt&lt;br /&gt;
&lt;br /&gt;
== Moodle Core deprecation process ==&lt;br /&gt;
&lt;br /&gt;
Once it is decided that a function should be deprecated, a two-step process should be followed.&lt;br /&gt;
&lt;br /&gt;
Note that both steps should always happen as earlier as possible in the 6-months period  between major releases, so all developers will have time to adjust their code and ensure it will work in the next release. Obviously, no changes will be allowed after code freeze (the APIs must remain 100% unmodified after it).&lt;br /&gt;
&lt;br /&gt;
Every deprecation should be documented in the corresponding upgrade.txt files &#039;&#039;&#039;at least&#039;&#039;&#039; once, but ideally both on initial deprecation and on final removal.&lt;br /&gt;
&lt;br /&gt;
=== Step 1. Immediate action ===&lt;br /&gt;
&lt;br /&gt;
Deprecation affects only the current master version, in other words, the deprecation only becomes effective after the next [[Releases|major release]].&lt;br /&gt;
&lt;br /&gt;
* If the function is not a member of a class (in other words, it is an independent function), it should be moved, with its PHPDoc and all comments, to &#039;&#039;lib/deprecatedlib.php&#039;&#039;, which is included everywhere. If the function is a class member, it will need to be deprecated in its current location.&lt;br /&gt;
** Deprecated behat step definitions should be moved to lib/tests/behat/behat_deprecated.php, including a call to behat_deprecated::deprecated_message() proposing an alternative to the deprecated method.&lt;br /&gt;
* A debugging message should be added to the function so that, when [[:en:Debugging|developer debugging mode]] is on, attention is drawn to the deprecation. The message should state that the function being called has been deprecated. The message should help a developer whose code currently calls the function that has gone. Tell them what they should do instead.&lt;br /&gt;
&lt;br /&gt;
 debugging(&#039;foobar() is deprecated. Please use foobar::blah() instead.&#039;, DEBUG_DEVELOPER);&lt;br /&gt;
&lt;br /&gt;
* If the deprecated function has been replaced with a new function, ideally the new function should be called from the deprecated function, so that the new functionality is used. This will make maintenance easier moving forward.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;@deprecated&amp;lt;/tt&amp;gt; tag should be added to the PHPDoc for the function description so that IDEs describing the function will note that it is deprecated, documenting which version it was deprecated in and the MDL issue associated with it. See the guidelines in [[Coding_style#.40deprecated_.28and_.40todo.29]].&lt;br /&gt;
* There will need to be an issue associated with the initial part of the deprecation. A second issue needs to be created to finish the job. The first issue will be linked to second issue. The second issue needs to be a sub-task of an appropriate [https://tracker.moodle.org/issues/?jql=%28summary%20~%20%22meta%22%20or%20type%20%3D%20Epic%29%20AND%20summary%20~%20%22together%20deprecated%22%20order%20by%20created&amp;amp;runQuery=true&amp;amp;clear=true deprecation META]. For example, if the current version is 3.1.2, the function will be marked as deprecated in 3.2 and should normally be removed for 3.6, so the second issue should be an issue in a deprecation epic for the 3.6 version (MDL-54740). This second issue should include instructions on how to remove the function so that when it comes time to do so, the task is trivial for any developer.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;@todo&amp;lt;/tt&amp;gt; tag can be added linking to the issues created for further action. (optional)&lt;br /&gt;
* A &amp;lt;tt&amp;gt;@see&amp;lt;/tt&amp;gt; tag can be added to point to the new apis that can be used. (optional)&lt;br /&gt;
* Check the body of the function being deprecated and look for additional function calls which have no other non-deprecated uses and may also be considered for deprecation. If they belong to the same code area they can be deprecated in the same issue.&lt;br /&gt;
&lt;br /&gt;
Longer deprecation periods can be considered for functions that are widely used.&lt;br /&gt;
&lt;br /&gt;
=== Step 2. Final deprecation ===&lt;br /&gt;
&lt;br /&gt;
* If a function has been marked as deprecated for 3.x (eg. 3.1) and set for removal at 3.x+4 (eg. 3.5), soon after the release of 3.x+3.1 (eg. 3.4.1), the 3.x+4 deprecation META will be processed. This means that the deprecated function will undergo final deprecation before 3.x+4, but only in the master version. This allows any potential regressions caused by the final deprecation of the function to be exposed as soon as possible.&lt;br /&gt;
* When a function undergoes final deprecation, all content of the function should be removed. In the skeleton that remains, an error statement should be included that indicates that the function cannot be used anymore. You can also direct developers to the new function(s) in this message.&lt;br /&gt;
&lt;br /&gt;
 throw new coding_exception(&#039;check_potential_filename() can not be used any more, please use new file API&#039;);&lt;br /&gt;
&lt;br /&gt;
* All function parameters should be removed&lt;br /&gt;
* The content of the PHPDoc should be removed, leaving only the &amp;lt;tt&amp;gt;@deprecated&amp;lt;/tt&amp;gt; tag with the notice and, optionally, the replacement information. This includes all &amp;lt;tt&amp;gt;@param&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;@return&amp;lt;/tt&amp;gt;, and other tags, as well as the description.&lt;br /&gt;
* Please note that previously the final deprecation was 2 versions instead of 4. For example, functions deprecated in 2.9 are throwing exceptions starting from 3.1; however functions deprecated in 3.0 will throw exception in 3.4&lt;br /&gt;
&lt;br /&gt;
== See also... ==&lt;br /&gt;
&lt;br /&gt;
* [[String deprecation]]&lt;br /&gt;
* [[Process]]&lt;br /&gt;
* [[Release process]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Processes]]&lt;br /&gt;
[[Category:Core development]]&lt;/div&gt;</summary>
		<author><name>Vmdef</name></author>
	</entry>
</feed>