<?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=Damyon</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=Damyon"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Damyon"/>
	<updated>2026-06-05T15:29:19Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=W3C_validation&amp;diff=56096</id>
		<title>W3C validation</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=W3C_validation&amp;diff=56096"/>
		<updated>2019-05-24T06:19:27Z</updated>

		<summary type="html">&lt;p&gt;Damyon: Consolidating accessibility documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
This page has been replaced because the content was no longer applicable to the current version of Moodle.&lt;br /&gt;
&lt;br /&gt;
Current documentation can be found here:&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Accessibility &amp;quot;Accessibility in Moodle&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The previous version of this document can be seen [https://docs.moodle.org/dev/index.php?title=W3C_validation&amp;amp;oldid=29805 in the history]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_Accessibility_Specification&amp;diff=56095</id>
		<title>Moodle Accessibility Specification</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_Accessibility_Specification&amp;diff=56095"/>
		<updated>2019-05-24T04:55:54Z</updated>

		<summary type="html">&lt;p&gt;Damyon: Consolidating accessibility documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
This page has been replaced because the content was no longer applicable to the current version of Moodle.&lt;br /&gt;
&lt;br /&gt;
Current documentation can be found here:&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Accessibility &amp;quot;Accessibility in Moodle&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The previous version of this document can be seen [https://docs.moodle.org/dev/index.php?title=Moodle_Accessibility_Specification&amp;amp;oldid=24832 in the history]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Aria_Guidelines&amp;diff=56094</id>
		<title>Aria Guidelines</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Aria_Guidelines&amp;diff=56094"/>
		<updated>2019-05-24T04:54:57Z</updated>

		<summary type="html">&lt;p&gt;Damyon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
This page has been replaced because the content was no longer applicable to the current version of Moodle.&lt;br /&gt;
&lt;br /&gt;
Current documentation can be found here:&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Accessibility &amp;quot;Accessibility in Moodle&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The previous version of this document can be seen [https://docs.moodle.org/dev/index.php?title=Aria_Guidelines&amp;amp;oldid=42229 in the history]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Accessibility_notes&amp;diff=56093</id>
		<title>Accessibility notes</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Accessibility_notes&amp;diff=56093"/>
		<updated>2019-05-24T04:53:37Z</updated>

		<summary type="html">&lt;p&gt;Damyon: Consolidating accessibility documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{obsolete}}&lt;br /&gt;
&lt;br /&gt;
This page has been replaced because the content was no longer applicable to the current version of Moodle.&lt;br /&gt;
&lt;br /&gt;
Current documentation can be found here:&lt;br /&gt;
&lt;br /&gt;
[https://docs.moodle.org/dev/Accessibility &amp;quot;Accessibility in Moodle&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The previous version of this document can be seen [https://docs.moodle.org/dev/index.php?title=Accessibility_notes&amp;amp;oldid=49247 in the history]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Atto&amp;diff=56092</id>
		<title>Atto</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Atto&amp;diff=56092"/>
		<updated>2019-05-24T04:04:27Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* See Also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.7}}&lt;br /&gt;
&lt;br /&gt;
Atto is a javascript text editor built specifically for Moodle. Atto is the default text editor in Moodle from 2.7 onwards.&lt;br /&gt;
&lt;br /&gt;
Atto is implemented as a standard Moodle text editor plugin ([[Editors]]). Most of the code is written in javascript as a standard Moodle YUI module. &lt;br /&gt;
&lt;br /&gt;
Follow the development of ATTO here: https://tracker.moodle.org/browse/MDL-43996&lt;br /&gt;
&lt;br /&gt;
==What does Atto mean?==&lt;br /&gt;
&lt;br /&gt;
Really really small. (10^-18). It used to be :)&lt;br /&gt;
&lt;br /&gt;
The name still ties in with some of the design concepts for Atto which is to be a simple, fast editor  users.&lt;br /&gt;
&lt;br /&gt;
==Where can I get Atto?==&lt;br /&gt;
&lt;br /&gt;
GIT - and you can check here: https://moodle.org/plugins/view.php?plugin=editor_atto&lt;br /&gt;
&lt;br /&gt;
==Atto Plugins==&lt;br /&gt;
&lt;br /&gt;
All of the buttons/menus in Atto are implemented as true Moodle subplugins. This means that the subplugins can do anything a subplugin can do including, lang strings, db tables, yui modules.&lt;br /&gt;
&lt;br /&gt;
There are a couple of extra functions/structure required for an Atto subplugin which are required in order to load a plugin on the toolbar.&lt;br /&gt;
&lt;br /&gt;
==Structure of an Atto Plugin==&lt;br /&gt;
&lt;br /&gt;
/lib.php &lt;br /&gt;
Optional. Only required if your plugin needs to implement one of the component callbacks listed below.&lt;br /&gt;
&lt;br /&gt;
/settings.php &lt;br /&gt;
Optional. Only required if your plugin wants to support custom admin settings. See: [[Admin_settings#Individual_settings]] for more info on settings. &lt;br /&gt;
&lt;br /&gt;
/version.php &lt;br /&gt;
Required. Moodle plugin version. See:[[version.php]] for more info on version files.&lt;br /&gt;
&lt;br /&gt;
/lang/en/atto_pluginname.php &lt;br /&gt;
Required. Language file. This file is required and must at least define the language string &#039;pluginname&#039;.&lt;br /&gt;
&lt;br /&gt;
/yui/src/button/&lt;br /&gt;
Required. The plugin must implement a YUI module that will be included by the editor when the page loads. That YUI module must be named &#039;button&#039; and must insert itself a class into the Y.M.&amp;lt;plugin name&amp;gt; namespace, with constructor that will be called to initialise the editor. It is recommended that you extend the EditorPlugin class as described below.&lt;br /&gt;
See: [[YUI/Modules]] for more information about YUI modules.&lt;br /&gt;
&lt;br /&gt;
==Atto subplugin Php API==&lt;br /&gt;
&lt;br /&gt;
Atto sub plugins can contain a lib.php file with 2 callbacks that will be looked for when the plugin is loaded.&lt;br /&gt;
&lt;br /&gt;
The first is &amp;quot;XXX_strings_for_js&amp;quot; (example taken from atto_table plugin):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Initialise the js strings required for this module.&lt;br /&gt;
 */&lt;br /&gt;
function atto_table_strings_for_js() {&lt;br /&gt;
    global $PAGE;&lt;br /&gt;
&lt;br /&gt;
    $PAGE-&amp;gt;requires-&amp;gt;strings_for_js(array(&#039;createtable&#039;,&lt;br /&gt;
                                          &#039;accessibilityhint&#039;,&lt;br /&gt;
                                          &#039;headers&#039;,&lt;br /&gt;
                                          &#039;caption&#039;,&lt;br /&gt;
                                          &#039;columns&#039;,&lt;br /&gt;
                                          &#039;rows&#039;,&lt;br /&gt;
                                          &#039;numberofcolumns&#039;,&lt;br /&gt;
                                          &#039;numberofrows&#039;,&lt;br /&gt;
                                          &#039;both&#039;,&lt;br /&gt;
                                          &#039;edittable&#039;,&lt;br /&gt;
                                          &#039;addcolumnafter&#039;,&lt;br /&gt;
                                          &#039;addrowafter&#039;,&lt;br /&gt;
                                          &#039;movecolumnright&#039;,&lt;br /&gt;
                                          &#039;movecolumnleft&#039;,&lt;br /&gt;
                                          &#039;moverowdown&#039;,&lt;br /&gt;
                                          &#039;moverowup&#039;,&lt;br /&gt;
                                          &#039;deleterow&#039;,&lt;br /&gt;
                                          &#039;deletecolumn&#039;),&lt;br /&gt;
                                    &#039;atto_table&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The purpose of this callback is to allow the plugin to initialise the strings that it will use in it&#039;s user interface. Note: that the pluginname string for each plugin is automatically loaded, and if this is the only string your plugin requires, then it is not necessary to implement this callback in your plugin. See: [[JavaScript_guidelines#Getting_Moodle_to_load_your_JavaScript_files]] for more information on strings_for_js.&lt;br /&gt;
&lt;br /&gt;
The second php callback that can be implemented in lib.php is: &amp;quot;XXX_params_for_js&amp;quot; (fictional example, not used in core):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Return the js params required for this module.&lt;br /&gt;
 * @return array of additional params to pass to javascript init function for this module.&lt;br /&gt;
 */&lt;br /&gt;
function atto_gambling_params_for_js() {&lt;br /&gt;
    return array(&#039;bestodds&#039; =&amp;gt; &#039;34 to 1&#039;, &#039;worstodds&#039; =&amp;gt; &#039;5 to 1&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using this second callback, you need to specify these parameters in your JavaScript source file, passing it as an argument in the constructor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    ATTRS: {&lt;br /&gt;
        bestodds: {&lt;br /&gt;
            value: &#039;&amp;lt;defaultvalue&amp;gt;&#039;&lt;br /&gt;
        },&lt;br /&gt;
        worstodds: {&lt;br /&gt;
            value: &#039;&amp;lt;defaultvalue&amp;gt;&#039;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Atto subplugin Javascript API==&lt;br /&gt;
Atto subplugins must implement a yui module named &amp;quot;moodle-atto_pluginname-button&amp;quot;.&lt;br /&gt;
This module will be automatically loaded when Atto is displayed on a page (and the subplugin is listed in the toolbar configuration).&lt;br /&gt;
&lt;br /&gt;
The plugin:&lt;br /&gt;
* &#039;&#039;&#039;must&#039;&#039;&#039; register a class at Y.M.atto_PLUGINNAME.button;&lt;br /&gt;
* &#039;&#039;&#039;must&#039;&#039;&#039; provide a constructor; and&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;should&#039;&#039;&#039;&#039;&#039; extend [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin.js Y.M.editor_atto.EditorPlugin].&lt;br /&gt;
&lt;br /&gt;
It is up to the plugin author to decide how best to write their plugin, but it is highly advisable to extend EditorPlugin class, which provides a number of useful functions for dealing with the Editor, Toolbars, Keyboard Navigation, and other related areas.&lt;br /&gt;
&lt;br /&gt;
Of particular interest are:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js#L293 addBasicButton] - to add a basic button which directly uses document.execCommand with minimal effort;&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js#L161] - to add a button giving you a greater degree of control via your own callback;&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js#L337 addToolbarMenu] - to add a dropdown toolbar menu;&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin.js#L91 markUpdated] - should be called after making changes to the content area; and&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-dialogue.js#L54 getDialogue] - return a standard dialogue, creating one if it does not already exist.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
You may also wish to take a look at some of the existing plugins for examples on how to create the different types:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/strike/yui/src/button/js/button.js A basic plugin];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/bold/yui/src/button/js/button.js A basic plugin which has a keyboard shortcuts];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/indent/yui/src/button/js/button.js A plugin with two buttons (one basic, one slightly more complex)];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/rtl/yui/src/button/js/button.js A plugin with multiple buttons which take arguments];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/title/yui/src/button/js/button.js A plugin which utilises a toolbar menu];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/image/yui/src/button/js/button.js A plugin with a dialogue]; and&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/charmap/yui/src/button/js/button.js A plugin which uses templates to build its dialogue].&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
Atto makes accessibility tools available to content authors. See https://docs.moodle.org/dev/Accessibility#Authoring_features&lt;br /&gt;
&lt;br /&gt;
Atto makes use of contenteditable regions, and the rich text editing API supported by modern browsers. See https://developer.mozilla.org/en/docs/Rich-Text_Editing_in_Mozilla for further reading.&lt;br /&gt;
&lt;br /&gt;
See the comparision (pros, cons, technical notes, missing features, etc) of Atto versus other candidate editors for Moodle 2.7 in [https://docs.moodle.org/dev/Editor_2.7 https://docs.moodle.org/dev/Editor_2.7]&lt;br /&gt;
&lt;br /&gt;
For opening dialogues it is recommended to use M.core.dialogue : https://github.com/moodle/moodle/blob/master/lib/yui/src/notification/js/dialogue.js&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Atto&amp;diff=56091</id>
		<title>Atto</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Atto&amp;diff=56091"/>
		<updated>2019-05-24T04:03:59Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* See Also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.7}}&lt;br /&gt;
&lt;br /&gt;
Atto is a javascript text editor built specifically for Moodle. Atto is the default text editor in Moodle from 2.7 onwards.&lt;br /&gt;
&lt;br /&gt;
Atto is implemented as a standard Moodle text editor plugin ([[Editors]]). Most of the code is written in javascript as a standard Moodle YUI module. &lt;br /&gt;
&lt;br /&gt;
Follow the development of ATTO here: https://tracker.moodle.org/browse/MDL-43996&lt;br /&gt;
&lt;br /&gt;
==What does Atto mean?==&lt;br /&gt;
&lt;br /&gt;
Really really small. (10^-18). It used to be :)&lt;br /&gt;
&lt;br /&gt;
The name still ties in with some of the design concepts for Atto which is to be a simple, fast editor  users.&lt;br /&gt;
&lt;br /&gt;
==Where can I get Atto?==&lt;br /&gt;
&lt;br /&gt;
GIT - and you can check here: https://moodle.org/plugins/view.php?plugin=editor_atto&lt;br /&gt;
&lt;br /&gt;
==Atto Plugins==&lt;br /&gt;
&lt;br /&gt;
All of the buttons/menus in Atto are implemented as true Moodle subplugins. This means that the subplugins can do anything a subplugin can do including, lang strings, db tables, yui modules.&lt;br /&gt;
&lt;br /&gt;
There are a couple of extra functions/structure required for an Atto subplugin which are required in order to load a plugin on the toolbar.&lt;br /&gt;
&lt;br /&gt;
==Structure of an Atto Plugin==&lt;br /&gt;
&lt;br /&gt;
/lib.php &lt;br /&gt;
Optional. Only required if your plugin needs to implement one of the component callbacks listed below.&lt;br /&gt;
&lt;br /&gt;
/settings.php &lt;br /&gt;
Optional. Only required if your plugin wants to support custom admin settings. See: [[Admin_settings#Individual_settings]] for more info on settings. &lt;br /&gt;
&lt;br /&gt;
/version.php &lt;br /&gt;
Required. Moodle plugin version. See:[[version.php]] for more info on version files.&lt;br /&gt;
&lt;br /&gt;
/lang/en/atto_pluginname.php &lt;br /&gt;
Required. Language file. This file is required and must at least define the language string &#039;pluginname&#039;.&lt;br /&gt;
&lt;br /&gt;
/yui/src/button/&lt;br /&gt;
Required. The plugin must implement a YUI module that will be included by the editor when the page loads. That YUI module must be named &#039;button&#039; and must insert itself a class into the Y.M.&amp;lt;plugin name&amp;gt; namespace, with constructor that will be called to initialise the editor. It is recommended that you extend the EditorPlugin class as described below.&lt;br /&gt;
See: [[YUI/Modules]] for more information about YUI modules.&lt;br /&gt;
&lt;br /&gt;
==Atto subplugin Php API==&lt;br /&gt;
&lt;br /&gt;
Atto sub plugins can contain a lib.php file with 2 callbacks that will be looked for when the plugin is loaded.&lt;br /&gt;
&lt;br /&gt;
The first is &amp;quot;XXX_strings_for_js&amp;quot; (example taken from atto_table plugin):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Initialise the js strings required for this module.&lt;br /&gt;
 */&lt;br /&gt;
function atto_table_strings_for_js() {&lt;br /&gt;
    global $PAGE;&lt;br /&gt;
&lt;br /&gt;
    $PAGE-&amp;gt;requires-&amp;gt;strings_for_js(array(&#039;createtable&#039;,&lt;br /&gt;
                                          &#039;accessibilityhint&#039;,&lt;br /&gt;
                                          &#039;headers&#039;,&lt;br /&gt;
                                          &#039;caption&#039;,&lt;br /&gt;
                                          &#039;columns&#039;,&lt;br /&gt;
                                          &#039;rows&#039;,&lt;br /&gt;
                                          &#039;numberofcolumns&#039;,&lt;br /&gt;
                                          &#039;numberofrows&#039;,&lt;br /&gt;
                                          &#039;both&#039;,&lt;br /&gt;
                                          &#039;edittable&#039;,&lt;br /&gt;
                                          &#039;addcolumnafter&#039;,&lt;br /&gt;
                                          &#039;addrowafter&#039;,&lt;br /&gt;
                                          &#039;movecolumnright&#039;,&lt;br /&gt;
                                          &#039;movecolumnleft&#039;,&lt;br /&gt;
                                          &#039;moverowdown&#039;,&lt;br /&gt;
                                          &#039;moverowup&#039;,&lt;br /&gt;
                                          &#039;deleterow&#039;,&lt;br /&gt;
                                          &#039;deletecolumn&#039;),&lt;br /&gt;
                                    &#039;atto_table&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The purpose of this callback is to allow the plugin to initialise the strings that it will use in it&#039;s user interface. Note: that the pluginname string for each plugin is automatically loaded, and if this is the only string your plugin requires, then it is not necessary to implement this callback in your plugin. See: [[JavaScript_guidelines#Getting_Moodle_to_load_your_JavaScript_files]] for more information on strings_for_js.&lt;br /&gt;
&lt;br /&gt;
The second php callback that can be implemented in lib.php is: &amp;quot;XXX_params_for_js&amp;quot; (fictional example, not used in core):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Return the js params required for this module.&lt;br /&gt;
 * @return array of additional params to pass to javascript init function for this module.&lt;br /&gt;
 */&lt;br /&gt;
function atto_gambling_params_for_js() {&lt;br /&gt;
    return array(&#039;bestodds&#039; =&amp;gt; &#039;34 to 1&#039;, &#039;worstodds&#039; =&amp;gt; &#039;5 to 1&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using this second callback, you need to specify these parameters in your JavaScript source file, passing it as an argument in the constructor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    ATTRS: {&lt;br /&gt;
        bestodds: {&lt;br /&gt;
            value: &#039;&amp;lt;defaultvalue&amp;gt;&#039;&lt;br /&gt;
        },&lt;br /&gt;
        worstodds: {&lt;br /&gt;
            value: &#039;&amp;lt;defaultvalue&amp;gt;&#039;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Atto subplugin Javascript API==&lt;br /&gt;
Atto subplugins must implement a yui module named &amp;quot;moodle-atto_pluginname-button&amp;quot;.&lt;br /&gt;
This module will be automatically loaded when Atto is displayed on a page (and the subplugin is listed in the toolbar configuration).&lt;br /&gt;
&lt;br /&gt;
The plugin:&lt;br /&gt;
* &#039;&#039;&#039;must&#039;&#039;&#039; register a class at Y.M.atto_PLUGINNAME.button;&lt;br /&gt;
* &#039;&#039;&#039;must&#039;&#039;&#039; provide a constructor; and&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;should&#039;&#039;&#039;&#039;&#039; extend [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin.js Y.M.editor_atto.EditorPlugin].&lt;br /&gt;
&lt;br /&gt;
It is up to the plugin author to decide how best to write their plugin, but it is highly advisable to extend EditorPlugin class, which provides a number of useful functions for dealing with the Editor, Toolbars, Keyboard Navigation, and other related areas.&lt;br /&gt;
&lt;br /&gt;
Of particular interest are:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js#L293 addBasicButton] - to add a basic button which directly uses document.execCommand with minimal effort;&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js#L161] - to add a button giving you a greater degree of control via your own callback;&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js#L337 addToolbarMenu] - to add a dropdown toolbar menu;&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin.js#L91 markUpdated] - should be called after making changes to the content area; and&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-dialogue.js#L54 getDialogue] - return a standard dialogue, creating one if it does not already exist.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
You may also wish to take a look at some of the existing plugins for examples on how to create the different types:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/strike/yui/src/button/js/button.js A basic plugin];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/bold/yui/src/button/js/button.js A basic plugin which has a keyboard shortcuts];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/indent/yui/src/button/js/button.js A plugin with two buttons (one basic, one slightly more complex)];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/rtl/yui/src/button/js/button.js A plugin with multiple buttons which take arguments];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/title/yui/src/button/js/button.js A plugin which utilises a toolbar menu];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/image/yui/src/button/js/button.js A plugin with a dialogue]; and&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/charmap/yui/src/button/js/button.js A plugin which uses templates to build its dialogue].&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
Atto makes accessibility tools available to content authors. See https://docs.moodle.org/dev/Accessibility&lt;br /&gt;
&lt;br /&gt;
Atto makes use of contenteditable regions, and the rich text editing API supported by modern browsers. See https://developer.mozilla.org/en/docs/Rich-Text_Editing_in_Mozilla for further reading.&lt;br /&gt;
&lt;br /&gt;
See the comparision (pros, cons, technical notes, missing features, etc) of Atto versus other candidate editors for Moodle 2.7 in [https://docs.moodle.org/dev/Editor_2.7 https://docs.moodle.org/dev/Editor_2.7]&lt;br /&gt;
&lt;br /&gt;
For opening dialogues it is recommended to use M.core.dialogue : https://github.com/moodle/moodle/blob/master/lib/yui/src/notification/js/dialogue.js&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Atto&amp;diff=56090</id>
		<title>Atto</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Atto&amp;diff=56090"/>
		<updated>2019-05-24T04:02:32Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Atto subplugin Javascript API */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.7}}&lt;br /&gt;
&lt;br /&gt;
Atto is a javascript text editor built specifically for Moodle. Atto is the default text editor in Moodle from 2.7 onwards.&lt;br /&gt;
&lt;br /&gt;
Atto is implemented as a standard Moodle text editor plugin ([[Editors]]). Most of the code is written in javascript as a standard Moodle YUI module. &lt;br /&gt;
&lt;br /&gt;
Follow the development of ATTO here: https://tracker.moodle.org/browse/MDL-43996&lt;br /&gt;
&lt;br /&gt;
==What does Atto mean?==&lt;br /&gt;
&lt;br /&gt;
Really really small. (10^-18). It used to be :)&lt;br /&gt;
&lt;br /&gt;
The name still ties in with some of the design concepts for Atto which is to be a simple, fast editor  users.&lt;br /&gt;
&lt;br /&gt;
==Where can I get Atto?==&lt;br /&gt;
&lt;br /&gt;
GIT - and you can check here: https://moodle.org/plugins/view.php?plugin=editor_atto&lt;br /&gt;
&lt;br /&gt;
==Atto Plugins==&lt;br /&gt;
&lt;br /&gt;
All of the buttons/menus in Atto are implemented as true Moodle subplugins. This means that the subplugins can do anything a subplugin can do including, lang strings, db tables, yui modules.&lt;br /&gt;
&lt;br /&gt;
There are a couple of extra functions/structure required for an Atto subplugin which are required in order to load a plugin on the toolbar.&lt;br /&gt;
&lt;br /&gt;
==Structure of an Atto Plugin==&lt;br /&gt;
&lt;br /&gt;
/lib.php &lt;br /&gt;
Optional. Only required if your plugin needs to implement one of the component callbacks listed below.&lt;br /&gt;
&lt;br /&gt;
/settings.php &lt;br /&gt;
Optional. Only required if your plugin wants to support custom admin settings. See: [[Admin_settings#Individual_settings]] for more info on settings. &lt;br /&gt;
&lt;br /&gt;
/version.php &lt;br /&gt;
Required. Moodle plugin version. See:[[version.php]] for more info on version files.&lt;br /&gt;
&lt;br /&gt;
/lang/en/atto_pluginname.php &lt;br /&gt;
Required. Language file. This file is required and must at least define the language string &#039;pluginname&#039;.&lt;br /&gt;
&lt;br /&gt;
/yui/src/button/&lt;br /&gt;
Required. The plugin must implement a YUI module that will be included by the editor when the page loads. That YUI module must be named &#039;button&#039; and must insert itself a class into the Y.M.&amp;lt;plugin name&amp;gt; namespace, with constructor that will be called to initialise the editor. It is recommended that you extend the EditorPlugin class as described below.&lt;br /&gt;
See: [[YUI/Modules]] for more information about YUI modules.&lt;br /&gt;
&lt;br /&gt;
==Atto subplugin Php API==&lt;br /&gt;
&lt;br /&gt;
Atto sub plugins can contain a lib.php file with 2 callbacks that will be looked for when the plugin is loaded.&lt;br /&gt;
&lt;br /&gt;
The first is &amp;quot;XXX_strings_for_js&amp;quot; (example taken from atto_table plugin):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Initialise the js strings required for this module.&lt;br /&gt;
 */&lt;br /&gt;
function atto_table_strings_for_js() {&lt;br /&gt;
    global $PAGE;&lt;br /&gt;
&lt;br /&gt;
    $PAGE-&amp;gt;requires-&amp;gt;strings_for_js(array(&#039;createtable&#039;,&lt;br /&gt;
                                          &#039;accessibilityhint&#039;,&lt;br /&gt;
                                          &#039;headers&#039;,&lt;br /&gt;
                                          &#039;caption&#039;,&lt;br /&gt;
                                          &#039;columns&#039;,&lt;br /&gt;
                                          &#039;rows&#039;,&lt;br /&gt;
                                          &#039;numberofcolumns&#039;,&lt;br /&gt;
                                          &#039;numberofrows&#039;,&lt;br /&gt;
                                          &#039;both&#039;,&lt;br /&gt;
                                          &#039;edittable&#039;,&lt;br /&gt;
                                          &#039;addcolumnafter&#039;,&lt;br /&gt;
                                          &#039;addrowafter&#039;,&lt;br /&gt;
                                          &#039;movecolumnright&#039;,&lt;br /&gt;
                                          &#039;movecolumnleft&#039;,&lt;br /&gt;
                                          &#039;moverowdown&#039;,&lt;br /&gt;
                                          &#039;moverowup&#039;,&lt;br /&gt;
                                          &#039;deleterow&#039;,&lt;br /&gt;
                                          &#039;deletecolumn&#039;),&lt;br /&gt;
                                    &#039;atto_table&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The purpose of this callback is to allow the plugin to initialise the strings that it will use in it&#039;s user interface. Note: that the pluginname string for each plugin is automatically loaded, and if this is the only string your plugin requires, then it is not necessary to implement this callback in your plugin. See: [[JavaScript_guidelines#Getting_Moodle_to_load_your_JavaScript_files]] for more information on strings_for_js.&lt;br /&gt;
&lt;br /&gt;
The second php callback that can be implemented in lib.php is: &amp;quot;XXX_params_for_js&amp;quot; (fictional example, not used in core):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Return the js params required for this module.&lt;br /&gt;
 * @return array of additional params to pass to javascript init function for this module.&lt;br /&gt;
 */&lt;br /&gt;
function atto_gambling_params_for_js() {&lt;br /&gt;
    return array(&#039;bestodds&#039; =&amp;gt; &#039;34 to 1&#039;, &#039;worstodds&#039; =&amp;gt; &#039;5 to 1&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using this second callback, you need to specify these parameters in your JavaScript source file, passing it as an argument in the constructor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    ATTRS: {&lt;br /&gt;
        bestodds: {&lt;br /&gt;
            value: &#039;&amp;lt;defaultvalue&amp;gt;&#039;&lt;br /&gt;
        },&lt;br /&gt;
        worstodds: {&lt;br /&gt;
            value: &#039;&amp;lt;defaultvalue&amp;gt;&#039;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Atto subplugin Javascript API==&lt;br /&gt;
Atto subplugins must implement a yui module named &amp;quot;moodle-atto_pluginname-button&amp;quot;.&lt;br /&gt;
This module will be automatically loaded when Atto is displayed on a page (and the subplugin is listed in the toolbar configuration).&lt;br /&gt;
&lt;br /&gt;
The plugin:&lt;br /&gt;
* &#039;&#039;&#039;must&#039;&#039;&#039; register a class at Y.M.atto_PLUGINNAME.button;&lt;br /&gt;
* &#039;&#039;&#039;must&#039;&#039;&#039; provide a constructor; and&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;should&#039;&#039;&#039;&#039;&#039; extend [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin.js Y.M.editor_atto.EditorPlugin].&lt;br /&gt;
&lt;br /&gt;
It is up to the plugin author to decide how best to write their plugin, but it is highly advisable to extend EditorPlugin class, which provides a number of useful functions for dealing with the Editor, Toolbars, Keyboard Navigation, and other related areas.&lt;br /&gt;
&lt;br /&gt;
Of particular interest are:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js#L293 addBasicButton] - to add a basic button which directly uses document.execCommand with minimal effort;&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js#L161] - to add a button giving you a greater degree of control via your own callback;&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js#L337 addToolbarMenu] - to add a dropdown toolbar menu;&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin.js#L91 markUpdated] - should be called after making changes to the content area; and&lt;br /&gt;
* [https://github.com/moodle/moodle/blob/MOODLE_37_STABLE/lib/editor/atto/yui/src/editor/js/editor-plugin-dialogue.js#L54 getDialogue] - return a standard dialogue, creating one if it does not already exist.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
You may also wish to take a look at some of the existing plugins for examples on how to create the different types:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/strike/yui/src/button/js/button.js A basic plugin];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/bold/yui/src/button/js/button.js A basic plugin which has a keyboard shortcuts];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/indent/yui/src/button/js/button.js A plugin with two buttons (one basic, one slightly more complex)];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/rtl/yui/src/button/js/button.js A plugin with multiple buttons which take arguments];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/title/yui/src/button/js/button.js A plugin which utilises a toolbar menu];&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/image/yui/src/button/js/button.js A plugin with a dialogue]; and&lt;br /&gt;
* [https://github.com/moodle/moodle/tree/master/lib/editor/atto/plugins/charmap/yui/src/button/js/button.js A plugin which uses templates to build its dialogue].&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
Atto makes use of contenteditable regions, and the rich text editing API supported by modern browsers. See https://developer.mozilla.org/en/docs/Rich-Text_Editing_in_Mozilla for further reading.&lt;br /&gt;
&lt;br /&gt;
See the comparision (pros, cons, technical notes, missing features, etc) of Atto versus other candidate editors for Moodle 2.7 in [https://docs.moodle.org/dev/Editor_2.7 https://docs.moodle.org/dev/Editor_2.7]&lt;br /&gt;
&lt;br /&gt;
For opening dialogues it is recommended to use M.core.dialogue : https://github.com/moodle/moodle/blob/master/lib/yui/src/notification/js/dialogue.js&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Accessibility&amp;diff=56089</id>
		<title>Accessibility</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Accessibility&amp;diff=56089"/>
		<updated>2019-05-24T02:26:36Z</updated>

		<summary type="html">&lt;p&gt;Damyon: This change is intended as a major revision of https://docs.moodle.org/dev/Accessibility. Some considerations are: only link to standards documents (not opinions), examples link to an W3C Aria page, Moodle Accessibility Collaboration Group retained&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle is designed to provide equal functionality and information to all people. This means that there should be no barriers for people regardless of disabilities, assistive technologies that are used, different screen sizes and different input devices (e.g. mouse, keyboard and touchscreen). &lt;br /&gt;
&lt;br /&gt;
== Moodle Accessibility Collaboration Group ==&lt;br /&gt;
&lt;br /&gt;
To improve the accessibility and usability of Moodle, we have established this collaboration group to work together with Moodle developers, accessibility experts, administrators, IT professionals, and other interested entities and individuals. We welcome anyone who is interested in improving the accessibility of Moodle to join this group. You don’t need to be a technical guru or accessibility expert to join; however, it is expected that you are familiar with the basics of accessibility and are willing to dedicate a few hours each month to this collaboration effort.&lt;br /&gt;
&lt;br /&gt;
This group meets once a month to discuss accessibility priorities, typically on the first Monday of each month.&lt;br /&gt;
&lt;br /&gt;
Visit http://collaborate.athenpro.org/group/moodle to join the email list.&lt;br /&gt;
&lt;br /&gt;
To review past meetings or to see upcoming meetings visit http://collaborate.athenpro.org/group/moodle/teleconferences/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Authoring features ==&lt;br /&gt;
&lt;br /&gt;
Moodle can be used by users to author content for other users. In some cases, accessibility features have been added to the authoring tools so that the content that is produced is as accessible as possible. An example is the “Atto text editor” which includes an “Accessibility checker” and an “Accessibility helper” which provide additional information for content authors on the accessibility of their content (like checks for sufficient contrast). The equations produced by the MathJax content filter have full accessibility enabled so they can be passed directly to the screen reader as maths content. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Coding standards ==&lt;br /&gt;
&lt;br /&gt;
All components in Moodle need to be available to use by all users. Accessibility needs to be part of the design of every new feature in Moodle.&lt;br /&gt;
&lt;br /&gt;
For simple features with no requirement for an advanced user interface, simple adherence to standard HTML5 does provide an accessible feature. In this case, it is better to use no ARIA than it would be to use it incorrectly ([https://www.w3.org/TR/wai-aria-practices/#no_aria_better_bad_aria W3C no Aria]). &lt;br /&gt;
&lt;br /&gt;
Bootstrap and Bootstrap components [https://getbootstrap.com/docs/4.0/getting-started/accessibility/#color-contrast do not support accessibility by default] and all features implemented with Bootstrap need to be checked and enhanced where necessary. The Boost theme contains an “aria” javascript module that does add accessibility to some default Bootstrap features (menus).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Colours ===&lt;br /&gt;
&lt;br /&gt;
All text that is presented needs to be displayed in a colour with sufficient contrast to its background colour so that the text is legible for all users. The foreground and background colours should meet the [https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html WCAG requirement for contrast], which varies depending on the size of the text. This can be tested with the [https://wave.webaim.org/ WebAIM Web Accessibility Evaluation Tool]. &lt;br /&gt;
&lt;br /&gt;
Additionally, colour alone cannot be used to imply meaning. An example of a failure for this would be to display error messages in “red” with no other information to convey that this is an error message. &lt;br /&gt;
&lt;br /&gt;
[https://www.w3.org/TR/WCAG21/#use-of-color WCAG use of colour]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Icons ===&lt;br /&gt;
&lt;br /&gt;
Icons (Images) can be displayed in a variety of ways, and the correct use of icons will depend on the context in which they are used. &lt;br /&gt;
&lt;br /&gt;
[https://www.w3.org/TR/WCAG21/#text-alternatives WCAG requirement for text alternatives]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Solitary Icons ====&lt;br /&gt;
&lt;br /&gt;
Icons displayed on their own, as part of a link or as informative content must include accessible text to convey the meaning of the icon. For an image tag, this can be the “alt” attribute for the image tag. It can be valid to include both the “alt” attribute and the “title” attribute (shown when hovering with the mouse) so that all users can access the textual meaning of the icon. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Icons and Text ====&lt;br /&gt;
&lt;br /&gt;
When an icon is displayed immediately before or after some text that also describes the meaning of the icon, it is redundant to repeat the same text twice. In this case, it is correct to hide the icon from screen readers by setting the “role” attribute to “presentation” or hiding it with the “aria-hidden” attribute set to “true”.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Multiple icons ====&lt;br /&gt;
&lt;br /&gt;
When multiple icons are displayed in a row as links, it is important that each icon is large enough and has sufficient space around it so the icon can be easily clicked with the mouse. &lt;br /&gt;
&lt;br /&gt;
The minimum valid size for a link target is 44 by 44 pixels.&lt;br /&gt;
&lt;br /&gt;
[https://www.w3.org/TR/WCAG21/#target-size WCAG requirement for target size]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Keyboard Support ===&lt;br /&gt;
&lt;br /&gt;
All components should be entirely operable through a keyboard-only interface. &lt;br /&gt;
&lt;br /&gt;
[https://www.w3.org/TR/WCAG21/#keyboard-accessible WCAG requirement for keyboard accessibility]&lt;br /&gt;
&lt;br /&gt;
Some important things to consider is that all components should be focusable with the keyboard (available in the tab sequence), and should allow the focus to be moved away using only the keyboard. &lt;br /&gt;
&lt;br /&gt;
The element that currently has focus should have a visual focus indicator. [https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_discernable_predictable ARIA focus management].&lt;br /&gt;
&lt;br /&gt;
In some cases, a single component can contain many smaller components. In order to not pollute the page tab sequence, the parent element can exist in the tab sequence once and should maintain focus within its smaller components with arrow key navigation (roving tabindex or active descendant). [https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_general_within ARIA keyboard navigation inside components]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Forms ===&lt;br /&gt;
&lt;br /&gt;
Moodle forms created with the standard forms library are designed to be accessible. Any custom (e.g. javascript) form or custom form elements must also be accessible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*   All form elements must have a label&lt;br /&gt;
*   The form must be able to be completed entirely with the keyboard&lt;br /&gt;
*   Invalid entries in the form fields should be indicated with the “aria-invalid” attribute set to “true”&lt;br /&gt;
*   Warning messages for invalid form fields should be associated with the invalid field using the “aria-describedby” attribute. &lt;br /&gt;
&lt;br /&gt;
[https://www.w3.org/TR/WCAG21/#error-identification WCAG error identification]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Presentation Only ===&lt;br /&gt;
&lt;br /&gt;
Any component that contains no information or functionality that is not provided by other components on the page can be considered decorative only. Content that meets this description can be hidden from screen readers using a suitable technique (aria-hidden or presentation role).&lt;br /&gt;
&lt;br /&gt;
[https://www.w3.org/TR/WCAG21/#dfn-pure-decoration WCAG pure decoration]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Landmark regions ===&lt;br /&gt;
&lt;br /&gt;
The layout of each page of content should be separated into valid regions where each region has a unique label and the correct landmark role. This is typically done in the layout files of the theme. &lt;br /&gt;
&lt;br /&gt;
[https://www.w3.org/TR/wai-aria-practices-1.1/#aria_landmark ARIA landmarks]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Page Titles ===&lt;br /&gt;
&lt;br /&gt;
All pages should have a unique title that describes the current page.&lt;br /&gt;
&lt;br /&gt;
[https://www.w3.org/TR/WCAG21/#page-titled WCAG page titled]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Advanced UX Widgets ===&lt;br /&gt;
&lt;br /&gt;
When it is determined that an advanced interface is required (typically one that relies on javascript), a minimum set of principles need to be applied to make sure that the feature “provides equal functionality and information to all people”. Each use case is different, but a minimum set of things to be checked are:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*   Does this component work entirely when accessed only via the keyboard?&lt;br /&gt;
*   Does this component map to any widget from the [https://www.w3.org/TR/wai-aria-practices-1.1/ ARIA Authoring Practices] document and if so, does it implement all of the “Keyboard Interaction” and “WAI-ARIA Roles, States and Properties” listed for that widget?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External Resources ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*   [https://www.w3.org/WAI/standards-guidelines/ W3C Accessibility Standards Overview]&lt;br /&gt;
*   [https://www.w3.org/TR/wai-aria-1.1/ Accessible Rich Internet Applications (WAI-ARIA) 1.1]&lt;br /&gt;
*   [https://www.w3.org/TR/wai-aria-practices/ WAI-ARIA Authoring Practices 1.1]&lt;br /&gt;
*   [https://www.w3.org/TR/WCAG21/ Web Content Accessibility Guidelines (WCAG) 2.1]&lt;br /&gt;
*   [https://www.w3.org/TR/ATAG20/ Authoring Tool Accessibility Guidelines (ATAG) 2.0]&lt;br /&gt;
*   [https://www.w3.org/TR/UAAG20/ User Agent Accessibility Guidelines (UAAG) 2.0]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Accessibility Tools ==&lt;br /&gt;
&lt;br /&gt;
Moodle officially supports the following screen reader/browser configurations:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*   Microsoft Edge, Jaws 15+ (Latest version recommended)&lt;br /&gt;
*   Mozilla Firefox, NVDA 2014.1+ (Latest version recommended)&lt;br /&gt;
&lt;br /&gt;
Screen readers:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*   [https://www.nvaccess.org/ NVDA Screen Reader] (Windows)&lt;br /&gt;
*   [http://www.freedomscientific.com/ JAWS Screen Reader] (Windows)&lt;br /&gt;
*   [http://www.chromevox.com/ Chromevox Screen Reader ] (Linux, Chrome OS, Windows, Mac OS X)&lt;br /&gt;
*   [https://help.gnome.org/users/orca/stable/ Orca Screen Reader] (Linux)&lt;br /&gt;
&lt;br /&gt;
Accessibility tools:&lt;br /&gt;
&lt;br /&gt;
*   [https://wave.webaim.org/extension/ WebAIM Web Accessibility Evaluation Tool] (Chrome, Firefox)&lt;br /&gt;
*   [https://developers.google.com/web/tools/chrome-devtools/accessibility/reference Chrome Accessibility Dev Tools] (Chrome)&lt;br /&gt;
*   [http://www.w3.org/WAI/ER/tools/complete W3C Accessibility Tool Listing]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== International Legislation ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== USA ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*   [http://www.section508.gov/ Section 508]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== UK ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*   [http://www.legislation.gov.uk/ukpga/2010/15/contents Equality Act 2010]&lt;br /&gt;
*   [http://www.equalityhumanrights.com/advice-and-guidance/public-sector-equality-duty/ Public sector equality duty]&lt;br /&gt;
*   [http://www.parliament.the-stationery-office.co.uk/pa/ld200001/ldbills/003/2001003.htm SENDA - Special Educational Needs and Disability Act/Bill]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 === Germany ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*   [http://www.einfach-fuer-alle.de/artikel/bitv/ Barrierefreie Informationstechnik-Verordnung - BITV]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== France ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*   [https://references.modernisation.gouv.fr/rgaa-accessibilite/ Référentiel Général d’Accessibilité des Administrations - RGAA]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 === European Union ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*   [https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=COM:2015:0615:FIN European Accessibility Act]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=MForm_Modal&amp;diff=55857</id>
		<title>MForm Modal</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=MForm_Modal&amp;diff=55857"/>
		<updated>2019-04-01T03:13:47Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Step 2 - Add a new AMD module to show the modal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Advanced tutorial: MForm in a modal ==&lt;br /&gt;
&lt;br /&gt;
{{Note| This tutorial is for advanced Moodle devs. You need to know a lot of APIs in order to understand all of this. See the list of related pages at the end of this tutorial for some of them. }}&lt;br /&gt;
&lt;br /&gt;
This is a walkthrough of the steps required to convert an existing page in moodle with an mform - to an mform that displays in a popup and submits data via AJAX.&lt;br /&gt;
&lt;br /&gt;
If you want to get all the code in this walkthrough - here is the link to the branch on github: https://github.com/damyon/moodle/tree/MFORM_AJAX&lt;br /&gt;
&lt;br /&gt;
Lets get started - first lets pick a page (spins a wheel)..... &amp;quot;Create a group&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We will modify the &amp;quot;Create group&amp;quot; button on the groups page to open a modal with the create a group form, instead of directing you to a new page. Whether this is actually a useful improvement or not does not really matter for now - we are just trying to show how to do it.&lt;br /&gt;
&lt;br /&gt;
=== Step 1 - Attach some javascript to the button ===&lt;br /&gt;
&lt;br /&gt;
The first step is to add some javascript to the &amp;quot;Create group&amp;quot; button so that we can open a modal. The page we are modifying is group/index.php which we get by visiting the page and checking the url. If we read through that page, we can see it uses a renderable to generate the HTML for the page. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$renderable = new \core_group\output\index_page($courseid, $groupoptions, $selectedname, $members, $disableaddedit, $disabledelete, &lt;br /&gt;
              $preventgroupremoval);                                                                                                      &lt;br /&gt;
&lt;br /&gt;
$output = $PAGE-&amp;gt;get_renderer(&#039;core_group&#039;);                                                                                        &lt;br /&gt;
echo $output-&amp;gt;render($renderable);         &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The renderer is in group/classes/output/renderer.php and the renderable is in group/classes/output/index_page.php (see [[Automatic_class_loading]]) for how we worked that out. &lt;br /&gt;
&lt;br /&gt;
Looking at the render_index_page function of the renderer (see https://docs.moodle.org/dev/Output_renderers) we can see that this renderer uses [[Templates]] to separate the HTML from the php (good).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function render_index_page(index_page $page) {                                                                           &lt;br /&gt;
    $data = $page-&amp;gt;export_for_template($this);                                                                                  &lt;br /&gt;
    return parent::render_from_template(&#039;core_group/index&#039;, $data);                                                             &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of the template is &amp;quot;core_group/index&amp;quot;. This maps to a mustache template located at group/templates/index.mustache.&lt;br /&gt;
&lt;br /&gt;
Hooray - we found the HTML we want to modify to add our javascript.&lt;br /&gt;
&lt;br /&gt;
This template already has a {{#js}} block we can use to add our custom javascript. We don&#039;t want to code all the javascript in a mustache template - we will just add the minimal code to call a new AMD module for creating a group.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
{{#js}}                                                                                                                             &lt;br /&gt;
    require([&#039;jquery&#039;, &#039;core/yui&#039;], function($) {                                                                                   &lt;br /&gt;
        $(&amp;quot;#groups&amp;quot;).change(function() {                                                                                            &lt;br /&gt;
            M.core_group.membersCombo.refreshMembers();                                                                             &lt;br /&gt;
        });                                                                                                                         &lt;br /&gt;
        M.core_group.init_index(Y, &amp;quot;{{wwwroot}}&amp;quot;, {{courseid}});                                                                    &lt;br /&gt;
        var undeletableGroups = JSON.parse(&#039;{{{undeletablegroups}}}&#039;);                                                              &lt;br /&gt;
        M.core_group.groupslist(Y, undeletableGroups);                                                                              &lt;br /&gt;
    });                                                                                                                             &lt;br /&gt;
&lt;br /&gt;
    // New code to create groups in a modal.                                                                                        &lt;br /&gt;
    require([&#039;core_group/newgroup&#039;], function(NewGroup) {                                                                           &lt;br /&gt;
        NewGroup.init(&#039;[data-action=creategroupmodal]&#039;, {{contextid}});                                                                            &lt;br /&gt;
    });&lt;br /&gt;
{{/js}}   &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We added contextid to the template (We always need a contextid to use the fragments API) but it&#039;s not in the context for the template yet. We need to add it to the export_for_template function for the renderable group/classes/output/index_page.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $context = context_course::instance($this-&amp;gt;courseid);&lt;br /&gt;
 $data-&amp;gt;contextid = $context-&amp;gt;id;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We added that code at the end to call the core_group/newgroup AMD module. The argument we will pass to this new module is a &amp;quot;selector&amp;quot; which is a flexible way to allow this same module to be used on other pages with different markup. In this case for the selector, we are looking for a node with a data attribute. We also need to modify the create group button to contain this data-attribute. In general data-attributes are a great way to add hooks to the DOM that are used for Javascript, but should not affect the appearance (unlike classes which are just gross and disgusting).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;act_showcreateorphangroupform&amp;quot; id=&amp;quot;showcreateorphangroupform&amp;quot; data-action=&amp;quot;creategroupmodal&amp;quot; value=&amp;quot;{{#str}}creategroup, group{{/str}}&amp;quot; class=&amp;quot;btn btn-default&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 2 - Add a new AMD module to show the modal ===&lt;br /&gt;
&lt;br /&gt;
So we tried to load an AMD module &amp;quot;core_group/newgroup&amp;quot; but it doesn&#039;t exist yet. Time to create it.&lt;br /&gt;
&lt;br /&gt;
Make a new folder at group/amd/src. &amp;quot;group&amp;quot; in this case is the directory for the core_group component, so amd modules for this component go in amd/src relative to that directory. When we run [[Grunt]] it will build the javascript to group/amd/build. &lt;br /&gt;
&lt;br /&gt;
Make a new file in this group/amd/src folder named &amp;quot;newgroup.js&amp;quot;. This will be our new javascript module. It exports a single function &amp;quot;init&amp;quot; which attaches event listeners to the elements that match the selector. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Add a create new group modal to the page.&lt;br /&gt;
 *&lt;br /&gt;
 * @module     core_group/newgroup&lt;br /&gt;
 * @class      NewGroup&lt;br /&gt;
 * @package    core_group&lt;br /&gt;
 * @copyright  2017 Damyon Wiese &amp;lt;damyon@moodle.com&amp;gt;&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
define([&#039;jquery&#039;, &#039;core/str&#039;, &#039;core/modal_factory&#039;, &#039;core/modal_events&#039;, &#039;core/fragment&#039;, &#039;core/ajax&#039;, &#039;core/yui&#039;],&lt;br /&gt;
        function($, Str, ModalFactory, ModalEvents, Fragment, Ajax, Y) {&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Constructor&lt;br /&gt;
     *&lt;br /&gt;
     * @param {String} selector used to find triggers for the new group modal.&lt;br /&gt;
     * @param {int} contextid&lt;br /&gt;
     *&lt;br /&gt;
     * Each call to init gets it&#039;s own instance of this class.&lt;br /&gt;
     */&lt;br /&gt;
    var NewGroup = function(selector, contextid) {&lt;br /&gt;
        this.contextid = contextid;&lt;br /&gt;
        this.init(selector);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * @var {Modal} modal&lt;br /&gt;
     * @private&lt;br /&gt;
     */&lt;br /&gt;
    NewGroup.prototype.modal = null;&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * @var {int} contextid&lt;br /&gt;
     * @private&lt;br /&gt;
     */&lt;br /&gt;
    NewGroup.prototype.contextid = -1;&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Initialise the class.&lt;br /&gt;
     *&lt;br /&gt;
     * @param {String} selector used to find triggers for the new group modal.&lt;br /&gt;
     * @private&lt;br /&gt;
     * @return {Promise}&lt;br /&gt;
     */&lt;br /&gt;
    NewGroup.prototype.init = function(selector) {&lt;br /&gt;
        var triggers = $(selector);&lt;br /&gt;
        // Fetch the title string.&lt;br /&gt;
        return Str.get_string(&#039;creategroup&#039;, &#039;core_group&#039;).then(function(title) {&lt;br /&gt;
            // Create the modal.&lt;br /&gt;
            return ModalFactory.create({&lt;br /&gt;
                type: ModalFactory.types.SAVE_CANCEL,&lt;br /&gt;
                title: title,&lt;br /&gt;
                body: this.getBody()&lt;br /&gt;
            }, triggers);&lt;br /&gt;
        }.bind(this)).then(function(modal) {&lt;br /&gt;
            // Keep a reference to the modal.&lt;br /&gt;
            this.modal = modal;&lt;br /&gt;
&lt;br /&gt;
            // Forms are big, we want a big modal.&lt;br /&gt;
            this.modal.setLarge();&lt;br /&gt;
&lt;br /&gt;
            // We want to reset the form every time it is opened.&lt;br /&gt;
            this.modal.getRoot().on(ModalEvents.hidden, function() {&lt;br /&gt;
                this.modal.setBody(this.getBody());&lt;br /&gt;
            }.bind(this));&lt;br /&gt;
&lt;br /&gt;
            // We want to hide the submit buttons every time it is opened.&lt;br /&gt;
            this.modal.getRoot().on(ModalEvents.shown, function() {&lt;br /&gt;
                this.modal.getRoot().append(&#039;&amp;lt;style&amp;gt;[data-fieldtype=submit] { display: none ! important; }&amp;lt;/style&amp;gt;&#039;);&lt;br /&gt;
            }.bind(this));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            // We catch the modal save event, and use it to submit the form inside the modal.&lt;br /&gt;
            // Triggering a form submission will give JS validation scripts a chance to check for errors.&lt;br /&gt;
            this.modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));&lt;br /&gt;
            // We also catch the form submit event and use it to submit the form with ajax.&lt;br /&gt;
            this.modal.getRoot().on(&#039;submit&#039;, &#039;form&#039;, this.submitFormAjax.bind(this));&lt;br /&gt;
&lt;br /&gt;
            return this.modal;&lt;br /&gt;
        }.bind(this));&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * @method getBody&lt;br /&gt;
     * @private&lt;br /&gt;
     * @return {Promise}&lt;br /&gt;
     */&lt;br /&gt;
    NewGroup.prototype.getBody = function(formdata) {&lt;br /&gt;
        if (typeof formdata === &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
            formdata = {};&lt;br /&gt;
        }&lt;br /&gt;
        // Get the content of the modal.&lt;br /&gt;
        var params = {jsonformdata: JSON.stringify(formdata)};&lt;br /&gt;
        return Fragment.loadFragment(&#039;core_group&#039;, &#039;new_group_form&#039;, this.contextid, params);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * @method handleFormSubmissionResponse&lt;br /&gt;
     * @private&lt;br /&gt;
     * @return {Promise}&lt;br /&gt;
     */&lt;br /&gt;
    NewGroup.prototype.handleFormSubmissionResponse = function() {&lt;br /&gt;
        this.modal.hide();&lt;br /&gt;
        // We could trigger an event instead.&lt;br /&gt;
        // Yuk.&lt;br /&gt;
        Y.use(&#039;moodle-core-formchangechecker&#039;, function() {&lt;br /&gt;
            M.core_formchangechecker.reset_form_dirty_state();&lt;br /&gt;
        });&lt;br /&gt;
        document.location.reload();&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * @method handleFormSubmissionFailure&lt;br /&gt;
     * @private&lt;br /&gt;
     * @return {Promise}&lt;br /&gt;
     */&lt;br /&gt;
    NewGroup.prototype.handleFormSubmissionFailure = function(data) {&lt;br /&gt;
        // Oh noes! Epic fail :(&lt;br /&gt;
        // Ah wait - this is normal. We need to re-display the form with errors!&lt;br /&gt;
        this.modal.setBody(this.getBody(data));&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Private method&lt;br /&gt;
     *&lt;br /&gt;
     * @method submitFormAjax&lt;br /&gt;
     * @private&lt;br /&gt;
     * @param {Event} e Form submission event.&lt;br /&gt;
     */&lt;br /&gt;
    NewGroup.prototype.submitFormAjax = function(e) {&lt;br /&gt;
        // We don&#039;t want to do a real form submission.&lt;br /&gt;
        e.preventDefault();&lt;br /&gt;
&lt;br /&gt;
        var changeEvent = document.createEvent(&#039;HTMLEvents&#039;);&lt;br /&gt;
       changeEvent.initEvent(&#039;change&#039;, true, true);&lt;br /&gt;
&lt;br /&gt;
       // Prompt all inputs to run their validation functions.&lt;br /&gt;
       // Normally this would happen when the form is submitted, but&lt;br /&gt;
       // since we aren&#039;t submitting the form normally we need to run client side&lt;br /&gt;
       // validation.&lt;br /&gt;
       this.modal.getRoot().find(&#039;:input&#039;).each(function(index, element) {&lt;br /&gt;
           element.dispatchEvent(changeEvent);&lt;br /&gt;
       });&lt;br /&gt;
&lt;br /&gt;
       // Now the change events have run, see if there are any &amp;quot;invalid&amp;quot; form fields.&lt;br /&gt;
       var invalid = $.merge(&lt;br /&gt;
           this.modal.getRoot().find(&#039;[aria-invalid=&amp;quot;true&amp;quot;]&#039;),&lt;br /&gt;
           this.modal.getRoot().find(&#039;.error&#039;)&lt;br /&gt;
       );&lt;br /&gt;
&lt;br /&gt;
       // If we found invalid fields, focus on the first one and do not submit via ajax.&lt;br /&gt;
       if (invalid.length) {&lt;br /&gt;
           invalid.first().focus();&lt;br /&gt;
           return;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
        // Convert all the form elements values to a serialised string.&lt;br /&gt;
        var formData = this.modal.getRoot().find(&#039;form&#039;).serialize();&lt;br /&gt;
&lt;br /&gt;
        // Now we can continue...&lt;br /&gt;
        Ajax.call([{&lt;br /&gt;
            methodname: &#039;core_group_submit_create_group_form&#039;,&lt;br /&gt;
            args: {contextid: this.contextid, jsonformdata: JSON.stringify(formData)},&lt;br /&gt;
            done: this.handleFormSubmissionResponse.bind(this, formData),&lt;br /&gt;
            fail: this.handleFormSubmissionFailure.bind(this, formData)&lt;br /&gt;
        }]);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.&lt;br /&gt;
     *&lt;br /&gt;
     * @method submitForm&lt;br /&gt;
     * @param {Event} e Form submission event.&lt;br /&gt;
     * @private&lt;br /&gt;
     */&lt;br /&gt;
    NewGroup.prototype.submitForm = function(e) {&lt;br /&gt;
        e.preventDefault();&lt;br /&gt;
        this.modal.getRoot().find(&#039;form&#039;).submit();&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    return /** @alias module:core_group/newgroup */ {&lt;br /&gt;
        // Public variables and functions.&lt;br /&gt;
        /**&lt;br /&gt;
         * Attach event listeners to initialise this module.&lt;br /&gt;
         *&lt;br /&gt;
         * @method init&lt;br /&gt;
         * @param {string} selector The CSS selector used to find nodes that will trigger this module.&lt;br /&gt;
         * @param {int} contextid The contextid for the course.&lt;br /&gt;
         * @return {Promise}&lt;br /&gt;
         */&lt;br /&gt;
        init: function(selector, contextid) {&lt;br /&gt;
            return new NewGroup(selector, contextid);&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some things to note: This is the standard boilerplate for an AMD module that only returns a list of functions (in this case one function named &amp;quot;init&amp;quot;). Everything else is private to the module. There is a bunch of code here but the main parts are:&lt;br /&gt;
&lt;br /&gt;
a) opening the modal&lt;br /&gt;
b) using the fragment api to load the body of the modal&lt;br /&gt;
c) catching the submit from the form so we can do something else with it&lt;br /&gt;
&lt;br /&gt;
=== Step 3 - Add a callback for the fragments API to load the form ===&lt;br /&gt;
&lt;br /&gt;
In the JS above we load the fragment for new_group_form from the core_group component. We need to add a callback to the core_group component that renders this fragment. This is a new global function in group/lib.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Serve the new group form as a fragment.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array $args List of named arguments for the fragment loader.&lt;br /&gt;
 * @return string&lt;br /&gt;
 */&lt;br /&gt;
function core_group_output_fragment_new_group_form($args) {&lt;br /&gt;
    global $CFG;&lt;br /&gt;
&lt;br /&gt;
    require_once($CFG-&amp;gt;dirroot . &#039;/group/group_form.php&#039;);&lt;br /&gt;
    $args = (object) $args;&lt;br /&gt;
    $context = $args-&amp;gt;context;&lt;br /&gt;
    $o = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    $formdata = [];&lt;br /&gt;
    if (!empty($args-&amp;gt;jsonformdata)) {&lt;br /&gt;
        $serialiseddata = json_decode($args-&amp;gt;jsonformdata);&lt;br /&gt;
        parse_str($serialiseddata, $formdata);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    list($ignored, $course) = get_context_info_array($context-&amp;gt;id);&lt;br /&gt;
    $group = new stdClass();&lt;br /&gt;
    $group-&amp;gt;courseid = $course-&amp;gt;id;&lt;br /&gt;
&lt;br /&gt;
    require_capability(&#039;moodle/course:managegroups&#039;, $context);&lt;br /&gt;
    $editoroptions = [&lt;br /&gt;
        &#039;maxfiles&#039; =&amp;gt; EDITOR_UNLIMITED_FILES,&lt;br /&gt;
        &#039;maxbytes&#039; =&amp;gt; $course-&amp;gt;maxbytes,&lt;br /&gt;
        &#039;trust&#039; =&amp;gt; false,&lt;br /&gt;
        &#039;context&#039; =&amp;gt; $context,&lt;br /&gt;
        &#039;noclean&#039; =&amp;gt; true,&lt;br /&gt;
        &#039;subdirs&#039; =&amp;gt; false&lt;br /&gt;
    ];&lt;br /&gt;
    $group = file_prepare_standard_editor($group, &#039;description&#039;, $editoroptions, $context, &#039;group&#039;, &#039;description&#039;, null);&lt;br /&gt;
&lt;br /&gt;
    $mform = new group_form(null, array(&#039;editoroptions&#039; =&amp;gt; $editoroptions), &#039;post&#039;, &#039;&#039;, null, true, $formdata);&lt;br /&gt;
    // Used to set the courseid.&lt;br /&gt;
    $mform-&amp;gt;set_data($group);&lt;br /&gt;
&lt;br /&gt;
    if (!empty($args-&amp;gt;jsonformdata)) {&lt;br /&gt;
        // If we were passed non-empty form data we want the mform to call validation functions and show errors.&lt;br /&gt;
        $mform-&amp;gt;is_validated();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    ob_start();&lt;br /&gt;
    $mform-&amp;gt;display();&lt;br /&gt;
    $o .= ob_get_contents();&lt;br /&gt;
    ob_end_clean();&lt;br /&gt;
&lt;br /&gt;
    return $o;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this code is the same as in group/group.php to build the mform. Note we accept a parameter which is the json encoded form data so we can pass it to the mform constructor. This is normally done by mforms parsing data from GET and POST params, but when we are in an ajax script we need to explicitly set the data like this. We also need to call is_validated() so the mform will render with error messages if this is required.&lt;br /&gt;
&lt;br /&gt;
=== Step 4 - Add a webservice function to handle the form submission ===&lt;br /&gt;
We need to add a new webservice function to handle our ajax form submission. This is webservice is different to a normal one in that the list of parameters are accepted in one json encoded blob, rather than separated and validated properly. This is because we want the mform to perform the validation for us.&lt;br /&gt;
&lt;br /&gt;
group/externallib.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
     * Describes the parameters for submit_create_group_form webservice.&lt;br /&gt;
     * @return external_function_parameters&lt;br /&gt;
     */&lt;br /&gt;
    public static function submit_create_group_form_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
            array(&lt;br /&gt;
                &#039;contextid&#039; =&amp;gt; new external_value(PARAM_INT, &#039;The context id for the course&#039;),&lt;br /&gt;
                &#039;jsonformdata&#039; =&amp;gt; new external_value(PARAM_RAW, &#039;The data from the create group form, encoded as a json array&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Submit the create group form.&lt;br /&gt;
     *&lt;br /&gt;
     * @param int $contextid The context id for the course.&lt;br /&gt;
     * @param string $jsonformdata The data from the form, encoded as a json array.&lt;br /&gt;
     * @return int new group id.&lt;br /&gt;
     */&lt;br /&gt;
    public static function submit_create_group_form($contextid, $jsonformdata) {&lt;br /&gt;
        global $CFG, $USER;&lt;br /&gt;
&lt;br /&gt;
        require_once($CFG-&amp;gt;dirroot . &#039;/group/lib.php&#039;);&lt;br /&gt;
        require_once($CFG-&amp;gt;dirroot . &#039;/group/group_form.php&#039;);&lt;br /&gt;
&lt;br /&gt;
        // We always must pass webservice params through validate_parameters.&lt;br /&gt;
        $params = self::validate_parameters(self::submit_create_group_form_parameters(),&lt;br /&gt;
                                            [&#039;contextid&#039; =&amp;gt; $contextid, &#039;jsonformdata&#039; =&amp;gt; $jsonformdata]);&lt;br /&gt;
&lt;br /&gt;
        $context = context::instance_by_id($params[&#039;contextid&#039;], MUST_EXIST);&lt;br /&gt;
&lt;br /&gt;
        // We always must call validate_context in a webservice.&lt;br /&gt;
        self::validate_context($context);&lt;br /&gt;
        require_capability(&#039;moodle/course:managegroups&#039;, $context);&lt;br /&gt;
&lt;br /&gt;
        list($ignored, $course) = get_context_info_array($context-&amp;gt;id);&lt;br /&gt;
        $serialiseddata = json_decode($params[&#039;jsonformdata&#039;]);&lt;br /&gt;
&lt;br /&gt;
        $data = array();&lt;br /&gt;
        parse_str($serialiseddata, $data);&lt;br /&gt;
&lt;br /&gt;
        $warnings = array();&lt;br /&gt;
&lt;br /&gt;
        $editoroptions = [&lt;br /&gt;
            &#039;maxfiles&#039; =&amp;gt; EDITOR_UNLIMITED_FILES,&lt;br /&gt;
            &#039;maxbytes&#039; =&amp;gt; $course-&amp;gt;maxbytes,&lt;br /&gt;
            &#039;trust&#039; =&amp;gt; false,&lt;br /&gt;
            &#039;context&#039; =&amp;gt; $context,&lt;br /&gt;
            &#039;noclean&#039; =&amp;gt; true,&lt;br /&gt;
            &#039;subdirs&#039; =&amp;gt; false&lt;br /&gt;
        ];&lt;br /&gt;
        $group = new stdClass();&lt;br /&gt;
        $group-&amp;gt;courseid = $course-&amp;gt;id;&lt;br /&gt;
        $group = file_prepare_standard_editor($group, &#039;description&#039;, $editoroptions, $context, &#039;group&#039;, &#039;description&#039;, null);&lt;br /&gt;
&lt;br /&gt;
        // The last param is the ajax submitted data.&lt;br /&gt;
        $mform = new group_form(null, array(&#039;editoroptions&#039; =&amp;gt; $editoroptions), &#039;post&#039;, &#039;&#039;, null, true, $data);&lt;br /&gt;
&lt;br /&gt;
        $validateddata = $mform-&amp;gt;get_data();&lt;br /&gt;
&lt;br /&gt;
        if ($validateddata) {&lt;br /&gt;
            // Do the action.&lt;br /&gt;
            $groupid = groups_create_group($validateddata, $mform, $editoroptions);&lt;br /&gt;
        } else {&lt;br /&gt;
            // Generate a warning.&lt;br /&gt;
            throw new moodle_exception(&#039;erroreditgroup&#039;, &#039;group&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return $groupid;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Returns description of method result value.&lt;br /&gt;
     *&lt;br /&gt;
     * @return external_description&lt;br /&gt;
     * @since Moodle 3.0&lt;br /&gt;
     */&lt;br /&gt;
    public static function submit_create_group_form_returns() {&lt;br /&gt;
        return new external_value(PARAM_INT, &#039;group id&#039;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also need to add the webservice to lib/db/services.php and bump the moodle version number.&lt;br /&gt;
&lt;br /&gt;
lib/db/services.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
  &#039;core_group_submit_create_group_form&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;classname&#039; =&amp;gt; &#039;core_group_external&#039;,&lt;br /&gt;
        &#039;methodname&#039; =&amp;gt; &#039;submit_create_group_form&#039;,&lt;br /&gt;
        &#039;classpath&#039; =&amp;gt; &#039;group/externallib.php&#039;,&lt;br /&gt;
        &#039;description&#039; =&amp;gt; &#039;Creates a group from submitted form data&#039;,&lt;br /&gt;
        &#039;ajax&#039; =&amp;gt; true,&lt;br /&gt;
        &#039;type&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;capabilities&#039; =&amp;gt; &#039;moodle/course:managegroups&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
This shows a working example of displaying an mform in a modal with server side validation. It was a bit messy and fiddly with quite a few things that can catch you out - but there are benefits too - we re-used an existing mform with all it&#039;s validation logic and mform elements including a text editor, file manager and password field. This will work for auto-complete fields and other advanced fields too.&lt;br /&gt;
&lt;br /&gt;
=== Related APIs ===&lt;br /&gt;
* [[Javascript_Modules]]&lt;br /&gt;
* [[Form_API]]&lt;br /&gt;
* [[AJAX]]&lt;br /&gt;
* [[Web_services_API]]&lt;br /&gt;
* [[Fragment]]&lt;br /&gt;
* [[Templates]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Prototypes&amp;diff=55704</id>
		<title>Prototypes</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Prototypes&amp;diff=55704"/>
		<updated>2019-03-14T03:57:43Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Prototype for Badgr.io */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is where Moodle HQ shares early work on new features that will be included in coming versions of Moodle.&lt;br /&gt;
For an overview of new features please see the [[Roadmap]] page.&lt;br /&gt;
&lt;br /&gt;
We use it to show features currently in development so that people can try them and provide feedback.&lt;br /&gt;
&lt;br /&gt;
Feel free to explore the sites, but as we are seeking feedback, please follow instructions for each prototype and be prepared to participate in forum discussions and surveys.&lt;br /&gt;
&lt;br /&gt;
You can provide feedback in the [https://moodle.org/mod/forum/view.php?id=55 general developer forum] or the [https://moodle.org/mod/forum/view.php?id=8052 future major features forum].&lt;br /&gt;
&lt;br /&gt;
Thank you for helping us help you.&lt;br /&gt;
&lt;br /&gt;
==Prototypes for Moodle 3.7 features==&lt;br /&gt;
Each prototype site has a short summary of the project, with a status update and login details.&lt;br /&gt;
&lt;br /&gt;
===Forum update===&lt;br /&gt;
This project is collaborative project with and sponsored by the [https://moodleassociation.org/ Moodle User Association].&lt;br /&gt;
&lt;br /&gt;
The scope for Moodle 3.7 includes:&lt;br /&gt;
* Forum to use mustache templates&lt;br /&gt;
* Accessibility improvements&lt;br /&gt;
* In-page reply to posts in a discussion&lt;br /&gt;
* In-page creation of discussions&lt;br /&gt;
* Ability to Star/Favourite a discussion&lt;br /&gt;
* Ability to manually lock a discussion&lt;br /&gt;
* Ability to sort the list of discussions in a number of ways&lt;br /&gt;
* Ability to reply privately to a post.&lt;br /&gt;
&lt;br /&gt;
[https://forum.moodledemo.net Forum prototype site]&lt;br /&gt;
&lt;br /&gt;
===Badges support for Open Badges 2.0===&lt;br /&gt;
This project is an upgrade to the backpack support for Badges so that Badges can be shared with a backpack that is compliant with the Open Badges v2.0 specification. This will allow publishing of Badges to a Badgr backpack. Badgr backpacks are taking over from Mozilla Open Badges.&lt;br /&gt;
&lt;br /&gt;
The scope of this feature for Moodle 3.7 includes:&lt;br /&gt;
* [https://badgr.io Badgr] backpack support&lt;br /&gt;
* Upgrades for exiting connections to Mozilla Open Badges&lt;br /&gt;
* Moodle Competencies can be selected as a criteria for a Badge&lt;br /&gt;
&lt;br /&gt;
[https://backpack.moodledemo.net Badgr backpack prototype site]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53528</id>
		<title>Peer reviewing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53528"/>
		<updated>2017-12-18T08:55:56Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Sanity check */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Process=&lt;br /&gt;
&lt;br /&gt;
Peer review process helps to prepare the issue for integration. The peer reviewer is another developer who was not involved in the development process on the issue and therefore can take a fresh look and notice something that original developer might have forgotten during development. It is important to check that the bug actually is present and the code fixes it without creating new regressions. &lt;br /&gt;
&lt;br /&gt;
==Completing Peer review as a community member==&lt;br /&gt;
&lt;br /&gt;
Any other developer can review any change. That is why it is called &#039;peer&#039; review. However, not everyone has the necessary permissions in the tracker to click the buttons &#039;Start peer review&#039;, &#039;Finish peer review&#039; etc. This should not discourage you from looking at other contributors code and providing comments and feedback. The issue will still need to wait for someone with the right permissions to come along and click the buttons, but they can read your review and then need do no more than double-check some points, which will save a lot of time.&lt;br /&gt;
&lt;br /&gt;
To provide feedback to the developer, leave the issue in &amp;quot;Waiting for Peer Review&amp;quot; (since you don&#039;t have permission to do anything else, and also that makes it easy for someone with sufficient permissions to find the issue and move it forwards). Review the code using the checklist below, including any appropriate comments.  Once finished, please post a comment clearly stating the outcome of your review.  If you think it needs more work then indicate what needs to be changes.  If you are happy with the patch, leave a clear comment that you believe this is ready to be made part of Moodle.  This can then easily be seen by a HQ developer or component lead and they can quickly take appropriate action.&lt;br /&gt;
&lt;br /&gt;
If a followup review happens to identify something you did not find, you have an opportunity to expand your knowledge and provide better reviews in the future as well as having saved everybody else some time.&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue is ready to progress might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks again for your contribution. I have reviewed the patch:&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I don&#039;t have permission to use the peer review buttons on this issue. I hope that someone with sufficient permissions will move the issue forwards soon.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue requires further work might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch. I think the following points require further work&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Please indicate If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Peer review for development by HQ or a known common contributor==&lt;br /&gt;
&lt;br /&gt;
When code comes from a HQ developer or external developer who has been contributing significantly to Moodle and is well acquainted with Moodle standards, peer review is limited to checking the code according to the Checklist below. &lt;br /&gt;
&lt;br /&gt;
If everything is fine, the peer reviewer submits the issue for integration. &lt;br /&gt;
&lt;br /&gt;
If some additional work is needed or the author specifically asked not to submit for integration yet, the peer reviewer clicks on “Finish peer review” and the issue state returns to “Development in progress”. Usually the name of the peer reviewer stays on the issue and if a second peer review is requested it is expected that the same Peer reviewer picks it up. If the peer reviewer is not able to do the second review, they should remove their name and comment about it. Otherwise the issue does not appear on “waiting for peer review” dashboard. Please remember that not all jira users have permission to submit for integration.&lt;br /&gt;
&lt;br /&gt;
==Peer review for external developers==&lt;br /&gt;
&lt;br /&gt;
When the code has come from an external developer, the peer reviewer will also help the developer to lead the issue to integration. In this case the peer reviewer should not use “Finish peer review” button. &lt;br /&gt;
&lt;br /&gt;
If the issue needs additional work, the peer reviewer comments about the suggested changes but does not change the status of the issue and it remains as “Peer review in progress”. If the author of the patch does not reply in 4 days, the peer reviewer may select either to complete the patch themselves or reopen the issue. The decision should be based on the amount of work required to complete the solution, for example, changing coding style or commit message, rebasing, backporting, adding testing instructions, etc. should be performed by the peer reviewer. This may require picking the commits into reviewer’s git branch. &lt;br /&gt;
&lt;br /&gt;
It is very important to give the credit to the author of the code by either keeping their authorship on the commit or adding “Thanks to XXXX for providing the patch” to the commit message. If the author of the patch is not in jira-developers group the special user &#039;moodle.com&#039; should be entered in Assignee field.&lt;br /&gt;
&lt;br /&gt;
There could be situations when the patch is incomplete, does not fix the original issue, creates regressions or otherwise is not correct. As stated above, the peer reviewer should comment about it and wait for the feedback from the author. If there is no feedback, or the author can not work on this issue any more, and the peer reviewer also does not find it easy and important enough to complete, the issue needs to be reopened. Button “Fail peer review” (available to HQ developers only) will reset the issue status to “Reopened”. On this screen peer reviewer should remove assignee, peer reviewer and “patch” label from the issue. This way issue will become available again for anybody who want to work on it. All communication will remain in comments and issue history.&lt;br /&gt;
&lt;br /&gt;
If the issue has passed peer review but the integrator or tester has raised some questions about it, then normally the developer who created the patch would be expected to respond. If they do no respond quickly enough, then the peer reviewer is expected to step in and take responsibility for the change they reviewed.&lt;br /&gt;
&lt;br /&gt;
Once the issue is ready for integration, you can submit it to integration on behalf of the developer. Most external developers (those who are not in the jira-developers group) do not have permission to submit their own issues to integration so cannot do it themselves.&lt;br /&gt;
&lt;br /&gt;
==Replies templates==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
I have reviewed your code and can confirm that it addresses the reported issue. We would like to include it in core. Moodle values its contributors and tries to give them credit when possible. If you are interested in your name appearing on the https://moodle.org/dev/contributions.php page you can create a git commit that we will then pull into Moodle. You can learn more about Git and how Moodle uses it at &amp;lt;nowiki&amp;gt;[Git for developers|https://docs.moodle.org/dev/Git_for_developers]&amp;lt;/nowiki&amp;gt; page. Please let me know if you want to prepare a git branch. Or if you don’t have time to go through the whole process at the moment I can pick your patch myself.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Your code looks almost ready for integration into Moodle. There are just some little things that need to be changed to comply with Moodle standards. Can you please take a look at the review results below and tell me if you are able to modify your branch to address them.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
I have reviewed your patch, it addresses the problem and complies with Moodle standards. I&#039;m pushing this issue for integration. Following Moodle &amp;lt;nowiki&amp;gt;[Process|https://docs.moodle.org/dev/Process]&amp;lt;/nowiki&amp;gt; it will go through integration review and testing before being included in the product. There might be additional questions from an integrator and/or a tester at those stages. It would be appreciated if you read tracker emails and can reply to questions if needed. If everything goes well during the next two stages your issue will be included in the next weekly release and your count on https://moodle.org/dev/contributions.php page will increase.&amp;lt;br/&amp;gt;&lt;br /&gt;
Thanks again for your contribution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Unfortunately this patch does not fully address the reported issue. ... DETAILS...&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Even though the code does solve the issue in the short-term it is very likely to create regressions ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
I have spent some time reviewing the patch and I would recommend that you ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Please let me know If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Checklist=&lt;br /&gt;
&lt;br /&gt;
These are points to consider while peer-reviewing issues. Further explanation below.&lt;br /&gt;
&lt;br /&gt;
 [] Syntax&lt;br /&gt;
 [] Output&lt;br /&gt;
 [] Language&lt;br /&gt;
 [] Databases&lt;br /&gt;
 [] Testing (instructions and automated tests)&lt;br /&gt;
 [] Security&lt;br /&gt;
 [] Performance and Clustering&lt;br /&gt;
 [] Documentation&lt;br /&gt;
 [] Git&lt;br /&gt;
 [] Third party code&lt;br /&gt;
 [] Sanity check&lt;br /&gt;
 [] Icons&lt;br /&gt;
&lt;br /&gt;
Acceptable check-marks are Y (for yes), N (for no) or - (for not applicable). All N check-marks should be accompanied by an explanation of the problem that still needs to be addressed.&lt;br /&gt;
&lt;br /&gt;
==Syntax==&lt;br /&gt;
To allow the community of Moodle developers to work together, conventions should be followed.&lt;br /&gt;
&lt;br /&gt;
* The code is easy to understand and, where it isn&#039;t, comments have been provided.&lt;br /&gt;
* Variables are named correctly (all lower case, no camel-case, no underscores).&lt;br /&gt;
* Functions are named correctly (all lower case, no camel-case, underscores allowed).&lt;br /&gt;
* PHP DocBlocks have been updated and adhere to [[Coding_style#Documentation_and_comments|coding style guide]].&lt;br /&gt;
* Where functions are being removed, the [[Deprecation]] process is followed.&lt;br /&gt;
* The code doesn&#039;t use [[Deprecated_functions_in_2.0|deprecated functions]].&lt;br /&gt;
* $_GET, $_POST, $_REQUEST, $_COOKIE, and $_SESSION are never used.&lt;br /&gt;
&lt;br /&gt;
See the [[Coding style]] guide for details.&lt;br /&gt;
&lt;br /&gt;
==Output==&lt;br /&gt;
Output needs to be controlled by renderers to achieve consistency and correct application of themes.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* output renders are used to generate output strings, including HTML tags;&lt;br /&gt;
* HTML output is valid XHTML;&lt;br /&gt;
* no inline styles have been used in HTML output (everything has to be in CSS);&lt;br /&gt;
* CSS has been added to the appropriate CSS files (base, specific area, sometimes canvas); and&lt;br /&gt;
* the code doesn&#039;t use buffered output unless absolutely necessary.&lt;br /&gt;
* all visual output has a RTL alternative included&lt;br /&gt;
&lt;br /&gt;
feedback any notices (E_STRICT, etc) seen into the MDL.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
To achieve appropriate internationalisation of Moodle, language strings must be managed correctly.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* new language strings are named correctly (all lower case, no camel-case, underscores are permissible in some cases);&lt;br /&gt;
* help strings are named and formatted as described in [[Help strings]];&lt;br /&gt;
* language strings are used instead of hard-coded strings for text output;&lt;br /&gt;
* language strings have not been removed or renamed, had their meaning changed or had their parameters changed in stable branches (permitted only in master); and&lt;br /&gt;
* [https://docs.moodle.org/dev/Commit_cheat_sheet#Include_AMOS_script_in_the_commit_if_needed AMOS commands]  have been specified when moving or copying language strings.&lt;br /&gt;
&lt;br /&gt;
==Databases==&lt;br /&gt;
DB calls are the greatest performance bottleneck in Moodle.&lt;br /&gt;
&lt;br /&gt;
If there is SQL code you can test quickly then do so. &lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are minimal DB calls (no excessive use of the DB); and&lt;br /&gt;
* the code uses SQL compatible with all the supported DB engines (check all selected fields appear in an &#039;order by&#039; clause).&lt;br /&gt;
&lt;br /&gt;
==Testing instructions and automated tests==&lt;br /&gt;
It is the developer&#039;s responsibility to test code before integration. Issues should not be sent for peer review without tests so that the peer reviewer can assess their quality and use them to consider the scope of the issue.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are specific testing instructions that state how, as well as what, to test. Please ensure that the testing instructions are in the correct format: [https://docs.moodle.org/dev/Behat Behat gherkin];&lt;br /&gt;
* the assignee has tested according to the instructions and verified that they are passing (This is the responsibility of the assignee, not the peer reviewer)&lt;br /&gt;
* new unit tests have been added when there is a change in functionality; and&lt;br /&gt;
* &#039;&#039;&#039;unit tests pass&#039;&#039;&#039; for related areas where changes have been made.&lt;br /&gt;
* &#039;&#039;&#039;Behat tests pass&#039;&#039;&#039; for related areas where changes have been made, especially when it involved UI changes.&lt;br /&gt;
&lt;br /&gt;
==Security==&lt;br /&gt;
The user community relies on Moodle being responsibly secure.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* user login is checked where an identity is needed;&lt;br /&gt;
* sesskey values are checked before all write actions where appropriate (some read actions as well);&lt;br /&gt;
* capabilities are checked where roles differ; and&lt;br /&gt;
* if the issue itself is a [[Security|security]] issue, the [[Process#Security_issues|security process]] is being followed.&lt;br /&gt;
** Ensure that the fix is &#039;&#039;&#039;not&#039;&#039;&#039; available in a public repository (ie. a personal Github account); stand-alone patches should be provided instead.&lt;br /&gt;
** The issue will not be integrated until just before the next minor version release.&lt;br /&gt;
&lt;br /&gt;
==Performance and clustering==&lt;br /&gt;
It is easy to write code that works sufficiently well when you are working on either small sets of data or with a small number of active users.  Picking performance issues can be quite difficult and can required a complex level of understanding of both the section of code being reviewed, but also other parts that interact with it.&lt;br /&gt;
&lt;br /&gt;
Clustering is when the same code is run on different computers and an end user could send each request to a different computer.  This can produce a number of concurrency issues if not thought through.  One example is;  If you complete an opcache_reset(), no other server except the one you ran it on knows that it happened.  So data can get out of sync.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Any filesystem, database or cache accesses are done in the most efficient way.&lt;br /&gt;
* That any code or function that appear expensive are not in critical paths.  eg; They don&#039;t load on every page.&lt;br /&gt;
* The least possible code is running to complete the task, especially looking for hidden loops.  They can appear from calling functions.&lt;br /&gt;
* Any code that runs is not specific to a single node. (eg opcache_reset())  The ensures clusters will run correctly.&lt;br /&gt;
* If the code could affect performance at all, make sure there is a comment noting what was considered.&lt;br /&gt;
** What they did to mitigate performance impact, or why they thought it wasn&#039;t an issue.&lt;br /&gt;
** Why they made certain trade-offs.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
Work does not stop when code is integrated.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Appropriate [[Tracker_issue_labels|labels]] have been added when there has been a function change, particularly&lt;br /&gt;
** docs_required (any functional change, usually paired with ui_change),&lt;br /&gt;
** dev_docs_required (any change to APIs, usually paired with api_change),&lt;br /&gt;
** ui_change (any functional change, usually paired with docs_required, except ui_change remains permanetly),&lt;br /&gt;
** api_change (any change to APIs that devs will need to know about, usually paired with dev_docs_required, except api_change remains permanetly),&lt;br /&gt;
** unit_test_required and acceptance_test_required, when there are api or ui changes needing improved coverage, and&lt;br /&gt;
** qa_test_required (significant functional change, not covered by unit/acceptance ones).&lt;br /&gt;
* Also, verify that the components for the issue are correctly set, so maintainers (subscribed by default) will be mailed about issues early in the process.&lt;br /&gt;
&lt;br /&gt;
==Git==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the commit matches the [[Coding style#Git_commits|Coding style]]&lt;br /&gt;
* the Git history is clean and the work has been rebased to logical commits; and&lt;br /&gt;
* the original author of the work provided as a patch has been given credit within the commit (as author of in the commit message if changes were made).&lt;br /&gt;
&lt;br /&gt;
==Third party code==&lt;br /&gt;
Does the change contain third party code? If so, ensure that:&lt;br /&gt;
&lt;br /&gt;
* The code is licensed under a [http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses| GPL compatible license].&lt;br /&gt;
* The instructions for upgrading/importing the library and contained within a readme_moodle.txt file.&lt;br /&gt;
* The library is recorded in a thirdparty.xml file, including licensing information.&lt;br /&gt;
* Third party code has been scanned to check for url accessible entry points that could be exploited. These should either be disabled, or if required functionality they should be checked for security weaknesses.&lt;br /&gt;
* Does not duplicate the functionality of any existing api or third party library in core.&lt;br /&gt;
* Any modifications to third party code are recorded in readme_moodle.txt&lt;br /&gt;
&lt;br /&gt;
==Sanity check==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the code seems to solve the described problem completely within its reported scope (and further issues have been created to resolve remaining parts or further refactoring);&lt;br /&gt;
* the code makes sense in relation to the broader codebase (look at the whole function, not just the altered code); and&lt;br /&gt;
* the developer has searched for and fixed other areas that may also have been affected by the same problem.&lt;br /&gt;
* verify that the related component maintainers, if known, have participated and are aware of the issue (as assignee, or existing comments...). If they have not, please perform a friendly &amp;lt;tt&amp;gt;@mention&amp;lt;/tt&amp;gt; to make them aware about the issue. A list of component leads is available here: https://docs.moodle.org/dev/Component_Leads&lt;br /&gt;
* if any version numbers have been changed in [[version.php]] files, then the changes follow [[Moodle_versions#How_to_increment_version_numbers_in_core|the rule for updating version numbers in core]].&lt;br /&gt;
* there are comments on tracker explaining why current approach was taken and why other options (especially large issues). If not comment asking them to explain&lt;br /&gt;
&lt;br /&gt;
==Icons==&lt;br /&gt;
Are new icons being introduced? If so, ensure that:&lt;br /&gt;
* the icons abide by our [https://docs.moodle.org/dev/Moodle_icons icon guidelines] with regards to size, design and format&lt;br /&gt;
* the icons are do not unnecessarily add new ways of expressing existing concepts&lt;br /&gt;
* the icons are in a pix folder that makes sense&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [http://moodle.org/plugins/view.php?plugin=local_codechecker Code checker plugin]&lt;br /&gt;
&lt;br /&gt;
[[Category: Processes]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53527</id>
		<title>Peer reviewing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53527"/>
		<updated>2017-12-18T08:55:20Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Checklist */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Process=&lt;br /&gt;
&lt;br /&gt;
Peer review process helps to prepare the issue for integration. The peer reviewer is another developer who was not involved in the development process on the issue and therefore can take a fresh look and notice something that original developer might have forgotten during development. It is important to check that the bug actually is present and the code fixes it without creating new regressions. &lt;br /&gt;
&lt;br /&gt;
==Completing Peer review as a community member==&lt;br /&gt;
&lt;br /&gt;
Any other developer can review any change. That is why it is called &#039;peer&#039; review. However, not everyone has the necessary permissions in the tracker to click the buttons &#039;Start peer review&#039;, &#039;Finish peer review&#039; etc. This should not discourage you from looking at other contributors code and providing comments and feedback. The issue will still need to wait for someone with the right permissions to come along and click the buttons, but they can read your review and then need do no more than double-check some points, which will save a lot of time.&lt;br /&gt;
&lt;br /&gt;
To provide feedback to the developer, leave the issue in &amp;quot;Waiting for Peer Review&amp;quot; (since you don&#039;t have permission to do anything else, and also that makes it easy for someone with sufficient permissions to find the issue and move it forwards). Review the code using the checklist below, including any appropriate comments.  Once finished, please post a comment clearly stating the outcome of your review.  If you think it needs more work then indicate what needs to be changes.  If you are happy with the patch, leave a clear comment that you believe this is ready to be made part of Moodle.  This can then easily be seen by a HQ developer or component lead and they can quickly take appropriate action.&lt;br /&gt;
&lt;br /&gt;
If a followup review happens to identify something you did not find, you have an opportunity to expand your knowledge and provide better reviews in the future as well as having saved everybody else some time.&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue is ready to progress might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks again for your contribution. I have reviewed the patch:&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I don&#039;t have permission to use the peer review buttons on this issue. I hope that someone with sufficient permissions will move the issue forwards soon.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue requires further work might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch. I think the following points require further work&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Please indicate If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Peer review for development by HQ or a known common contributor==&lt;br /&gt;
&lt;br /&gt;
When code comes from a HQ developer or external developer who has been contributing significantly to Moodle and is well acquainted with Moodle standards, peer review is limited to checking the code according to the Checklist below. &lt;br /&gt;
&lt;br /&gt;
If everything is fine, the peer reviewer submits the issue for integration. &lt;br /&gt;
&lt;br /&gt;
If some additional work is needed or the author specifically asked not to submit for integration yet, the peer reviewer clicks on “Finish peer review” and the issue state returns to “Development in progress”. Usually the name of the peer reviewer stays on the issue and if a second peer review is requested it is expected that the same Peer reviewer picks it up. If the peer reviewer is not able to do the second review, they should remove their name and comment about it. Otherwise the issue does not appear on “waiting for peer review” dashboard. Please remember that not all jira users have permission to submit for integration.&lt;br /&gt;
&lt;br /&gt;
==Peer review for external developers==&lt;br /&gt;
&lt;br /&gt;
When the code has come from an external developer, the peer reviewer will also help the developer to lead the issue to integration. In this case the peer reviewer should not use “Finish peer review” button. &lt;br /&gt;
&lt;br /&gt;
If the issue needs additional work, the peer reviewer comments about the suggested changes but does not change the status of the issue and it remains as “Peer review in progress”. If the author of the patch does not reply in 4 days, the peer reviewer may select either to complete the patch themselves or reopen the issue. The decision should be based on the amount of work required to complete the solution, for example, changing coding style or commit message, rebasing, backporting, adding testing instructions, etc. should be performed by the peer reviewer. This may require picking the commits into reviewer’s git branch. &lt;br /&gt;
&lt;br /&gt;
It is very important to give the credit to the author of the code by either keeping their authorship on the commit or adding “Thanks to XXXX for providing the patch” to the commit message. If the author of the patch is not in jira-developers group the special user &#039;moodle.com&#039; should be entered in Assignee field.&lt;br /&gt;
&lt;br /&gt;
There could be situations when the patch is incomplete, does not fix the original issue, creates regressions or otherwise is not correct. As stated above, the peer reviewer should comment about it and wait for the feedback from the author. If there is no feedback, or the author can not work on this issue any more, and the peer reviewer also does not find it easy and important enough to complete, the issue needs to be reopened. Button “Fail peer review” (available to HQ developers only) will reset the issue status to “Reopened”. On this screen peer reviewer should remove assignee, peer reviewer and “patch” label from the issue. This way issue will become available again for anybody who want to work on it. All communication will remain in comments and issue history.&lt;br /&gt;
&lt;br /&gt;
If the issue has passed peer review but the integrator or tester has raised some questions about it, then normally the developer who created the patch would be expected to respond. If they do no respond quickly enough, then the peer reviewer is expected to step in and take responsibility for the change they reviewed.&lt;br /&gt;
&lt;br /&gt;
Once the issue is ready for integration, you can submit it to integration on behalf of the developer. Most external developers (those who are not in the jira-developers group) do not have permission to submit their own issues to integration so cannot do it themselves.&lt;br /&gt;
&lt;br /&gt;
==Replies templates==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
I have reviewed your code and can confirm that it addresses the reported issue. We would like to include it in core. Moodle values its contributors and tries to give them credit when possible. If you are interested in your name appearing on the https://moodle.org/dev/contributions.php page you can create a git commit that we will then pull into Moodle. You can learn more about Git and how Moodle uses it at &amp;lt;nowiki&amp;gt;[Git for developers|https://docs.moodle.org/dev/Git_for_developers]&amp;lt;/nowiki&amp;gt; page. Please let me know if you want to prepare a git branch. Or if you don’t have time to go through the whole process at the moment I can pick your patch myself.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Your code looks almost ready for integration into Moodle. There are just some little things that need to be changed to comply with Moodle standards. Can you please take a look at the review results below and tell me if you are able to modify your branch to address them.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
I have reviewed your patch, it addresses the problem and complies with Moodle standards. I&#039;m pushing this issue for integration. Following Moodle &amp;lt;nowiki&amp;gt;[Process|https://docs.moodle.org/dev/Process]&amp;lt;/nowiki&amp;gt; it will go through integration review and testing before being included in the product. There might be additional questions from an integrator and/or a tester at those stages. It would be appreciated if you read tracker emails and can reply to questions if needed. If everything goes well during the next two stages your issue will be included in the next weekly release and your count on https://moodle.org/dev/contributions.php page will increase.&amp;lt;br/&amp;gt;&lt;br /&gt;
Thanks again for your contribution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Unfortunately this patch does not fully address the reported issue. ... DETAILS...&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Even though the code does solve the issue in the short-term it is very likely to create regressions ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
I have spent some time reviewing the patch and I would recommend that you ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Please let me know If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Checklist=&lt;br /&gt;
&lt;br /&gt;
These are points to consider while peer-reviewing issues. Further explanation below.&lt;br /&gt;
&lt;br /&gt;
 [] Syntax&lt;br /&gt;
 [] Output&lt;br /&gt;
 [] Language&lt;br /&gt;
 [] Databases&lt;br /&gt;
 [] Testing (instructions and automated tests)&lt;br /&gt;
 [] Security&lt;br /&gt;
 [] Performance and Clustering&lt;br /&gt;
 [] Documentation&lt;br /&gt;
 [] Git&lt;br /&gt;
 [] Third party code&lt;br /&gt;
 [] Sanity check&lt;br /&gt;
 [] Icons&lt;br /&gt;
&lt;br /&gt;
Acceptable check-marks are Y (for yes), N (for no) or - (for not applicable). All N check-marks should be accompanied by an explanation of the problem that still needs to be addressed.&lt;br /&gt;
&lt;br /&gt;
==Syntax==&lt;br /&gt;
To allow the community of Moodle developers to work together, conventions should be followed.&lt;br /&gt;
&lt;br /&gt;
* The code is easy to understand and, where it isn&#039;t, comments have been provided.&lt;br /&gt;
* Variables are named correctly (all lower case, no camel-case, no underscores).&lt;br /&gt;
* Functions are named correctly (all lower case, no camel-case, underscores allowed).&lt;br /&gt;
* PHP DocBlocks have been updated and adhere to [[Coding_style#Documentation_and_comments|coding style guide]].&lt;br /&gt;
* Where functions are being removed, the [[Deprecation]] process is followed.&lt;br /&gt;
* The code doesn&#039;t use [[Deprecated_functions_in_2.0|deprecated functions]].&lt;br /&gt;
* $_GET, $_POST, $_REQUEST, $_COOKIE, and $_SESSION are never used.&lt;br /&gt;
&lt;br /&gt;
See the [[Coding style]] guide for details.&lt;br /&gt;
&lt;br /&gt;
==Output==&lt;br /&gt;
Output needs to be controlled by renderers to achieve consistency and correct application of themes.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* output renders are used to generate output strings, including HTML tags;&lt;br /&gt;
* HTML output is valid XHTML;&lt;br /&gt;
* no inline styles have been used in HTML output (everything has to be in CSS);&lt;br /&gt;
* CSS has been added to the appropriate CSS files (base, specific area, sometimes canvas); and&lt;br /&gt;
* the code doesn&#039;t use buffered output unless absolutely necessary.&lt;br /&gt;
* all visual output has a RTL alternative included&lt;br /&gt;
&lt;br /&gt;
feedback any notices (E_STRICT, etc) seen into the MDL.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
To achieve appropriate internationalisation of Moodle, language strings must be managed correctly.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* new language strings are named correctly (all lower case, no camel-case, underscores are permissible in some cases);&lt;br /&gt;
* help strings are named and formatted as described in [[Help strings]];&lt;br /&gt;
* language strings are used instead of hard-coded strings for text output;&lt;br /&gt;
* language strings have not been removed or renamed, had their meaning changed or had their parameters changed in stable branches (permitted only in master); and&lt;br /&gt;
* [https://docs.moodle.org/dev/Commit_cheat_sheet#Include_AMOS_script_in_the_commit_if_needed AMOS commands]  have been specified when moving or copying language strings.&lt;br /&gt;
&lt;br /&gt;
==Databases==&lt;br /&gt;
DB calls are the greatest performance bottleneck in Moodle.&lt;br /&gt;
&lt;br /&gt;
If there is SQL code you can test quickly then do so. &lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are minimal DB calls (no excessive use of the DB); and&lt;br /&gt;
* the code uses SQL compatible with all the supported DB engines (check all selected fields appear in an &#039;order by&#039; clause).&lt;br /&gt;
&lt;br /&gt;
==Testing instructions and automated tests==&lt;br /&gt;
It is the developer&#039;s responsibility to test code before integration. Issues should not be sent for peer review without tests so that the peer reviewer can assess their quality and use them to consider the scope of the issue.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are specific testing instructions that state how, as well as what, to test. Please ensure that the testing instructions are in the correct format: [https://docs.moodle.org/dev/Behat Behat gherkin];&lt;br /&gt;
* the assignee has tested according to the instructions and verified that they are passing (This is the responsibility of the assignee, not the peer reviewer)&lt;br /&gt;
* new unit tests have been added when there is a change in functionality; and&lt;br /&gt;
* &#039;&#039;&#039;unit tests pass&#039;&#039;&#039; for related areas where changes have been made.&lt;br /&gt;
* &#039;&#039;&#039;Behat tests pass&#039;&#039;&#039; for related areas where changes have been made, especially when it involved UI changes.&lt;br /&gt;
&lt;br /&gt;
==Security==&lt;br /&gt;
The user community relies on Moodle being responsibly secure.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* user login is checked where an identity is needed;&lt;br /&gt;
* sesskey values are checked before all write actions where appropriate (some read actions as well);&lt;br /&gt;
* capabilities are checked where roles differ; and&lt;br /&gt;
* if the issue itself is a [[Security|security]] issue, the [[Process#Security_issues|security process]] is being followed.&lt;br /&gt;
** Ensure that the fix is &#039;&#039;&#039;not&#039;&#039;&#039; available in a public repository (ie. a personal Github account); stand-alone patches should be provided instead.&lt;br /&gt;
** The issue will not be integrated until just before the next minor version release.&lt;br /&gt;
&lt;br /&gt;
==Performance and clustering==&lt;br /&gt;
It is easy to write code that works sufficiently well when you are working on either small sets of data or with a small number of active users.  Picking performance issues can be quite difficult and can required a complex level of understanding of both the section of code being reviewed, but also other parts that interact with it.&lt;br /&gt;
&lt;br /&gt;
Clustering is when the same code is run on different computers and an end user could send each request to a different computer.  This can produce a number of concurrency issues if not thought through.  One example is;  If you complete an opcache_reset(), no other server except the one you ran it on knows that it happened.  So data can get out of sync.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Any filesystem, database or cache accesses are done in the most efficient way.&lt;br /&gt;
* That any code or function that appear expensive are not in critical paths.  eg; They don&#039;t load on every page.&lt;br /&gt;
* The least possible code is running to complete the task, especially looking for hidden loops.  They can appear from calling functions.&lt;br /&gt;
* Any code that runs is not specific to a single node. (eg opcache_reset())  The ensures clusters will run correctly.&lt;br /&gt;
* If the code could affect performance at all, make sure there is a comment noting what was considered.&lt;br /&gt;
** What they did to mitigate performance impact, or why they thought it wasn&#039;t an issue.&lt;br /&gt;
** Why they made certain trade-offs.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
Work does not stop when code is integrated.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Appropriate [[Tracker_issue_labels|labels]] have been added when there has been a function change, particularly&lt;br /&gt;
** docs_required (any functional change, usually paired with ui_change),&lt;br /&gt;
** dev_docs_required (any change to APIs, usually paired with api_change),&lt;br /&gt;
** ui_change (any functional change, usually paired with docs_required, except ui_change remains permanetly),&lt;br /&gt;
** api_change (any change to APIs that devs will need to know about, usually paired with dev_docs_required, except api_change remains permanetly),&lt;br /&gt;
** unit_test_required and acceptance_test_required, when there are api or ui changes needing improved coverage, and&lt;br /&gt;
** qa_test_required (significant functional change, not covered by unit/acceptance ones).&lt;br /&gt;
* Also, verify that the components for the issue are correctly set, so maintainers (subscribed by default) will be mailed about issues early in the process.&lt;br /&gt;
&lt;br /&gt;
==Git==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the commit matches the [[Coding style#Git_commits|Coding style]]&lt;br /&gt;
* the Git history is clean and the work has been rebased to logical commits; and&lt;br /&gt;
* the original author of the work provided as a patch has been given credit within the commit (as author of in the commit message if changes were made).&lt;br /&gt;
&lt;br /&gt;
==Third party code==&lt;br /&gt;
Does the change contain third party code? If so, ensure that:&lt;br /&gt;
&lt;br /&gt;
* The code is licensed under a [http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses| GPL compatible license].&lt;br /&gt;
* The instructions for upgrading/importing the library and contained within a readme_moodle.txt file.&lt;br /&gt;
* The library is recorded in a thirdparty.xml file, including licensing information.&lt;br /&gt;
* Third party code has been scanned to check for url accessible entry points that could be exploited. These should either be disabled, or if required functionality they should be checked for security weaknesses.&lt;br /&gt;
* Does not duplicate the functionality of any existing api or third party library in core.&lt;br /&gt;
* Any modifications to third party code are recorded in readme_moodle.txt&lt;br /&gt;
&lt;br /&gt;
==Sanity check==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the code seems to solve the described problem completely within its reported scope (and further issues have been created to resolve remaining parts or further refactoring);&lt;br /&gt;
* the code makes sense in relation to the broader codebase (look at the whole function, not just the altered code); and&lt;br /&gt;
* the developer has searched for and fixed other areas that may also have been affected by the same problem.&lt;br /&gt;
* verify that the related component maintainers, if known, have participated and are aware of the issue (as assignee, or existing comments...). If they have not, please perform a friendly &amp;lt;tt&amp;gt;@mention&amp;lt;/tt&amp;gt; to make them aware about the issue.&lt;br /&gt;
* if any version numbers have been changed in [[version.php]] files, then the changes follow [[Moodle_versions#How_to_increment_version_numbers_in_core|the rule for updating version numbers in core]].&lt;br /&gt;
* there are comments on tracker explaining why current approach was taken and why other options (especially large issues). If not comment asking them to explain&lt;br /&gt;
&lt;br /&gt;
==Icons==&lt;br /&gt;
Are new icons being introduced? If so, ensure that:&lt;br /&gt;
* the icons abide by our [https://docs.moodle.org/dev/Moodle_icons icon guidelines] with regards to size, design and format&lt;br /&gt;
* the icons are do not unnecessarily add new ways of expressing existing concepts&lt;br /&gt;
* the icons are in a pix folder that makes sense&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [http://moodle.org/plugins/view.php?plugin=local_codechecker Code checker plugin]&lt;br /&gt;
&lt;br /&gt;
[[Category: Processes]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53526</id>
		<title>Peer reviewing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53526"/>
		<updated>2017-12-18T08:55:05Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Component Leads */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Process=&lt;br /&gt;
&lt;br /&gt;
Peer review process helps to prepare the issue for integration. The peer reviewer is another developer who was not involved in the development process on the issue and therefore can take a fresh look and notice something that original developer might have forgotten during development. It is important to check that the bug actually is present and the code fixes it without creating new regressions. &lt;br /&gt;
&lt;br /&gt;
==Completing Peer review as a community member==&lt;br /&gt;
&lt;br /&gt;
Any other developer can review any change. That is why it is called &#039;peer&#039; review. However, not everyone has the necessary permissions in the tracker to click the buttons &#039;Start peer review&#039;, &#039;Finish peer review&#039; etc. This should not discourage you from looking at other contributors code and providing comments and feedback. The issue will still need to wait for someone with the right permissions to come along and click the buttons, but they can read your review and then need do no more than double-check some points, which will save a lot of time.&lt;br /&gt;
&lt;br /&gt;
To provide feedback to the developer, leave the issue in &amp;quot;Waiting for Peer Review&amp;quot; (since you don&#039;t have permission to do anything else, and also that makes it easy for someone with sufficient permissions to find the issue and move it forwards). Review the code using the checklist below, including any appropriate comments.  Once finished, please post a comment clearly stating the outcome of your review.  If you think it needs more work then indicate what needs to be changes.  If you are happy with the patch, leave a clear comment that you believe this is ready to be made part of Moodle.  This can then easily be seen by a HQ developer or component lead and they can quickly take appropriate action.&lt;br /&gt;
&lt;br /&gt;
If a followup review happens to identify something you did not find, you have an opportunity to expand your knowledge and provide better reviews in the future as well as having saved everybody else some time.&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue is ready to progress might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks again for your contribution. I have reviewed the patch:&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I don&#039;t have permission to use the peer review buttons on this issue. I hope that someone with sufficient permissions will move the issue forwards soon.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue requires further work might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch. I think the following points require further work&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Please indicate If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Peer review for development by HQ or a known common contributor==&lt;br /&gt;
&lt;br /&gt;
When code comes from a HQ developer or external developer who has been contributing significantly to Moodle and is well acquainted with Moodle standards, peer review is limited to checking the code according to the Checklist below. &lt;br /&gt;
&lt;br /&gt;
If everything is fine, the peer reviewer submits the issue for integration. &lt;br /&gt;
&lt;br /&gt;
If some additional work is needed or the author specifically asked not to submit for integration yet, the peer reviewer clicks on “Finish peer review” and the issue state returns to “Development in progress”. Usually the name of the peer reviewer stays on the issue and if a second peer review is requested it is expected that the same Peer reviewer picks it up. If the peer reviewer is not able to do the second review, they should remove their name and comment about it. Otherwise the issue does not appear on “waiting for peer review” dashboard. Please remember that not all jira users have permission to submit for integration.&lt;br /&gt;
&lt;br /&gt;
==Peer review for external developers==&lt;br /&gt;
&lt;br /&gt;
When the code has come from an external developer, the peer reviewer will also help the developer to lead the issue to integration. In this case the peer reviewer should not use “Finish peer review” button. &lt;br /&gt;
&lt;br /&gt;
If the issue needs additional work, the peer reviewer comments about the suggested changes but does not change the status of the issue and it remains as “Peer review in progress”. If the author of the patch does not reply in 4 days, the peer reviewer may select either to complete the patch themselves or reopen the issue. The decision should be based on the amount of work required to complete the solution, for example, changing coding style or commit message, rebasing, backporting, adding testing instructions, etc. should be performed by the peer reviewer. This may require picking the commits into reviewer’s git branch. &lt;br /&gt;
&lt;br /&gt;
It is very important to give the credit to the author of the code by either keeping their authorship on the commit or adding “Thanks to XXXX for providing the patch” to the commit message. If the author of the patch is not in jira-developers group the special user &#039;moodle.com&#039; should be entered in Assignee field.&lt;br /&gt;
&lt;br /&gt;
There could be situations when the patch is incomplete, does not fix the original issue, creates regressions or otherwise is not correct. As stated above, the peer reviewer should comment about it and wait for the feedback from the author. If there is no feedback, or the author can not work on this issue any more, and the peer reviewer also does not find it easy and important enough to complete, the issue needs to be reopened. Button “Fail peer review” (available to HQ developers only) will reset the issue status to “Reopened”. On this screen peer reviewer should remove assignee, peer reviewer and “patch” label from the issue. This way issue will become available again for anybody who want to work on it. All communication will remain in comments and issue history.&lt;br /&gt;
&lt;br /&gt;
If the issue has passed peer review but the integrator or tester has raised some questions about it, then normally the developer who created the patch would be expected to respond. If they do no respond quickly enough, then the peer reviewer is expected to step in and take responsibility for the change they reviewed.&lt;br /&gt;
&lt;br /&gt;
Once the issue is ready for integration, you can submit it to integration on behalf of the developer. Most external developers (those who are not in the jira-developers group) do not have permission to submit their own issues to integration so cannot do it themselves.&lt;br /&gt;
&lt;br /&gt;
==Replies templates==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
I have reviewed your code and can confirm that it addresses the reported issue. We would like to include it in core. Moodle values its contributors and tries to give them credit when possible. If you are interested in your name appearing on the https://moodle.org/dev/contributions.php page you can create a git commit that we will then pull into Moodle. You can learn more about Git and how Moodle uses it at &amp;lt;nowiki&amp;gt;[Git for developers|https://docs.moodle.org/dev/Git_for_developers]&amp;lt;/nowiki&amp;gt; page. Please let me know if you want to prepare a git branch. Or if you don’t have time to go through the whole process at the moment I can pick your patch myself.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Your code looks almost ready for integration into Moodle. There are just some little things that need to be changed to comply with Moodle standards. Can you please take a look at the review results below and tell me if you are able to modify your branch to address them.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
I have reviewed your patch, it addresses the problem and complies with Moodle standards. I&#039;m pushing this issue for integration. Following Moodle &amp;lt;nowiki&amp;gt;[Process|https://docs.moodle.org/dev/Process]&amp;lt;/nowiki&amp;gt; it will go through integration review and testing before being included in the product. There might be additional questions from an integrator and/or a tester at those stages. It would be appreciated if you read tracker emails and can reply to questions if needed. If everything goes well during the next two stages your issue will be included in the next weekly release and your count on https://moodle.org/dev/contributions.php page will increase.&amp;lt;br/&amp;gt;&lt;br /&gt;
Thanks again for your contribution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Unfortunately this patch does not fully address the reported issue. ... DETAILS...&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Even though the code does solve the issue in the short-term it is very likely to create regressions ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
I have spent some time reviewing the patch and I would recommend that you ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Please let me know If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Checklist=&lt;br /&gt;
&lt;br /&gt;
These are points to consider while peer-reviewing issues. Further explanation below.&lt;br /&gt;
&lt;br /&gt;
 [] Syntax&lt;br /&gt;
 [] Output&lt;br /&gt;
 [] Language&lt;br /&gt;
 [] Databases&lt;br /&gt;
 [] Testing (instructions and automated tests)&lt;br /&gt;
 [] Security&lt;br /&gt;
 [] Performance and Clustering&lt;br /&gt;
 [] Documentation&lt;br /&gt;
 [] Git&lt;br /&gt;
 [] Third party code&lt;br /&gt;
 [] Component Leads&lt;br /&gt;
 [] Sanity check&lt;br /&gt;
 [] Icons&lt;br /&gt;
&lt;br /&gt;
Acceptable check-marks are Y (for yes), N (for no) or - (for not applicable). All N check-marks should be accompanied by an explanation of the problem that still needs to be addressed.&lt;br /&gt;
&lt;br /&gt;
==Syntax==&lt;br /&gt;
To allow the community of Moodle developers to work together, conventions should be followed.&lt;br /&gt;
&lt;br /&gt;
* The code is easy to understand and, where it isn&#039;t, comments have been provided.&lt;br /&gt;
* Variables are named correctly (all lower case, no camel-case, no underscores).&lt;br /&gt;
* Functions are named correctly (all lower case, no camel-case, underscores allowed).&lt;br /&gt;
* PHP DocBlocks have been updated and adhere to [[Coding_style#Documentation_and_comments|coding style guide]].&lt;br /&gt;
* Where functions are being removed, the [[Deprecation]] process is followed.&lt;br /&gt;
* The code doesn&#039;t use [[Deprecated_functions_in_2.0|deprecated functions]].&lt;br /&gt;
* $_GET, $_POST, $_REQUEST, $_COOKIE, and $_SESSION are never used.&lt;br /&gt;
&lt;br /&gt;
See the [[Coding style]] guide for details.&lt;br /&gt;
&lt;br /&gt;
==Output==&lt;br /&gt;
Output needs to be controlled by renderers to achieve consistency and correct application of themes.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* output renders are used to generate output strings, including HTML tags;&lt;br /&gt;
* HTML output is valid XHTML;&lt;br /&gt;
* no inline styles have been used in HTML output (everything has to be in CSS);&lt;br /&gt;
* CSS has been added to the appropriate CSS files (base, specific area, sometimes canvas); and&lt;br /&gt;
* the code doesn&#039;t use buffered output unless absolutely necessary.&lt;br /&gt;
* all visual output has a RTL alternative included&lt;br /&gt;
&lt;br /&gt;
feedback any notices (E_STRICT, etc) seen into the MDL.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
To achieve appropriate internationalisation of Moodle, language strings must be managed correctly.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* new language strings are named correctly (all lower case, no camel-case, underscores are permissible in some cases);&lt;br /&gt;
* help strings are named and formatted as described in [[Help strings]];&lt;br /&gt;
* language strings are used instead of hard-coded strings for text output;&lt;br /&gt;
* language strings have not been removed or renamed, had their meaning changed or had their parameters changed in stable branches (permitted only in master); and&lt;br /&gt;
* [https://docs.moodle.org/dev/Commit_cheat_sheet#Include_AMOS_script_in_the_commit_if_needed AMOS commands]  have been specified when moving or copying language strings.&lt;br /&gt;
&lt;br /&gt;
==Databases==&lt;br /&gt;
DB calls are the greatest performance bottleneck in Moodle.&lt;br /&gt;
&lt;br /&gt;
If there is SQL code you can test quickly then do so. &lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are minimal DB calls (no excessive use of the DB); and&lt;br /&gt;
* the code uses SQL compatible with all the supported DB engines (check all selected fields appear in an &#039;order by&#039; clause).&lt;br /&gt;
&lt;br /&gt;
==Testing instructions and automated tests==&lt;br /&gt;
It is the developer&#039;s responsibility to test code before integration. Issues should not be sent for peer review without tests so that the peer reviewer can assess their quality and use them to consider the scope of the issue.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are specific testing instructions that state how, as well as what, to test. Please ensure that the testing instructions are in the correct format: [https://docs.moodle.org/dev/Behat Behat gherkin];&lt;br /&gt;
* the assignee has tested according to the instructions and verified that they are passing (This is the responsibility of the assignee, not the peer reviewer)&lt;br /&gt;
* new unit tests have been added when there is a change in functionality; and&lt;br /&gt;
* &#039;&#039;&#039;unit tests pass&#039;&#039;&#039; for related areas where changes have been made.&lt;br /&gt;
* &#039;&#039;&#039;Behat tests pass&#039;&#039;&#039; for related areas where changes have been made, especially when it involved UI changes.&lt;br /&gt;
&lt;br /&gt;
==Security==&lt;br /&gt;
The user community relies on Moodle being responsibly secure.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* user login is checked where an identity is needed;&lt;br /&gt;
* sesskey values are checked before all write actions where appropriate (some read actions as well);&lt;br /&gt;
* capabilities are checked where roles differ; and&lt;br /&gt;
* if the issue itself is a [[Security|security]] issue, the [[Process#Security_issues|security process]] is being followed.&lt;br /&gt;
** Ensure that the fix is &#039;&#039;&#039;not&#039;&#039;&#039; available in a public repository (ie. a personal Github account); stand-alone patches should be provided instead.&lt;br /&gt;
** The issue will not be integrated until just before the next minor version release.&lt;br /&gt;
&lt;br /&gt;
==Performance and clustering==&lt;br /&gt;
It is easy to write code that works sufficiently well when you are working on either small sets of data or with a small number of active users.  Picking performance issues can be quite difficult and can required a complex level of understanding of both the section of code being reviewed, but also other parts that interact with it.&lt;br /&gt;
&lt;br /&gt;
Clustering is when the same code is run on different computers and an end user could send each request to a different computer.  This can produce a number of concurrency issues if not thought through.  One example is;  If you complete an opcache_reset(), no other server except the one you ran it on knows that it happened.  So data can get out of sync.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Any filesystem, database or cache accesses are done in the most efficient way.&lt;br /&gt;
* That any code or function that appear expensive are not in critical paths.  eg; They don&#039;t load on every page.&lt;br /&gt;
* The least possible code is running to complete the task, especially looking for hidden loops.  They can appear from calling functions.&lt;br /&gt;
* Any code that runs is not specific to a single node. (eg opcache_reset())  The ensures clusters will run correctly.&lt;br /&gt;
* If the code could affect performance at all, make sure there is a comment noting what was considered.&lt;br /&gt;
** What they did to mitigate performance impact, or why they thought it wasn&#039;t an issue.&lt;br /&gt;
** Why they made certain trade-offs.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
Work does not stop when code is integrated.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Appropriate [[Tracker_issue_labels|labels]] have been added when there has been a function change, particularly&lt;br /&gt;
** docs_required (any functional change, usually paired with ui_change),&lt;br /&gt;
** dev_docs_required (any change to APIs, usually paired with api_change),&lt;br /&gt;
** ui_change (any functional change, usually paired with docs_required, except ui_change remains permanetly),&lt;br /&gt;
** api_change (any change to APIs that devs will need to know about, usually paired with dev_docs_required, except api_change remains permanetly),&lt;br /&gt;
** unit_test_required and acceptance_test_required, when there are api or ui changes needing improved coverage, and&lt;br /&gt;
** qa_test_required (significant functional change, not covered by unit/acceptance ones).&lt;br /&gt;
* Also, verify that the components for the issue are correctly set, so maintainers (subscribed by default) will be mailed about issues early in the process.&lt;br /&gt;
&lt;br /&gt;
==Git==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the commit matches the [[Coding style#Git_commits|Coding style]]&lt;br /&gt;
* the Git history is clean and the work has been rebased to logical commits; and&lt;br /&gt;
* the original author of the work provided as a patch has been given credit within the commit (as author of in the commit message if changes were made).&lt;br /&gt;
&lt;br /&gt;
==Third party code==&lt;br /&gt;
Does the change contain third party code? If so, ensure that:&lt;br /&gt;
&lt;br /&gt;
* The code is licensed under a [http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses| GPL compatible license].&lt;br /&gt;
* The instructions for upgrading/importing the library and contained within a readme_moodle.txt file.&lt;br /&gt;
* The library is recorded in a thirdparty.xml file, including licensing information.&lt;br /&gt;
* Third party code has been scanned to check for url accessible entry points that could be exploited. These should either be disabled, or if required functionality they should be checked for security weaknesses.&lt;br /&gt;
* Does not duplicate the functionality of any existing api or third party library in core.&lt;br /&gt;
* Any modifications to third party code are recorded in readme_moodle.txt&lt;br /&gt;
&lt;br /&gt;
==Sanity check==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the code seems to solve the described problem completely within its reported scope (and further issues have been created to resolve remaining parts or further refactoring);&lt;br /&gt;
* the code makes sense in relation to the broader codebase (look at the whole function, not just the altered code); and&lt;br /&gt;
* the developer has searched for and fixed other areas that may also have been affected by the same problem.&lt;br /&gt;
* verify that the related component maintainers, if known, have participated and are aware of the issue (as assignee, or existing comments...). If they have not, please perform a friendly &amp;lt;tt&amp;gt;@mention&amp;lt;/tt&amp;gt; to make them aware about the issue.&lt;br /&gt;
* if any version numbers have been changed in [[version.php]] files, then the changes follow [[Moodle_versions#How_to_increment_version_numbers_in_core|the rule for updating version numbers in core]].&lt;br /&gt;
* there are comments on tracker explaining why current approach was taken and why other options (especially large issues). If not comment asking them to explain&lt;br /&gt;
&lt;br /&gt;
==Icons==&lt;br /&gt;
Are new icons being introduced? If so, ensure that:&lt;br /&gt;
* the icons abide by our [https://docs.moodle.org/dev/Moodle_icons icon guidelines] with regards to size, design and format&lt;br /&gt;
* the icons are do not unnecessarily add new ways of expressing existing concepts&lt;br /&gt;
* the icons are in a pix folder that makes sense&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [http://moodle.org/plugins/view.php?plugin=local_codechecker Code checker plugin]&lt;br /&gt;
&lt;br /&gt;
[[Category: Processes]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53525</id>
		<title>Peer reviewing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53525"/>
		<updated>2017-12-18T08:45:18Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Checklist */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Process=&lt;br /&gt;
&lt;br /&gt;
Peer review process helps to prepare the issue for integration. The peer reviewer is another developer who was not involved in the development process on the issue and therefore can take a fresh look and notice something that original developer might have forgotten during development. It is important to check that the bug actually is present and the code fixes it without creating new regressions. &lt;br /&gt;
&lt;br /&gt;
==Completing Peer review as a community member==&lt;br /&gt;
&lt;br /&gt;
Any other developer can review any change. That is why it is called &#039;peer&#039; review. However, not everyone has the necessary permissions in the tracker to click the buttons &#039;Start peer review&#039;, &#039;Finish peer review&#039; etc. This should not discourage you from looking at other contributors code and providing comments and feedback. The issue will still need to wait for someone with the right permissions to come along and click the buttons, but they can read your review and then need do no more than double-check some points, which will save a lot of time.&lt;br /&gt;
&lt;br /&gt;
To provide feedback to the developer, leave the issue in &amp;quot;Waiting for Peer Review&amp;quot; (since you don&#039;t have permission to do anything else, and also that makes it easy for someone with sufficient permissions to find the issue and move it forwards). Review the code using the checklist below, including any appropriate comments.  Once finished, please post a comment clearly stating the outcome of your review.  If you think it needs more work then indicate what needs to be changes.  If you are happy with the patch, leave a clear comment that you believe this is ready to be made part of Moodle.  This can then easily be seen by a HQ developer or component lead and they can quickly take appropriate action.&lt;br /&gt;
&lt;br /&gt;
If a followup review happens to identify something you did not find, you have an opportunity to expand your knowledge and provide better reviews in the future as well as having saved everybody else some time.&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue is ready to progress might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks again for your contribution. I have reviewed the patch:&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I don&#039;t have permission to use the peer review buttons on this issue. I hope that someone with sufficient permissions will move the issue forwards soon.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue requires further work might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch. I think the following points require further work&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Please indicate If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Peer review for development by HQ or a known common contributor==&lt;br /&gt;
&lt;br /&gt;
When code comes from a HQ developer or external developer who has been contributing significantly to Moodle and is well acquainted with Moodle standards, peer review is limited to checking the code according to the Checklist below. &lt;br /&gt;
&lt;br /&gt;
If everything is fine, the peer reviewer submits the issue for integration. &lt;br /&gt;
&lt;br /&gt;
If some additional work is needed or the author specifically asked not to submit for integration yet, the peer reviewer clicks on “Finish peer review” and the issue state returns to “Development in progress”. Usually the name of the peer reviewer stays on the issue and if a second peer review is requested it is expected that the same Peer reviewer picks it up. If the peer reviewer is not able to do the second review, they should remove their name and comment about it. Otherwise the issue does not appear on “waiting for peer review” dashboard. Please remember that not all jira users have permission to submit for integration.&lt;br /&gt;
&lt;br /&gt;
==Peer review for external developers==&lt;br /&gt;
&lt;br /&gt;
When the code has come from an external developer, the peer reviewer will also help the developer to lead the issue to integration. In this case the peer reviewer should not use “Finish peer review” button. &lt;br /&gt;
&lt;br /&gt;
If the issue needs additional work, the peer reviewer comments about the suggested changes but does not change the status of the issue and it remains as “Peer review in progress”. If the author of the patch does not reply in 4 days, the peer reviewer may select either to complete the patch themselves or reopen the issue. The decision should be based on the amount of work required to complete the solution, for example, changing coding style or commit message, rebasing, backporting, adding testing instructions, etc. should be performed by the peer reviewer. This may require picking the commits into reviewer’s git branch. &lt;br /&gt;
&lt;br /&gt;
It is very important to give the credit to the author of the code by either keeping their authorship on the commit or adding “Thanks to XXXX for providing the patch” to the commit message. If the author of the patch is not in jira-developers group the special user &#039;moodle.com&#039; should be entered in Assignee field.&lt;br /&gt;
&lt;br /&gt;
There could be situations when the patch is incomplete, does not fix the original issue, creates regressions or otherwise is not correct. As stated above, the peer reviewer should comment about it and wait for the feedback from the author. If there is no feedback, or the author can not work on this issue any more, and the peer reviewer also does not find it easy and important enough to complete, the issue needs to be reopened. Button “Fail peer review” (available to HQ developers only) will reset the issue status to “Reopened”. On this screen peer reviewer should remove assignee, peer reviewer and “patch” label from the issue. This way issue will become available again for anybody who want to work on it. All communication will remain in comments and issue history.&lt;br /&gt;
&lt;br /&gt;
If the issue has passed peer review but the integrator or tester has raised some questions about it, then normally the developer who created the patch would be expected to respond. If they do no respond quickly enough, then the peer reviewer is expected to step in and take responsibility for the change they reviewed.&lt;br /&gt;
&lt;br /&gt;
Once the issue is ready for integration, you can submit it to integration on behalf of the developer. Most external developers (those who are not in the jira-developers group) do not have permission to submit their own issues to integration so cannot do it themselves.&lt;br /&gt;
&lt;br /&gt;
==Replies templates==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
I have reviewed your code and can confirm that it addresses the reported issue. We would like to include it in core. Moodle values its contributors and tries to give them credit when possible. If you are interested in your name appearing on the https://moodle.org/dev/contributions.php page you can create a git commit that we will then pull into Moodle. You can learn more about Git and how Moodle uses it at &amp;lt;nowiki&amp;gt;[Git for developers|https://docs.moodle.org/dev/Git_for_developers]&amp;lt;/nowiki&amp;gt; page. Please let me know if you want to prepare a git branch. Or if you don’t have time to go through the whole process at the moment I can pick your patch myself.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Your code looks almost ready for integration into Moodle. There are just some little things that need to be changed to comply with Moodle standards. Can you please take a look at the review results below and tell me if you are able to modify your branch to address them.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
I have reviewed your patch, it addresses the problem and complies with Moodle standards. I&#039;m pushing this issue for integration. Following Moodle &amp;lt;nowiki&amp;gt;[Process|https://docs.moodle.org/dev/Process]&amp;lt;/nowiki&amp;gt; it will go through integration review and testing before being included in the product. There might be additional questions from an integrator and/or a tester at those stages. It would be appreciated if you read tracker emails and can reply to questions if needed. If everything goes well during the next two stages your issue will be included in the next weekly release and your count on https://moodle.org/dev/contributions.php page will increase.&amp;lt;br/&amp;gt;&lt;br /&gt;
Thanks again for your contribution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Unfortunately this patch does not fully address the reported issue. ... DETAILS...&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Even though the code does solve the issue in the short-term it is very likely to create regressions ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
I have spent some time reviewing the patch and I would recommend that you ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Please let me know If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Checklist=&lt;br /&gt;
&lt;br /&gt;
These are points to consider while peer-reviewing issues. Further explanation below.&lt;br /&gt;
&lt;br /&gt;
 [] Syntax&lt;br /&gt;
 [] Output&lt;br /&gt;
 [] Language&lt;br /&gt;
 [] Databases&lt;br /&gt;
 [] Testing (instructions and automated tests)&lt;br /&gt;
 [] Security&lt;br /&gt;
 [] Performance and Clustering&lt;br /&gt;
 [] Documentation&lt;br /&gt;
 [] Git&lt;br /&gt;
 [] Third party code&lt;br /&gt;
 [] Component Leads&lt;br /&gt;
 [] Sanity check&lt;br /&gt;
 [] Icons&lt;br /&gt;
&lt;br /&gt;
Acceptable check-marks are Y (for yes), N (for no) or - (for not applicable). All N check-marks should be accompanied by an explanation of the problem that still needs to be addressed.&lt;br /&gt;
&lt;br /&gt;
==Syntax==&lt;br /&gt;
To allow the community of Moodle developers to work together, conventions should be followed.&lt;br /&gt;
&lt;br /&gt;
* The code is easy to understand and, where it isn&#039;t, comments have been provided.&lt;br /&gt;
* Variables are named correctly (all lower case, no camel-case, no underscores).&lt;br /&gt;
* Functions are named correctly (all lower case, no camel-case, underscores allowed).&lt;br /&gt;
* PHP DocBlocks have been updated and adhere to [[Coding_style#Documentation_and_comments|coding style guide]].&lt;br /&gt;
* Where functions are being removed, the [[Deprecation]] process is followed.&lt;br /&gt;
* The code doesn&#039;t use [[Deprecated_functions_in_2.0|deprecated functions]].&lt;br /&gt;
* $_GET, $_POST, $_REQUEST, $_COOKIE, and $_SESSION are never used.&lt;br /&gt;
&lt;br /&gt;
See the [[Coding style]] guide for details.&lt;br /&gt;
&lt;br /&gt;
==Output==&lt;br /&gt;
Output needs to be controlled by renderers to achieve consistency and correct application of themes.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* output renders are used to generate output strings, including HTML tags;&lt;br /&gt;
* HTML output is valid XHTML;&lt;br /&gt;
* no inline styles have been used in HTML output (everything has to be in CSS);&lt;br /&gt;
* CSS has been added to the appropriate CSS files (base, specific area, sometimes canvas); and&lt;br /&gt;
* the code doesn&#039;t use buffered output unless absolutely necessary.&lt;br /&gt;
* all visual output has a RTL alternative included&lt;br /&gt;
&lt;br /&gt;
feedback any notices (E_STRICT, etc) seen into the MDL.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
To achieve appropriate internationalisation of Moodle, language strings must be managed correctly.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* new language strings are named correctly (all lower case, no camel-case, underscores are permissible in some cases);&lt;br /&gt;
* help strings are named and formatted as described in [[Help strings]];&lt;br /&gt;
* language strings are used instead of hard-coded strings for text output;&lt;br /&gt;
* language strings have not been removed or renamed, had their meaning changed or had their parameters changed in stable branches (permitted only in master); and&lt;br /&gt;
* [https://docs.moodle.org/dev/Commit_cheat_sheet#Include_AMOS_script_in_the_commit_if_needed AMOS commands]  have been specified when moving or copying language strings.&lt;br /&gt;
&lt;br /&gt;
==Databases==&lt;br /&gt;
DB calls are the greatest performance bottleneck in Moodle.&lt;br /&gt;
&lt;br /&gt;
If there is SQL code you can test quickly then do so. &lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are minimal DB calls (no excessive use of the DB); and&lt;br /&gt;
* the code uses SQL compatible with all the supported DB engines (check all selected fields appear in an &#039;order by&#039; clause).&lt;br /&gt;
&lt;br /&gt;
==Testing instructions and automated tests==&lt;br /&gt;
It is the developer&#039;s responsibility to test code before integration. Issues should not be sent for peer review without tests so that the peer reviewer can assess their quality and use them to consider the scope of the issue.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are specific testing instructions that state how, as well as what, to test. Please ensure that the testing instructions are in the correct format: [https://docs.moodle.org/dev/Behat Behat gherkin];&lt;br /&gt;
* the assignee has tested according to the instructions and verified that they are passing (This is the responsibility of the assignee, not the peer reviewer)&lt;br /&gt;
* new unit tests have been added when there is a change in functionality; and&lt;br /&gt;
* &#039;&#039;&#039;unit tests pass&#039;&#039;&#039; for related areas where changes have been made.&lt;br /&gt;
* &#039;&#039;&#039;Behat tests pass&#039;&#039;&#039; for related areas where changes have been made, especially when it involved UI changes.&lt;br /&gt;
&lt;br /&gt;
==Security==&lt;br /&gt;
The user community relies on Moodle being responsibly secure.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* user login is checked where an identity is needed;&lt;br /&gt;
* sesskey values are checked before all write actions where appropriate (some read actions as well);&lt;br /&gt;
* capabilities are checked where roles differ; and&lt;br /&gt;
* if the issue itself is a [[Security|security]] issue, the [[Process#Security_issues|security process]] is being followed.&lt;br /&gt;
** Ensure that the fix is &#039;&#039;&#039;not&#039;&#039;&#039; available in a public repository (ie. a personal Github account); stand-alone patches should be provided instead.&lt;br /&gt;
** The issue will not be integrated until just before the next minor version release.&lt;br /&gt;
&lt;br /&gt;
==Performance and clustering==&lt;br /&gt;
It is easy to write code that works sufficiently well when you are working on either small sets of data or with a small number of active users.  Picking performance issues can be quite difficult and can required a complex level of understanding of both the section of code being reviewed, but also other parts that interact with it.&lt;br /&gt;
&lt;br /&gt;
Clustering is when the same code is run on different computers and an end user could send each request to a different computer.  This can produce a number of concurrency issues if not thought through.  One example is;  If you complete an opcache_reset(), no other server except the one you ran it on knows that it happened.  So data can get out of sync.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Any filesystem, database or cache accesses are done in the most efficient way.&lt;br /&gt;
* That any code or function that appear expensive are not in critical paths.  eg; They don&#039;t load on every page.&lt;br /&gt;
* The least possible code is running to complete the task, especially looking for hidden loops.  They can appear from calling functions.&lt;br /&gt;
* Any code that runs is not specific to a single node. (eg opcache_reset())  The ensures clusters will run correctly.&lt;br /&gt;
* If the code could affect performance at all, make sure there is a comment noting what was considered.&lt;br /&gt;
** What they did to mitigate performance impact, or why they thought it wasn&#039;t an issue.&lt;br /&gt;
** Why they made certain trade-offs.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
Work does not stop when code is integrated.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Appropriate [[Tracker_issue_labels|labels]] have been added when there has been a function change, particularly&lt;br /&gt;
** docs_required (any functional change, usually paired with ui_change),&lt;br /&gt;
** dev_docs_required (any change to APIs, usually paired with api_change),&lt;br /&gt;
** ui_change (any functional change, usually paired with docs_required, except ui_change remains permanetly),&lt;br /&gt;
** api_change (any change to APIs that devs will need to know about, usually paired with dev_docs_required, except api_change remains permanetly),&lt;br /&gt;
** unit_test_required and acceptance_test_required, when there are api or ui changes needing improved coverage, and&lt;br /&gt;
** qa_test_required (significant functional change, not covered by unit/acceptance ones).&lt;br /&gt;
* Also, verify that the components for the issue are correctly set, so maintainers (subscribed by default) will be mailed about issues early in the process.&lt;br /&gt;
&lt;br /&gt;
==Git==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the commit matches the [[Coding style#Git_commits|Coding style]]&lt;br /&gt;
* the Git history is clean and the work has been rebased to logical commits; and&lt;br /&gt;
* the original author of the work provided as a patch has been given credit within the commit (as author of in the commit message if changes were made).&lt;br /&gt;
&lt;br /&gt;
==Third party code==&lt;br /&gt;
Does the change contain third party code? If so, ensure that:&lt;br /&gt;
&lt;br /&gt;
* The code is licensed under a [http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses| GPL compatible license].&lt;br /&gt;
* The instructions for upgrading/importing the library and contained within a readme_moodle.txt file.&lt;br /&gt;
* The library is recorded in a thirdparty.xml file, including licensing information.&lt;br /&gt;
* Third party code has been scanned to check for url accessible entry points that could be exploited. These should either be disabled, or if required functionality they should be checked for security weaknesses.&lt;br /&gt;
* Does not duplicate the functionality of any existing api or third party library in core.&lt;br /&gt;
* Any modifications to third party code are recorded in readme_moodle.txt&lt;br /&gt;
&lt;br /&gt;
==Component Leads==&lt;br /&gt;
If no component leads have not been involved in the issue, at least one of the component leads should be asked for a +1 on the issue to ensure they are aware of the issues being worked on in their components. The list of component leads is available here:&lt;br /&gt;
https://docs.moodle.org/dev/Component_Leads&lt;br /&gt;
&lt;br /&gt;
==Sanity check==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the code seems to solve the described problem completely within its reported scope (and further issues have been created to resolve remaining parts or further refactoring);&lt;br /&gt;
* the code makes sense in relation to the broader codebase (look at the whole function, not just the altered code); and&lt;br /&gt;
* the developer has searched for and fixed other areas that may also have been affected by the same problem.&lt;br /&gt;
* verify that the related component maintainers, if known, have participated and are aware of the issue (as assignee, or existing comments...). If they have not, please perform a friendly &amp;lt;tt&amp;gt;@mention&amp;lt;/tt&amp;gt; to make them aware about the issue.&lt;br /&gt;
* if any version numbers have been changed in [[version.php]] files, then the changes follow [[Moodle_versions#How_to_increment_version_numbers_in_core|the rule for updating version numbers in core]].&lt;br /&gt;
* there are comments on tracker explaining why current approach was taken and why other options (especially large issues). If not comment asking them to explain&lt;br /&gt;
&lt;br /&gt;
==Icons==&lt;br /&gt;
Are new icons being introduced? If so, ensure that:&lt;br /&gt;
* the icons abide by our [https://docs.moodle.org/dev/Moodle_icons icon guidelines] with regards to size, design and format&lt;br /&gt;
* the icons are do not unnecessarily add new ways of expressing existing concepts&lt;br /&gt;
* the icons are in a pix folder that makes sense&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [http://moodle.org/plugins/view.php?plugin=local_codechecker Code checker plugin]&lt;br /&gt;
&lt;br /&gt;
[[Category: Processes]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=HQ_component_teams&amp;diff=53524</id>
		<title>HQ component teams</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=HQ_component_teams&amp;diff=53524"/>
		<updated>2017-12-18T08:44:31Z</updated>

		<summary type="html">&lt;p&gt;Damyon: Created page with &amp;quot;As of Dec 2017, at Moodle HQ each core developer is assigned a list of components to lead. They are responsible for triaging the issues in those components, planning the roadm...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As of Dec 2017, at Moodle HQ each core developer is assigned a list of components to lead. They are responsible for triaging the issues in those components, planning the roadmap of issues to be worked on and should be consulted as part of the peer review process for all issues relating to their components. &lt;br /&gt;
&lt;br /&gt;
The current list of component leads is:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Adrian (abgreeve), Mihail (Geshoski)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Blocks, Blog, Book, Filepicker, Glossary, Lesson, Ratings, Reports, Repositories, Resource&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Andrew (dobedobedoh), Ryan (ryanwyllie)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Email, Forum, HTML Editor (Atto), HTML Editor (TinyMCE), Installation, JavaScript, Logging, RSS, Unit tests, User Tours&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Damyon (damyon), Zig (zig)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assignment, Assignment (2.2), Competencies, Database activity module, Backup, Backup: IMS-CC&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;David (dmonllao), Ankit (ankit_frenz)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Analytics, Caching, Global search, Gradebook, Grading methods, Libraries, Performance, Tasks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;David (mudrd8mz), Sara (saraarjona)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Badges, Cohorts, Dashboard (My home), Enrolments, Language, Maths filters, MNet, Plagiarism, Roles / Access, SCORM, Translation, User management, Workshop&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Jake (jaked), Jun (jpataleta )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Automated functional tests (behat), Choice, Comments, Conditional activities, Database SQL/XMLDB, Events API, Files API, Filters, Forms Library, Portfolio, Web Services&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Marina (marina)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Feedback, Hub, Survey, Tags, Wiki (2.x)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Mark (markn)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Activity completion, Authentication, Chat, Course completion, External Tool (IMS-LTI), IMS-CP resource type, LTI provider, Media, Messages&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simey (lameze), Shamim (rezaie9)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Calendar, Groups, Questions, Quiz&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53523</id>
		<title>Peer reviewing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53523"/>
		<updated>2017-12-18T08:19:01Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Testing instructions and automated tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Process=&lt;br /&gt;
&lt;br /&gt;
Peer review process helps to prepare the issue for integration. The peer reviewer is another developer who was not involved in the development process on the issue and therefore can take a fresh look and notice something that original developer might have forgotten during development. It is important to check that the bug actually is present and the code fixes it without creating new regressions. &lt;br /&gt;
&lt;br /&gt;
==Completing Peer review as a community member==&lt;br /&gt;
&lt;br /&gt;
Any other developer can review any change. That is why it is called &#039;peer&#039; review. However, not everyone has the necessary permissions in the tracker to click the buttons &#039;Start peer review&#039;, &#039;Finish peer review&#039; etc. This should not discourage you from looking at other contributors code and providing comments and feedback. The issue will still need to wait for someone with the right permissions to come along and click the buttons, but they can read your review and then need do no more than double-check some points, which will save a lot of time.&lt;br /&gt;
&lt;br /&gt;
To provide feedback to the developer, leave the issue in &amp;quot;Waiting for Peer Review&amp;quot; (since you don&#039;t have permission to do anything else, and also that makes it easy for someone with sufficient permissions to find the issue and move it forwards). Review the code using the checklist below, including any appropriate comments.  Once finished, please post a comment clearly stating the outcome of your review.  If you think it needs more work then indicate what needs to be changes.  If you are happy with the patch, leave a clear comment that you believe this is ready to be made part of Moodle.  This can then easily be seen by a HQ developer or component lead and they can quickly take appropriate action.&lt;br /&gt;
&lt;br /&gt;
If a followup review happens to identify something you did not find, you have an opportunity to expand your knowledge and provide better reviews in the future as well as having saved everybody else some time.&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue is ready to progress might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks again for your contribution. I have reviewed the patch:&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I don&#039;t have permission to use the peer review buttons on this issue. I hope that someone with sufficient permissions will move the issue forwards soon.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue requires further work might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch. I think the following points require further work&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Please indicate If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Peer review for development by HQ or a known common contributor==&lt;br /&gt;
&lt;br /&gt;
When code comes from a HQ developer or external developer who has been contributing significantly to Moodle and is well acquainted with Moodle standards, peer review is limited to checking the code according to the Checklist below. &lt;br /&gt;
&lt;br /&gt;
If everything is fine, the peer reviewer submits the issue for integration. &lt;br /&gt;
&lt;br /&gt;
If some additional work is needed or the author specifically asked not to submit for integration yet, the peer reviewer clicks on “Finish peer review” and the issue state returns to “Development in progress”. Usually the name of the peer reviewer stays on the issue and if a second peer review is requested it is expected that the same Peer reviewer picks it up. If the peer reviewer is not able to do the second review, they should remove their name and comment about it. Otherwise the issue does not appear on “waiting for peer review” dashboard. Please remember that not all jira users have permission to submit for integration.&lt;br /&gt;
&lt;br /&gt;
==Peer review for external developers==&lt;br /&gt;
&lt;br /&gt;
When the code has come from an external developer, the peer reviewer will also help the developer to lead the issue to integration. In this case the peer reviewer should not use “Finish peer review” button. &lt;br /&gt;
&lt;br /&gt;
If the issue needs additional work, the peer reviewer comments about the suggested changes but does not change the status of the issue and it remains as “Peer review in progress”. If the author of the patch does not reply in 4 days, the peer reviewer may select either to complete the patch themselves or reopen the issue. The decision should be based on the amount of work required to complete the solution, for example, changing coding style or commit message, rebasing, backporting, adding testing instructions, etc. should be performed by the peer reviewer. This may require picking the commits into reviewer’s git branch. &lt;br /&gt;
&lt;br /&gt;
It is very important to give the credit to the author of the code by either keeping their authorship on the commit or adding “Thanks to XXXX for providing the patch” to the commit message. If the author of the patch is not in jira-developers group the special user &#039;moodle.com&#039; should be entered in Assignee field.&lt;br /&gt;
&lt;br /&gt;
There could be situations when the patch is incomplete, does not fix the original issue, creates regressions or otherwise is not correct. As stated above, the peer reviewer should comment about it and wait for the feedback from the author. If there is no feedback, or the author can not work on this issue any more, and the peer reviewer also does not find it easy and important enough to complete, the issue needs to be reopened. Button “Fail peer review” (available to HQ developers only) will reset the issue status to “Reopened”. On this screen peer reviewer should remove assignee, peer reviewer and “patch” label from the issue. This way issue will become available again for anybody who want to work on it. All communication will remain in comments and issue history.&lt;br /&gt;
&lt;br /&gt;
If the issue has passed peer review but the integrator or tester has raised some questions about it, then normally the developer who created the patch would be expected to respond. If they do no respond quickly enough, then the peer reviewer is expected to step in and take responsibility for the change they reviewed.&lt;br /&gt;
&lt;br /&gt;
Once the issue is ready for integration, you can submit it to integration on behalf of the developer. Most external developers (those who are not in the jira-developers group) do not have permission to submit their own issues to integration so cannot do it themselves.&lt;br /&gt;
&lt;br /&gt;
==Replies templates==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
I have reviewed your code and can confirm that it addresses the reported issue. We would like to include it in core. Moodle values its contributors and tries to give them credit when possible. If you are interested in your name appearing on the https://moodle.org/dev/contributions.php page you can create a git commit that we will then pull into Moodle. You can learn more about Git and how Moodle uses it at &amp;lt;nowiki&amp;gt;[Git for developers|https://docs.moodle.org/dev/Git_for_developers]&amp;lt;/nowiki&amp;gt; page. Please let me know if you want to prepare a git branch. Or if you don’t have time to go through the whole process at the moment I can pick your patch myself.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Your code looks almost ready for integration into Moodle. There are just some little things that need to be changed to comply with Moodle standards. Can you please take a look at the review results below and tell me if you are able to modify your branch to address them.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
I have reviewed your patch, it addresses the problem and complies with Moodle standards. I&#039;m pushing this issue for integration. Following Moodle &amp;lt;nowiki&amp;gt;[Process|https://docs.moodle.org/dev/Process]&amp;lt;/nowiki&amp;gt; it will go through integration review and testing before being included in the product. There might be additional questions from an integrator and/or a tester at those stages. It would be appreciated if you read tracker emails and can reply to questions if needed. If everything goes well during the next two stages your issue will be included in the next weekly release and your count on https://moodle.org/dev/contributions.php page will increase.&amp;lt;br/&amp;gt;&lt;br /&gt;
Thanks again for your contribution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Unfortunately this patch does not fully address the reported issue. ... DETAILS...&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Even though the code does solve the issue in the short-term it is very likely to create regressions ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
I have spent some time reviewing the patch and I would recommend that you ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Please let me know If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Checklist=&lt;br /&gt;
&lt;br /&gt;
These are points to consider while peer-reviewing issues. Further explanation below.&lt;br /&gt;
&lt;br /&gt;
 [] Syntax&lt;br /&gt;
 [] Output&lt;br /&gt;
 [] Language&lt;br /&gt;
 [] Databases&lt;br /&gt;
 [] Testing (instructions and automated tests)&lt;br /&gt;
 [] Security&lt;br /&gt;
 [] Performance and Clustering&lt;br /&gt;
 [] Documentation&lt;br /&gt;
 [] Git&lt;br /&gt;
 [] Third party code&lt;br /&gt;
 [] Sanity check&lt;br /&gt;
 [] Icons&lt;br /&gt;
&lt;br /&gt;
Acceptable check-marks are Y (for yes), N (for no) or - (for not applicable). All N check-marks should be accompanied by an explanation of the problem that still needs to be addressed.&lt;br /&gt;
&lt;br /&gt;
==Syntax==&lt;br /&gt;
To allow the community of Moodle developers to work together, conventions should be followed.&lt;br /&gt;
&lt;br /&gt;
* The code is easy to understand and, where it isn&#039;t, comments have been provided.&lt;br /&gt;
* Variables are named correctly (all lower case, no camel-case, no underscores).&lt;br /&gt;
* Functions are named correctly (all lower case, no camel-case, underscores allowed).&lt;br /&gt;
* PHP DocBlocks have been updated and adhere to [[Coding_style#Documentation_and_comments|coding style guide]].&lt;br /&gt;
* Where functions are being removed, the [[Deprecation]] process is followed.&lt;br /&gt;
* The code doesn&#039;t use [[Deprecated_functions_in_2.0|deprecated functions]].&lt;br /&gt;
* $_GET, $_POST, $_REQUEST, $_COOKIE, and $_SESSION are never used.&lt;br /&gt;
&lt;br /&gt;
See the [[Coding style]] guide for details.&lt;br /&gt;
&lt;br /&gt;
==Output==&lt;br /&gt;
Output needs to be controlled by renderers to achieve consistency and correct application of themes.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* output renders are used to generate output strings, including HTML tags;&lt;br /&gt;
* HTML output is valid XHTML;&lt;br /&gt;
* no inline styles have been used in HTML output (everything has to be in CSS);&lt;br /&gt;
* CSS has been added to the appropriate CSS files (base, specific area, sometimes canvas); and&lt;br /&gt;
* the code doesn&#039;t use buffered output unless absolutely necessary.&lt;br /&gt;
* all visual output has a RTL alternative included&lt;br /&gt;
&lt;br /&gt;
feedback any notices (E_STRICT, etc) seen into the MDL.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
To achieve appropriate internationalisation of Moodle, language strings must be managed correctly.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* new language strings are named correctly (all lower case, no camel-case, underscores are permissible in some cases);&lt;br /&gt;
* help strings are named and formatted as described in [[Help strings]];&lt;br /&gt;
* language strings are used instead of hard-coded strings for text output;&lt;br /&gt;
* language strings have not been removed or renamed, had their meaning changed or had their parameters changed in stable branches (permitted only in master); and&lt;br /&gt;
* [https://docs.moodle.org/dev/Commit_cheat_sheet#Include_AMOS_script_in_the_commit_if_needed AMOS commands]  have been specified when moving or copying language strings.&lt;br /&gt;
&lt;br /&gt;
==Databases==&lt;br /&gt;
DB calls are the greatest performance bottleneck in Moodle.&lt;br /&gt;
&lt;br /&gt;
If there is SQL code you can test quickly then do so. &lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are minimal DB calls (no excessive use of the DB); and&lt;br /&gt;
* the code uses SQL compatible with all the supported DB engines (check all selected fields appear in an &#039;order by&#039; clause).&lt;br /&gt;
&lt;br /&gt;
==Testing instructions and automated tests==&lt;br /&gt;
It is the developer&#039;s responsibility to test code before integration. Issues should not be sent for peer review without tests so that the peer reviewer can assess their quality and use them to consider the scope of the issue.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are specific testing instructions that state how, as well as what, to test. Please ensure that the testing instructions are in the correct format: [https://docs.moodle.org/dev/Behat Behat gherkin];&lt;br /&gt;
* the assignee has tested according to the instructions and verified that they are passing (This is the responsibility of the assignee, not the peer reviewer)&lt;br /&gt;
* new unit tests have been added when there is a change in functionality; and&lt;br /&gt;
* &#039;&#039;&#039;unit tests pass&#039;&#039;&#039; for related areas where changes have been made.&lt;br /&gt;
* &#039;&#039;&#039;Behat tests pass&#039;&#039;&#039; for related areas where changes have been made, especially when it involved UI changes.&lt;br /&gt;
&lt;br /&gt;
==Security==&lt;br /&gt;
The user community relies on Moodle being responsibly secure.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* user login is checked where an identity is needed;&lt;br /&gt;
* sesskey values are checked before all write actions where appropriate (some read actions as well);&lt;br /&gt;
* capabilities are checked where roles differ; and&lt;br /&gt;
* if the issue itself is a [[Security|security]] issue, the [[Process#Security_issues|security process]] is being followed.&lt;br /&gt;
** Ensure that the fix is &#039;&#039;&#039;not&#039;&#039;&#039; available in a public repository (ie. a personal Github account); stand-alone patches should be provided instead.&lt;br /&gt;
** The issue will not be integrated until just before the next minor version release.&lt;br /&gt;
&lt;br /&gt;
==Performance and clustering==&lt;br /&gt;
It is easy to write code that works sufficiently well when you are working on either small sets of data or with a small number of active users.  Picking performance issues can be quite difficult and can required a complex level of understanding of both the section of code being reviewed, but also other parts that interact with it.&lt;br /&gt;
&lt;br /&gt;
Clustering is when the same code is run on different computers and an end user could send each request to a different computer.  This can produce a number of concurrency issues if not thought through.  One example is;  If you complete an opcache_reset(), no other server except the one you ran it on knows that it happened.  So data can get out of sync.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Any filesystem, database or cache accesses are done in the most efficient way.&lt;br /&gt;
* That any code or function that appear expensive are not in critical paths.  eg; They don&#039;t load on every page.&lt;br /&gt;
* The least possible code is running to complete the task, especially looking for hidden loops.  They can appear from calling functions.&lt;br /&gt;
* Any code that runs is not specific to a single node. (eg opcache_reset())  The ensures clusters will run correctly.&lt;br /&gt;
* If the code could affect performance at all, make sure there is a comment noting what was considered.&lt;br /&gt;
** What they did to mitigate performance impact, or why they thought it wasn&#039;t an issue.&lt;br /&gt;
** Why they made certain trade-offs.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
Work does not stop when code is integrated.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Appropriate [[Tracker_issue_labels|labels]] have been added when there has been a function change, particularly&lt;br /&gt;
** docs_required (any functional change, usually paired with ui_change),&lt;br /&gt;
** dev_docs_required (any change to APIs, usually paired with api_change),&lt;br /&gt;
** ui_change (any functional change, usually paired with docs_required, except ui_change remains permanetly),&lt;br /&gt;
** api_change (any change to APIs that devs will need to know about, usually paired with dev_docs_required, except api_change remains permanetly),&lt;br /&gt;
** unit_test_required and acceptance_test_required, when there are api or ui changes needing improved coverage, and&lt;br /&gt;
** qa_test_required (significant functional change, not covered by unit/acceptance ones).&lt;br /&gt;
* Also, verify that the components for the issue are correctly set, so maintainers (subscribed by default) will be mailed about issues early in the process.&lt;br /&gt;
&lt;br /&gt;
==Git==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the commit matches the [[Coding style#Git_commits|Coding style]]&lt;br /&gt;
* the Git history is clean and the work has been rebased to logical commits; and&lt;br /&gt;
* the original author of the work provided as a patch has been given credit within the commit (as author of in the commit message if changes were made).&lt;br /&gt;
&lt;br /&gt;
==Third party code==&lt;br /&gt;
Does the change contain third party code? If so, ensure that:&lt;br /&gt;
&lt;br /&gt;
* The code is licensed under a [http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses| GPL compatible license].&lt;br /&gt;
* The instructions for upgrading/importing the library and contained within a readme_moodle.txt file.&lt;br /&gt;
* The library is recorded in a thirdparty.xml file, including licensing information.&lt;br /&gt;
* Third party code has been scanned to check for url accessible entry points that could be exploited. These should either be disabled, or if required functionality they should be checked for security weaknesses.&lt;br /&gt;
* Does not duplicate the functionality of any existing api or third party library in core.&lt;br /&gt;
* Any modifications to third party code are recorded in readme_moodle.txt&lt;br /&gt;
&lt;br /&gt;
==Sanity check==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the code seems to solve the described problem completely within its reported scope (and further issues have been created to resolve remaining parts or further refactoring);&lt;br /&gt;
* the code makes sense in relation to the broader codebase (look at the whole function, not just the altered code); and&lt;br /&gt;
* the developer has searched for and fixed other areas that may also have been affected by the same problem.&lt;br /&gt;
* verify that the related component maintainers, if known, have participated and are aware of the issue (as assignee, or existing comments...). If they have not, please perform a friendly &amp;lt;tt&amp;gt;@mention&amp;lt;/tt&amp;gt; to make them aware about the issue.&lt;br /&gt;
* if any version numbers have been changed in [[version.php]] files, then the changes follow [[Moodle_versions#How_to_increment_version_numbers_in_core|the rule for updating version numbers in core]].&lt;br /&gt;
* there are comments on tracker explaining why current approach was taken and why other options (especially large issues). If not comment asking them to explain&lt;br /&gt;
&lt;br /&gt;
==Icons==&lt;br /&gt;
Are new icons being introduced? If so, ensure that:&lt;br /&gt;
* the icons abide by our [https://docs.moodle.org/dev/Moodle_icons icon guidelines] with regards to size, design and format&lt;br /&gt;
* the icons are do not unnecessarily add new ways of expressing existing concepts&lt;br /&gt;
* the icons are in a pix folder that makes sense&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [http://moodle.org/plugins/view.php?plugin=local_codechecker Code checker plugin]&lt;br /&gt;
&lt;br /&gt;
[[Category: Processes]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53522</id>
		<title>Peer reviewing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Peer_reviewing&amp;diff=53522"/>
		<updated>2017-12-18T08:18:30Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Testing instructions and automated tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Process=&lt;br /&gt;
&lt;br /&gt;
Peer review process helps to prepare the issue for integration. The peer reviewer is another developer who was not involved in the development process on the issue and therefore can take a fresh look and notice something that original developer might have forgotten during development. It is important to check that the bug actually is present and the code fixes it without creating new regressions. &lt;br /&gt;
&lt;br /&gt;
==Completing Peer review as a community member==&lt;br /&gt;
&lt;br /&gt;
Any other developer can review any change. That is why it is called &#039;peer&#039; review. However, not everyone has the necessary permissions in the tracker to click the buttons &#039;Start peer review&#039;, &#039;Finish peer review&#039; etc. This should not discourage you from looking at other contributors code and providing comments and feedback. The issue will still need to wait for someone with the right permissions to come along and click the buttons, but they can read your review and then need do no more than double-check some points, which will save a lot of time.&lt;br /&gt;
&lt;br /&gt;
To provide feedback to the developer, leave the issue in &amp;quot;Waiting for Peer Review&amp;quot; (since you don&#039;t have permission to do anything else, and also that makes it easy for someone with sufficient permissions to find the issue and move it forwards). Review the code using the checklist below, including any appropriate comments.  Once finished, please post a comment clearly stating the outcome of your review.  If you think it needs more work then indicate what needs to be changes.  If you are happy with the patch, leave a clear comment that you believe this is ready to be made part of Moodle.  This can then easily be seen by a HQ developer or component lead and they can quickly take appropriate action.&lt;br /&gt;
&lt;br /&gt;
If a followup review happens to identify something you did not find, you have an opportunity to expand your knowledge and provide better reviews in the future as well as having saved everybody else some time.&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue is ready to progress might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks again for your contribution. I have reviewed the patch:&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I don&#039;t have permission to use the peer review buttons on this issue. I hope that someone with sufficient permissions will move the issue forwards soon.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Feedback to indicate the issue requires further work might look like the following;&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch. I think the following points require further work&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[Copy and paste the checklist here, and complete it]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Please indicate If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Peer review for development by HQ or a known common contributor==&lt;br /&gt;
&lt;br /&gt;
When code comes from a HQ developer or external developer who has been contributing significantly to Moodle and is well acquainted with Moodle standards, peer review is limited to checking the code according to the Checklist below. &lt;br /&gt;
&lt;br /&gt;
If everything is fine, the peer reviewer submits the issue for integration. &lt;br /&gt;
&lt;br /&gt;
If some additional work is needed or the author specifically asked not to submit for integration yet, the peer reviewer clicks on “Finish peer review” and the issue state returns to “Development in progress”. Usually the name of the peer reviewer stays on the issue and if a second peer review is requested it is expected that the same Peer reviewer picks it up. If the peer reviewer is not able to do the second review, they should remove their name and comment about it. Otherwise the issue does not appear on “waiting for peer review” dashboard. Please remember that not all jira users have permission to submit for integration.&lt;br /&gt;
&lt;br /&gt;
==Peer review for external developers==&lt;br /&gt;
&lt;br /&gt;
When the code has come from an external developer, the peer reviewer will also help the developer to lead the issue to integration. In this case the peer reviewer should not use “Finish peer review” button. &lt;br /&gt;
&lt;br /&gt;
If the issue needs additional work, the peer reviewer comments about the suggested changes but does not change the status of the issue and it remains as “Peer review in progress”. If the author of the patch does not reply in 4 days, the peer reviewer may select either to complete the patch themselves or reopen the issue. The decision should be based on the amount of work required to complete the solution, for example, changing coding style or commit message, rebasing, backporting, adding testing instructions, etc. should be performed by the peer reviewer. This may require picking the commits into reviewer’s git branch. &lt;br /&gt;
&lt;br /&gt;
It is very important to give the credit to the author of the code by either keeping their authorship on the commit or adding “Thanks to XXXX for providing the patch” to the commit message. If the author of the patch is not in jira-developers group the special user &#039;moodle.com&#039; should be entered in Assignee field.&lt;br /&gt;
&lt;br /&gt;
There could be situations when the patch is incomplete, does not fix the original issue, creates regressions or otherwise is not correct. As stated above, the peer reviewer should comment about it and wait for the feedback from the author. If there is no feedback, or the author can not work on this issue any more, and the peer reviewer also does not find it easy and important enough to complete, the issue needs to be reopened. Button “Fail peer review” (available to HQ developers only) will reset the issue status to “Reopened”. On this screen peer reviewer should remove assignee, peer reviewer and “patch” label from the issue. This way issue will become available again for anybody who want to work on it. All communication will remain in comments and issue history.&lt;br /&gt;
&lt;br /&gt;
If the issue has passed peer review but the integrator or tester has raised some questions about it, then normally the developer who created the patch would be expected to respond. If they do no respond quickly enough, then the peer reviewer is expected to step in and take responsibility for the change they reviewed.&lt;br /&gt;
&lt;br /&gt;
Once the issue is ready for integration, you can submit it to integration on behalf of the developer. Most external developers (those who are not in the jira-developers group) do not have permission to submit their own issues to integration so cannot do it themselves.&lt;br /&gt;
&lt;br /&gt;
==Replies templates==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
I have reviewed your code and can confirm that it addresses the reported issue. We would like to include it in core. Moodle values its contributors and tries to give them credit when possible. If you are interested in your name appearing on the https://moodle.org/dev/contributions.php page you can create a git commit that we will then pull into Moodle. You can learn more about Git and how Moodle uses it at &amp;lt;nowiki&amp;gt;[Git for developers|https://docs.moodle.org/dev/Git_for_developers]&amp;lt;/nowiki&amp;gt; page. Please let me know if you want to prepare a git branch. Or if you don’t have time to go through the whole process at the moment I can pick your patch myself.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Your code looks almost ready for integration into Moodle. There are just some little things that need to be changed to comply with Moodle standards. Can you please take a look at the review results below and tell me if you are able to modify your branch to address them.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
I have reviewed your patch, it addresses the problem and complies with Moodle standards. I&#039;m pushing this issue for integration. Following Moodle &amp;lt;nowiki&amp;gt;[Process|https://docs.moodle.org/dev/Process]&amp;lt;/nowiki&amp;gt; it will go through integration review and testing before being included in the product. There might be additional questions from an integrator and/or a tester at those stages. It would be appreciated if you read tracker emails and can reply to questions if needed. If everything goes well during the next two stages your issue will be included in the next weekly release and your count on https://moodle.org/dev/contributions.php page will increase.&amp;lt;br/&amp;gt;&lt;br /&gt;
Thanks again for your contribution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
Thanks for providing a patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
Unfortunately this patch does not fully address the reported issue. ... DETAILS...&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Even though the code does solve the issue in the short-term it is very likely to create regressions ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
I have spent some time reviewing the patch and I would recommend that you ..... &amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Please let me know If you are willing to continue working on this issue and complete the solution.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Checklist=&lt;br /&gt;
&lt;br /&gt;
These are points to consider while peer-reviewing issues. Further explanation below.&lt;br /&gt;
&lt;br /&gt;
 [] Syntax&lt;br /&gt;
 [] Output&lt;br /&gt;
 [] Language&lt;br /&gt;
 [] Databases&lt;br /&gt;
 [] Testing (instructions and automated tests)&lt;br /&gt;
 [] Security&lt;br /&gt;
 [] Performance and Clustering&lt;br /&gt;
 [] Documentation&lt;br /&gt;
 [] Git&lt;br /&gt;
 [] Third party code&lt;br /&gt;
 [] Sanity check&lt;br /&gt;
 [] Icons&lt;br /&gt;
&lt;br /&gt;
Acceptable check-marks are Y (for yes), N (for no) or - (for not applicable). All N check-marks should be accompanied by an explanation of the problem that still needs to be addressed.&lt;br /&gt;
&lt;br /&gt;
==Syntax==&lt;br /&gt;
To allow the community of Moodle developers to work together, conventions should be followed.&lt;br /&gt;
&lt;br /&gt;
* The code is easy to understand and, where it isn&#039;t, comments have been provided.&lt;br /&gt;
* Variables are named correctly (all lower case, no camel-case, no underscores).&lt;br /&gt;
* Functions are named correctly (all lower case, no camel-case, underscores allowed).&lt;br /&gt;
* PHP DocBlocks have been updated and adhere to [[Coding_style#Documentation_and_comments|coding style guide]].&lt;br /&gt;
* Where functions are being removed, the [[Deprecation]] process is followed.&lt;br /&gt;
* The code doesn&#039;t use [[Deprecated_functions_in_2.0|deprecated functions]].&lt;br /&gt;
* $_GET, $_POST, $_REQUEST, $_COOKIE, and $_SESSION are never used.&lt;br /&gt;
&lt;br /&gt;
See the [[Coding style]] guide for details.&lt;br /&gt;
&lt;br /&gt;
==Output==&lt;br /&gt;
Output needs to be controlled by renderers to achieve consistency and correct application of themes.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* output renders are used to generate output strings, including HTML tags;&lt;br /&gt;
* HTML output is valid XHTML;&lt;br /&gt;
* no inline styles have been used in HTML output (everything has to be in CSS);&lt;br /&gt;
* CSS has been added to the appropriate CSS files (base, specific area, sometimes canvas); and&lt;br /&gt;
* the code doesn&#039;t use buffered output unless absolutely necessary.&lt;br /&gt;
* all visual output has a RTL alternative included&lt;br /&gt;
&lt;br /&gt;
feedback any notices (E_STRICT, etc) seen into the MDL.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
To achieve appropriate internationalisation of Moodle, language strings must be managed correctly.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* new language strings are named correctly (all lower case, no camel-case, underscores are permissible in some cases);&lt;br /&gt;
* help strings are named and formatted as described in [[Help strings]];&lt;br /&gt;
* language strings are used instead of hard-coded strings for text output;&lt;br /&gt;
* language strings have not been removed or renamed, had their meaning changed or had their parameters changed in stable branches (permitted only in master); and&lt;br /&gt;
* [https://docs.moodle.org/dev/Commit_cheat_sheet#Include_AMOS_script_in_the_commit_if_needed AMOS commands]  have been specified when moving or copying language strings.&lt;br /&gt;
&lt;br /&gt;
==Databases==&lt;br /&gt;
DB calls are the greatest performance bottleneck in Moodle.&lt;br /&gt;
&lt;br /&gt;
If there is SQL code you can test quickly then do so. &lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are minimal DB calls (no excessive use of the DB); and&lt;br /&gt;
* the code uses SQL compatible with all the supported DB engines (check all selected fields appear in an &#039;order by&#039; clause).&lt;br /&gt;
&lt;br /&gt;
==Testing instructions and automated tests==&lt;br /&gt;
It is the developer&#039;s responsibility to test code before integration. Issues should not be sent for peer review without tests so that the peer reviewer can assess their quality and use them to consider the scope of the issue.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* there are specific testing instructions that state how, as well as what, to test. Please ensure that the testing instructions are in the correct format: [https://docs.moodle.org/dev/Behat Behat gherkin];&lt;br /&gt;
* the assignee has tested according to the instructions and verified that they are passing&lt;br /&gt;
* new unit tests have been added when there is a change in functionality; and&lt;br /&gt;
* &#039;&#039;&#039;unit tests pass&#039;&#039;&#039; for related areas where changes have been made.&lt;br /&gt;
* &#039;&#039;&#039;Behat tests pass&#039;&#039;&#039; for related areas where changes have been made, especially when it involved UI changes.&lt;br /&gt;
&lt;br /&gt;
==Security==&lt;br /&gt;
The user community relies on Moodle being responsibly secure.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* user login is checked where an identity is needed;&lt;br /&gt;
* sesskey values are checked before all write actions where appropriate (some read actions as well);&lt;br /&gt;
* capabilities are checked where roles differ; and&lt;br /&gt;
* if the issue itself is a [[Security|security]] issue, the [[Process#Security_issues|security process]] is being followed.&lt;br /&gt;
** Ensure that the fix is &#039;&#039;&#039;not&#039;&#039;&#039; available in a public repository (ie. a personal Github account); stand-alone patches should be provided instead.&lt;br /&gt;
** The issue will not be integrated until just before the next minor version release.&lt;br /&gt;
&lt;br /&gt;
==Performance and clustering==&lt;br /&gt;
It is easy to write code that works sufficiently well when you are working on either small sets of data or with a small number of active users.  Picking performance issues can be quite difficult and can required a complex level of understanding of both the section of code being reviewed, but also other parts that interact with it.&lt;br /&gt;
&lt;br /&gt;
Clustering is when the same code is run on different computers and an end user could send each request to a different computer.  This can produce a number of concurrency issues if not thought through.  One example is;  If you complete an opcache_reset(), no other server except the one you ran it on knows that it happened.  So data can get out of sync.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Any filesystem, database or cache accesses are done in the most efficient way.&lt;br /&gt;
* That any code or function that appear expensive are not in critical paths.  eg; They don&#039;t load on every page.&lt;br /&gt;
* The least possible code is running to complete the task, especially looking for hidden loops.  They can appear from calling functions.&lt;br /&gt;
* Any code that runs is not specific to a single node. (eg opcache_reset())  The ensures clusters will run correctly.&lt;br /&gt;
* If the code could affect performance at all, make sure there is a comment noting what was considered.&lt;br /&gt;
** What they did to mitigate performance impact, or why they thought it wasn&#039;t an issue.&lt;br /&gt;
** Why they made certain trade-offs.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
Work does not stop when code is integrated.&lt;br /&gt;
&lt;br /&gt;
Ensure that:&lt;br /&gt;
* Appropriate [[Tracker_issue_labels|labels]] have been added when there has been a function change, particularly&lt;br /&gt;
** docs_required (any functional change, usually paired with ui_change),&lt;br /&gt;
** dev_docs_required (any change to APIs, usually paired with api_change),&lt;br /&gt;
** ui_change (any functional change, usually paired with docs_required, except ui_change remains permanetly),&lt;br /&gt;
** api_change (any change to APIs that devs will need to know about, usually paired with dev_docs_required, except api_change remains permanetly),&lt;br /&gt;
** unit_test_required and acceptance_test_required, when there are api or ui changes needing improved coverage, and&lt;br /&gt;
** qa_test_required (significant functional change, not covered by unit/acceptance ones).&lt;br /&gt;
* Also, verify that the components for the issue are correctly set, so maintainers (subscribed by default) will be mailed about issues early in the process.&lt;br /&gt;
&lt;br /&gt;
==Git==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the commit matches the [[Coding style#Git_commits|Coding style]]&lt;br /&gt;
* the Git history is clean and the work has been rebased to logical commits; and&lt;br /&gt;
* the original author of the work provided as a patch has been given credit within the commit (as author of in the commit message if changes were made).&lt;br /&gt;
&lt;br /&gt;
==Third party code==&lt;br /&gt;
Does the change contain third party code? If so, ensure that:&lt;br /&gt;
&lt;br /&gt;
* The code is licensed under a [http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses| GPL compatible license].&lt;br /&gt;
* The instructions for upgrading/importing the library and contained within a readme_moodle.txt file.&lt;br /&gt;
* The library is recorded in a thirdparty.xml file, including licensing information.&lt;br /&gt;
* Third party code has been scanned to check for url accessible entry points that could be exploited. These should either be disabled, or if required functionality they should be checked for security weaknesses.&lt;br /&gt;
* Does not duplicate the functionality of any existing api or third party library in core.&lt;br /&gt;
* Any modifications to third party code are recorded in readme_moodle.txt&lt;br /&gt;
&lt;br /&gt;
==Sanity check==&lt;br /&gt;
Ensure that:&lt;br /&gt;
* the code seems to solve the described problem completely within its reported scope (and further issues have been created to resolve remaining parts or further refactoring);&lt;br /&gt;
* the code makes sense in relation to the broader codebase (look at the whole function, not just the altered code); and&lt;br /&gt;
* the developer has searched for and fixed other areas that may also have been affected by the same problem.&lt;br /&gt;
* verify that the related component maintainers, if known, have participated and are aware of the issue (as assignee, or existing comments...). If they have not, please perform a friendly &amp;lt;tt&amp;gt;@mention&amp;lt;/tt&amp;gt; to make them aware about the issue.&lt;br /&gt;
* if any version numbers have been changed in [[version.php]] files, then the changes follow [[Moodle_versions#How_to_increment_version_numbers_in_core|the rule for updating version numbers in core]].&lt;br /&gt;
* there are comments on tracker explaining why current approach was taken and why other options (especially large issues). If not comment asking them to explain&lt;br /&gt;
&lt;br /&gt;
==Icons==&lt;br /&gt;
Are new icons being introduced? If so, ensure that:&lt;br /&gt;
* the icons abide by our [https://docs.moodle.org/dev/Moodle_icons icon guidelines] with regards to size, design and format&lt;br /&gt;
* the icons are do not unnecessarily add new ways of expressing existing concepts&lt;br /&gt;
* the icons are in a pix folder that makes sense&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [http://moodle.org/plugins/view.php?plugin=local_codechecker Code checker plugin]&lt;br /&gt;
&lt;br /&gt;
[[Category: Processes]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Integration_Review&amp;diff=53433</id>
		<title>Integration Review</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Integration_Review&amp;diff=53433"/>
		<updated>2017-11-24T02:02:47Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* On-sync period */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Purpose==&lt;br /&gt;
&lt;br /&gt;
The purpose of the integration review is to:&lt;br /&gt;
* Ensure consistent quality across the codebase&lt;br /&gt;
* Ensure that pedagogical aims of Moodle are at the forefront of any change&lt;br /&gt;
* Take into consideration the holistic view of moodle, looking at the impact beyond where the original developer was focused&lt;br /&gt;
* Provide guidance and feedback to developers, helping them learn and improve &lt;br /&gt;
* Consider &#039;&#039;&#039;other perspectives&#039;&#039;&#039; of other users perhaps not considered by original developers e.g.&lt;br /&gt;
** Teachers&lt;br /&gt;
** Students&lt;br /&gt;
** Administrators&lt;br /&gt;
**Third-party developers&lt;br /&gt;
&lt;br /&gt;
==Integration Review Process==&lt;br /&gt;
&lt;br /&gt;
# Run automated pre-checks against the continuous integration server. (In future this can be automated and also moved into a publicly accessible domain.)&lt;br /&gt;
# Final code review, much like the peer review, except that this is the final check. To include&lt;br /&gt;
## Takes place in-situ (integrated) to examine the impact to other integrated issues&lt;br /&gt;
## Checking against the coding guidelines - syntax/whitespace&lt;br /&gt;
## Moodleisms - using the built-in API functions where appropriate&lt;br /&gt;
## Cross-DB compatibility &lt;br /&gt;
## Security&lt;br /&gt;
# Check purpose - the patch needs to fix the issue reported.&lt;br /&gt;
# Verify target branches are appropriated. They must match 100% the rules defined for [[#Backporting|backporting issues]].&lt;br /&gt;
# Ensure backwards compatibility is maintained. As a starting point backwards compatibility must always be maintained. Where backwards compatibility is affected it should be:&lt;br /&gt;
## Well discussed with evidence of justification&lt;br /&gt;
## Documented and communicated to the community &lt;br /&gt;
# Verify that components are correct and check the right people have been involved (e.g. component maintainers)&lt;br /&gt;
# For fundamental changes, check that a thread has been started in an appropriate forum, and other Moodlers, given enough time to comment.&lt;br /&gt;
# Tests - must be written to guide tester to verify the fix is working.&lt;br /&gt;
## Unit test - very much preferred if applicable&lt;br /&gt;
## at end of Wednesday, ensure testing is going to complete as expected. else take other actions (speak to test manager)&lt;br /&gt;
# Performance - we have to look at maintaining optimum code here, as far as simple patches that can affect performance. (simple optimisations)&lt;br /&gt;
# Scalability - if master only - we&#039;re looking far future, stable branches may not be lucky to get such improvements.&lt;br /&gt;
# git authorship is correct vs committer + credits due are mentioned + email addresses&lt;br /&gt;
# Documentation / PHP Doc / readability&lt;br /&gt;
# [[Tracker_issue_labels]] which might need adding. Particularly:&lt;br /&gt;
## docs_required / dev_docs_required / release_notes: About which type of documentation is required for the issue.&lt;br /&gt;
## ui_change / api_change: About the implications of the change.&lt;br /&gt;
## unit_test_required / acceptance_test_required / qa_test_required: About the need to cover the issue with some test.&lt;br /&gt;
# Fixed Version after integration - is the versions that the issue is patched for. (A rule here: mention master if its the only branched fixed. If not, don&#039;t mention master)&lt;br /&gt;
# Update the workflow counters&lt;br /&gt;
## If an issue is in need of a second review +1 to errors column in integration workflow counters&lt;br /&gt;
&lt;br /&gt;
== Integration Principles ==&lt;br /&gt;
&lt;br /&gt;
Integration (non-technical but philosophical) principles (4-5 words determining if something has to be integrated/backported or no):&lt;br /&gt;
&lt;br /&gt;
# safety: if something does not look safe, stable, it won&#039;t land. Be conservative.&lt;br /&gt;
# security: all security issues, if not breaking principle (1) will be integrated/backported to all security-supported versions.&lt;br /&gt;
# community: Anything not useful for the community (or against it) won&#039;t be integrated/backported. We can measure the community as 10%HQ, 10%Partners, 10%Core developers, 20%Admins, 20%Teachers, 30%Students - not exact science, just one approximation, you know). Question yourself how the change will affect those groups and ensure positives are bigger always (only affected groups count). All community issues, if not breaking principles (1) and (2) will be integrated.&lt;br /&gt;
# typology:  bug fixes will be always integrated/backported to all the supported braches if none of the principles (1), (2) and (3) are violated. Also, partially-unsupported branches can receive some if they are important enough. Improvements and new features go, exclusively, to master only, that&#039;s the main reason for short release periods. We *must* not make exceptions to this.&lt;br /&gt;
# priority: issues will be &amp;quot;ordered down&amp;quot; by priority down (where priority is a [https://tracker.moodle.org/issues/?filter=14000 mix of various factors], dynamic). And will be integrated in that order. If something has to be delayed, better if it is low priority. Once again, nothing here can break any of the previous principles.&lt;br /&gt;
# tests: unit tests and acceptance tests will backported as far as possible without breaking (1) and (2). New features required to implement tests will be backported if the API is 100% backwards compatible. &lt;br /&gt;
If all the principles are fulfilled, the answer for &amp;quot;should I integrate this?&amp;quot; is, &amp;quot;yes, please!&amp;quot;&lt;br /&gt;
(apart from technical findings, of course, that can lead to the issue being not integrated/reopened at last, these principles are 100% philosophical)&lt;br /&gt;
&lt;br /&gt;
==Schedule==&lt;br /&gt;
===In normal periods ===&lt;br /&gt;
The integrators adhere to the following schedule:&lt;br /&gt;
&lt;br /&gt;
* Sunday 22:00 UTC: Issues waiting for integration brought into current integration.&lt;br /&gt;
* Monday: Integration&lt;br /&gt;
* Tuesday:  Integration&lt;br /&gt;
* Wednesday: [[Testing of integrated issues#The testing process|Testing]]. Integrators duties during this time are to monitor, facilitate and &#039;problem solve&#039; the testing process.&lt;br /&gt;
* Thursday: Testing should be completed by 07:00 UTC, at which time remaining testing failures will be reverted and reopened. The release process follows.&lt;br /&gt;
* Friday: Should be kept free from integration. Integration systems are maintained during this time.&lt;br /&gt;
&lt;br /&gt;
=== During continuous integration/Freeze/QA period ===&lt;br /&gt;
During the continuous integration period the integration team are continuously focused on producing regular builds of master to facilitate QA and fast fixes to issues identified.&lt;br /&gt;
&lt;br /&gt;
* Throughout:&lt;br /&gt;
** Issues are picked on a one by one basis, prioritising [https://docs.moodle.org/dev/QA_testing#Resetting_tests QA blockers] and master regressions (MUST FIX) issues.&lt;br /&gt;
** Any non bug fix issues are given the &#039;&#039;integration_held&#039;&#039; label and are explicitly not picked for integration. Still, anybody is able to add a reasoned &#039;&#039;unhold_requested&#039;&#039; label to those issues in order to get them unblocked by the development managers. Note this does not guarantee the issue to land before release, but just gives it a chance to be integrated like any other issue.&lt;br /&gt;
** Our goal is to achieve &#039;releaseability&#039; throughout, so we stop integrating to ensure a release happens&lt;br /&gt;
&lt;br /&gt;
So, basically, once the QA cycle begins (4 weeks before release) and until release, we do organize work as follows:&lt;br /&gt;
* Continuous officially begins. Everybody is on integration. Until end of on-sync period.&lt;br /&gt;
* Monday: Integration and [[Testing of integrated issues#Differences in test process during continuous integration periods|testing]] happens.&lt;br /&gt;
* Tuesday: Integration happens until 12:00 (UTC+8), [[Testing of integrated issues#Differences in test process during continuous integration periods|afterwards we try to achieve 100% &#039;Test Passed&#039;]] and stop integrating any untested changes until a master release is produced.&lt;br /&gt;
* Wednesday: [Assuming a master release has been rolled] Integration and testing continues&lt;br /&gt;
* Thursday: Integration and testing continues&lt;br /&gt;
* Friday: Integration happens until 12:00 (UTC+8), afterwards we try to achieve 100% &#039;Test Passed&#039; and stop integrating any untested changes until a master release is produced.&lt;br /&gt;
&lt;br /&gt;
Note: along this period we always release as many stable weeklies as master rolls (on-demand, beta, rc) happen (see MDLSITE-3470). Note that those tags are not simply tags but they come with some important implications, aiming to stability, safety and clarity. Integrators will try to remain loyal to them, be warned:&lt;br /&gt;
&lt;br /&gt;
* Once beta is released... new features or improvements &amp;quot;unrelated&amp;quot; with the release will be really harder to be accepted. A +4 from developer managers (normally +3 is enough) will be needed to proceed with the issue. Integrators vote will be, always, -1.&lt;br /&gt;
* Once rc are released... new features or improvements &amp;quot;unrelated&amp;quot; with the release are forbidden. No unhold voting, no managers. Simply forbidden.&lt;br /&gt;
* Last week before release, only &amp;quot;related&amp;quot; issues will be picked for integration. Everything else (bug fixes included) are kept out (given the &amp;quot;integration_held&amp;quot; label) if unrelated, at very least until after release. No distractions.&lt;br /&gt;
Definition: &amp;quot;related&amp;quot;: said to be a followup of required to release, planned OR security issue.&lt;br /&gt;
&lt;br /&gt;
=== On-sync period ===&lt;br /&gt;
Immediately after a major release and for a short period (right now, 2 weeks, matching 1st HQ sprint duration), the integration team is under the named on-sync period.&lt;br /&gt;
&lt;br /&gt;
At all effects, it&#039;s a normal period (see above), and weeklies are produced for supported stable branches and also for master. But with one important rule/goal:&lt;br /&gt;
&lt;br /&gt;
* We must keep the latest stable branch and master 100% on-sync, specifically about versions and upgrade steps.&lt;br /&gt;
&lt;br /&gt;
This simple, but important constraint, is there to facilitate the integration of impeding bugs, needing urgent resolution, and by keeping them the same, we guarantee that any stable or master fix will apply without problems to both branches. Of course, in order to achieve the rule, these must be also observed along the period:&lt;br /&gt;
&lt;br /&gt;
* We continuously perform diffs between the latest stable and master, controlling that we are on-sync. Any non-authorised difference is cleaned (rewritten).&lt;br /&gt;
* Both improvements and new features (and, in general, everything leading to divergence) are held until the on-sync period ends.&lt;br /&gt;
&lt;br /&gt;
Last, but not less important, a second goal for this on-sync period is:&lt;br /&gt;
&lt;br /&gt;
* The environmental requirements &#039;&#039;&#039;for next major version&#039;&#039;&#039; [[Release process#2_weeks_after|must be agreed and resolved so they can land to master]] early in the process, remaining defined and stable over the next, 6 months of, development cycle.&lt;br /&gt;
&lt;br /&gt;
At the beginning of the on-sync period, we &amp;quot;unhold&amp;quot; all bugs that were held during the last week before the release because they were unrelated to the release. At the end of the onsync period we &amp;quot;unhold&amp;quot; all new features that were submitted after the code freeze for the the release.&lt;br /&gt;
&lt;br /&gt;
== Backporting ==&lt;br /&gt;
&lt;br /&gt;
Whilst we&#039;d all like all Moodle users to be using our latest and greatest code, there is a balance to strike between improving our software and maintaining stability (both in terms of regressions, but also training and documentation materials). Large amounts of change on the stable branches make the lives difficult for institutions to manage upgrades between point releases.&lt;br /&gt;
&lt;br /&gt;
==== General policy ====&lt;br /&gt;
Our general policy is as follows:&lt;br /&gt;
&lt;br /&gt;
* Bug fixes will be backported to all (and only to) supported stable branches. &lt;br /&gt;
** When fixing a bug, please provide a fix for all supported stable branches. &lt;br /&gt;
** If a fix doesn&#039;t make sense to be backported to every branch, please make it clear in the issue.&lt;br /&gt;
* Improvements or new features will only land in master.&lt;br /&gt;
&lt;br /&gt;
==== Process for requesting a non bug-fix backport ====&lt;br /&gt;
Improvements or new features can be requested to be backported to the stable branches. We urge developers to consider this request carefully. In recent years, Moodle has moved to a short and predicatable time based release schedule and we use a very effective distributed source control system. Both of these process changes should ensure that a change not being backported to the stable branches is not as problematic as it may have used to be. &lt;br /&gt;
&lt;br /&gt;
Should you feel that a new feature or improvement needs backporting, please follow this process:&lt;br /&gt;
&lt;br /&gt;
# File a new issue.&lt;br /&gt;
# Set the issue title using our backport template guide.  (i.e. &amp;quot;Fix forum alignment (backport of MDL-99999)&amp;quot;) - see [https://docs.moodle.org/dev/Tracker_guide#Tracker_fields Tracker_guide]&lt;br /&gt;
# Link the original issue&lt;br /&gt;
# You should include clear rationale for the request to backport&lt;br /&gt;
&lt;br /&gt;
The integration team will process backport requests, with the following guidelines:&lt;br /&gt;
# The integration team will together consider each request individually considering the needs of the community (influenced by forum posts, moodle partners, nagging developers etc).&lt;br /&gt;
# Backports will happen not earlier than 3 weeks and not later than 2 months after the issue has landed in master.&lt;br /&gt;
# Rationale will be given for rejection&lt;br /&gt;
&lt;br /&gt;
If the backport request is approved, please follow the usual development process to submit the feature or improvement on earlier branches.&lt;br /&gt;
&lt;br /&gt;
==== Polite note about bug classification ====&lt;br /&gt;
Many issues can be appropiately classified as borderline bugfix/improvements. We politely request that developers do not try and &#039;game the system&#039; by clasifying their improvements as bugs intentionally. If your fix is in a grey area, please state your case for it being a bug fix clearly. The integration team will use their discretion where necessary.&lt;br /&gt;
&lt;br /&gt;
==== Backport fixes to unsupported branches ====&lt;br /&gt;
* Given the [[#General policy|general policy]] above, only supported stable branches are candidates normally.&lt;br /&gt;
* Also security and dataloss issues are accepted to be fixed into security-only supported branches.&lt;br /&gt;
* Apart from the previous, backport to unsupported branches only will happen when the issue is a &#039;&#039;&#039;direct regression caused by a bug fix&#039;&#039;&#039; introduced by the latest releases. This applies to both security-only and out-of-support branches. A new weekly release will be performed including the fix.&lt;br /&gt;
&lt;br /&gt;
== Fixing issues identified during integration review/ testing ==&lt;br /&gt;
&lt;br /&gt;
When a branch has been merged by an integrator, it is important that you do not modify the existing history of your branch (e.g. by amending or squashing your commits) and instead add new commits on top. If you modify the history of your branch, it makes it extremely difficult for the integrator to merge your changes (and see the differences).&lt;br /&gt;
&lt;br /&gt;
As a general rule, this means that if your issue has entered the &#039;in integration review&#039; stage of the development process, please only add new commits on top of your existing commits. There are circumstances when your issue will be &#039;in integration review&#039; but not merged (and thus possible to squash changes) but if in any doubt, please add new commits and ask the integrator to squash your changes for you.&lt;br /&gt;
&lt;br /&gt;
== Commit squashing ==&lt;br /&gt;
&lt;br /&gt;
The Integration team will sometimes recommend squashing commits when things do not look natural (and may offer to do this for you), especially when there are &amp;quot;fix-commits&amp;quot; in the history happening before integration. But [https://moodle.org/local/chatlogs/index.php?conversationid=13987#c489485 our policy] is &amp;quot;if you want your history of commits to look like bad, it&#039;s your history&amp;quot;. You will not be forced to squash your changes. You should pay close attention to https://docs.moodle.org/dev/Coding_style#Git_commits and intend to  &amp;quot;Tell a perfect, cleaned up version of the history. As if the code was written perfectly first time.&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Category: Processes]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Integration_Review&amp;diff=53432</id>
		<title>Integration Review</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Integration_Review&amp;diff=53432"/>
		<updated>2017-11-24T02:00:00Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* During continuous integration/Freeze/QA period */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Purpose==&lt;br /&gt;
&lt;br /&gt;
The purpose of the integration review is to:&lt;br /&gt;
* Ensure consistent quality across the codebase&lt;br /&gt;
* Ensure that pedagogical aims of Moodle are at the forefront of any change&lt;br /&gt;
* Take into consideration the holistic view of moodle, looking at the impact beyond where the original developer was focused&lt;br /&gt;
* Provide guidance and feedback to developers, helping them learn and improve &lt;br /&gt;
* Consider &#039;&#039;&#039;other perspectives&#039;&#039;&#039; of other users perhaps not considered by original developers e.g.&lt;br /&gt;
** Teachers&lt;br /&gt;
** Students&lt;br /&gt;
** Administrators&lt;br /&gt;
**Third-party developers&lt;br /&gt;
&lt;br /&gt;
==Integration Review Process==&lt;br /&gt;
&lt;br /&gt;
# Run automated pre-checks against the continuous integration server. (In future this can be automated and also moved into a publicly accessible domain.)&lt;br /&gt;
# Final code review, much like the peer review, except that this is the final check. To include&lt;br /&gt;
## Takes place in-situ (integrated) to examine the impact to other integrated issues&lt;br /&gt;
## Checking against the coding guidelines - syntax/whitespace&lt;br /&gt;
## Moodleisms - using the built-in API functions where appropriate&lt;br /&gt;
## Cross-DB compatibility &lt;br /&gt;
## Security&lt;br /&gt;
# Check purpose - the patch needs to fix the issue reported.&lt;br /&gt;
# Verify target branches are appropriated. They must match 100% the rules defined for [[#Backporting|backporting issues]].&lt;br /&gt;
# Ensure backwards compatibility is maintained. As a starting point backwards compatibility must always be maintained. Where backwards compatibility is affected it should be:&lt;br /&gt;
## Well discussed with evidence of justification&lt;br /&gt;
## Documented and communicated to the community &lt;br /&gt;
# Verify that components are correct and check the right people have been involved (e.g. component maintainers)&lt;br /&gt;
# For fundamental changes, check that a thread has been started in an appropriate forum, and other Moodlers, given enough time to comment.&lt;br /&gt;
# Tests - must be written to guide tester to verify the fix is working.&lt;br /&gt;
## Unit test - very much preferred if applicable&lt;br /&gt;
## at end of Wednesday, ensure testing is going to complete as expected. else take other actions (speak to test manager)&lt;br /&gt;
# Performance - we have to look at maintaining optimum code here, as far as simple patches that can affect performance. (simple optimisations)&lt;br /&gt;
# Scalability - if master only - we&#039;re looking far future, stable branches may not be lucky to get such improvements.&lt;br /&gt;
# git authorship is correct vs committer + credits due are mentioned + email addresses&lt;br /&gt;
# Documentation / PHP Doc / readability&lt;br /&gt;
# [[Tracker_issue_labels]] which might need adding. Particularly:&lt;br /&gt;
## docs_required / dev_docs_required / release_notes: About which type of documentation is required for the issue.&lt;br /&gt;
## ui_change / api_change: About the implications of the change.&lt;br /&gt;
## unit_test_required / acceptance_test_required / qa_test_required: About the need to cover the issue with some test.&lt;br /&gt;
# Fixed Version after integration - is the versions that the issue is patched for. (A rule here: mention master if its the only branched fixed. If not, don&#039;t mention master)&lt;br /&gt;
# Update the workflow counters&lt;br /&gt;
## If an issue is in need of a second review +1 to errors column in integration workflow counters&lt;br /&gt;
&lt;br /&gt;
== Integration Principles ==&lt;br /&gt;
&lt;br /&gt;
Integration (non-technical but philosophical) principles (4-5 words determining if something has to be integrated/backported or no):&lt;br /&gt;
&lt;br /&gt;
# safety: if something does not look safe, stable, it won&#039;t land. Be conservative.&lt;br /&gt;
# security: all security issues, if not breaking principle (1) will be integrated/backported to all security-supported versions.&lt;br /&gt;
# community: Anything not useful for the community (or against it) won&#039;t be integrated/backported. We can measure the community as 10%HQ, 10%Partners, 10%Core developers, 20%Admins, 20%Teachers, 30%Students - not exact science, just one approximation, you know). Question yourself how the change will affect those groups and ensure positives are bigger always (only affected groups count). All community issues, if not breaking principles (1) and (2) will be integrated.&lt;br /&gt;
# typology:  bug fixes will be always integrated/backported to all the supported braches if none of the principles (1), (2) and (3) are violated. Also, partially-unsupported branches can receive some if they are important enough. Improvements and new features go, exclusively, to master only, that&#039;s the main reason for short release periods. We *must* not make exceptions to this.&lt;br /&gt;
# priority: issues will be &amp;quot;ordered down&amp;quot; by priority down (where priority is a [https://tracker.moodle.org/issues/?filter=14000 mix of various factors], dynamic). And will be integrated in that order. If something has to be delayed, better if it is low priority. Once again, nothing here can break any of the previous principles.&lt;br /&gt;
# tests: unit tests and acceptance tests will backported as far as possible without breaking (1) and (2). New features required to implement tests will be backported if the API is 100% backwards compatible. &lt;br /&gt;
If all the principles are fulfilled, the answer for &amp;quot;should I integrate this?&amp;quot; is, &amp;quot;yes, please!&amp;quot;&lt;br /&gt;
(apart from technical findings, of course, that can lead to the issue being not integrated/reopened at last, these principles are 100% philosophical)&lt;br /&gt;
&lt;br /&gt;
==Schedule==&lt;br /&gt;
===In normal periods ===&lt;br /&gt;
The integrators adhere to the following schedule:&lt;br /&gt;
&lt;br /&gt;
* Sunday 22:00 UTC: Issues waiting for integration brought into current integration.&lt;br /&gt;
* Monday: Integration&lt;br /&gt;
* Tuesday:  Integration&lt;br /&gt;
* Wednesday: [[Testing of integrated issues#The testing process|Testing]]. Integrators duties during this time are to monitor, facilitate and &#039;problem solve&#039; the testing process.&lt;br /&gt;
* Thursday: Testing should be completed by 07:00 UTC, at which time remaining testing failures will be reverted and reopened. The release process follows.&lt;br /&gt;
* Friday: Should be kept free from integration. Integration systems are maintained during this time.&lt;br /&gt;
&lt;br /&gt;
=== During continuous integration/Freeze/QA period ===&lt;br /&gt;
During the continuous integration period the integration team are continuously focused on producing regular builds of master to facilitate QA and fast fixes to issues identified.&lt;br /&gt;
&lt;br /&gt;
* Throughout:&lt;br /&gt;
** Issues are picked on a one by one basis, prioritising [https://docs.moodle.org/dev/QA_testing#Resetting_tests QA blockers] and master regressions (MUST FIX) issues.&lt;br /&gt;
** Any non bug fix issues are given the &#039;&#039;integration_held&#039;&#039; label and are explicitly not picked for integration. Still, anybody is able to add a reasoned &#039;&#039;unhold_requested&#039;&#039; label to those issues in order to get them unblocked by the development managers. Note this does not guarantee the issue to land before release, but just gives it a chance to be integrated like any other issue.&lt;br /&gt;
** Our goal is to achieve &#039;releaseability&#039; throughout, so we stop integrating to ensure a release happens&lt;br /&gt;
&lt;br /&gt;
So, basically, once the QA cycle begins (4 weeks before release) and until release, we do organize work as follows:&lt;br /&gt;
* Continuous officially begins. Everybody is on integration. Until end of on-sync period.&lt;br /&gt;
* Monday: Integration and [[Testing of integrated issues#Differences in test process during continuous integration periods|testing]] happens.&lt;br /&gt;
* Tuesday: Integration happens until 12:00 (UTC+8), [[Testing of integrated issues#Differences in test process during continuous integration periods|afterwards we try to achieve 100% &#039;Test Passed&#039;]] and stop integrating any untested changes until a master release is produced.&lt;br /&gt;
* Wednesday: [Assuming a master release has been rolled] Integration and testing continues&lt;br /&gt;
* Thursday: Integration and testing continues&lt;br /&gt;
* Friday: Integration happens until 12:00 (UTC+8), afterwards we try to achieve 100% &#039;Test Passed&#039; and stop integrating any untested changes until a master release is produced.&lt;br /&gt;
&lt;br /&gt;
Note: along this period we always release as many stable weeklies as master rolls (on-demand, beta, rc) happen (see MDLSITE-3470). Note that those tags are not simply tags but they come with some important implications, aiming to stability, safety and clarity. Integrators will try to remain loyal to them, be warned:&lt;br /&gt;
&lt;br /&gt;
* Once beta is released... new features or improvements &amp;quot;unrelated&amp;quot; with the release will be really harder to be accepted. A +4 from developer managers (normally +3 is enough) will be needed to proceed with the issue. Integrators vote will be, always, -1.&lt;br /&gt;
* Once rc are released... new features or improvements &amp;quot;unrelated&amp;quot; with the release are forbidden. No unhold voting, no managers. Simply forbidden.&lt;br /&gt;
* Last week before release, only &amp;quot;related&amp;quot; issues will be picked for integration. Everything else (bug fixes included) are kept out (given the &amp;quot;integration_held&amp;quot; label) if unrelated, at very least until after release. No distractions.&lt;br /&gt;
Definition: &amp;quot;related&amp;quot;: said to be a followup of required to release, planned OR security issue.&lt;br /&gt;
&lt;br /&gt;
=== On-sync period ===&lt;br /&gt;
Immediately after a major release and for a short period (right now, 2 weeks, matching 1st HQ sprint duration), the integration team is under the named on-sync period.&lt;br /&gt;
&lt;br /&gt;
At all effects, it&#039;s a normal period (see above), and weeklies are produced for supported stable branches and also for master. But with one important rule/goal:&lt;br /&gt;
&lt;br /&gt;
* We must keep the latest stable branch and master 100% on-sync, specifically about versions and upgrade steps.&lt;br /&gt;
&lt;br /&gt;
This simple, but important constraint, is there to facilitate the integration of impeding bugs, needing urgent resolution, and by keeping them the same, we guarantee that any stable or master fix will apply without problems to both branches. Of course, in order to achieve the rule, these must be also observed along the period:&lt;br /&gt;
&lt;br /&gt;
* We continuously perform diffs between the latest stable and master, controlling that we are on-sync. Any non-authorised difference is cleaned (rewritten).&lt;br /&gt;
* Both improvements and new features (and, in general, everything leading to divergence) are held until the on-sync period ends.&lt;br /&gt;
&lt;br /&gt;
Last, but not less important, a second goal for this on-sync period is:&lt;br /&gt;
&lt;br /&gt;
* The environmental requirements &#039;&#039;&#039;for next major version&#039;&#039;&#039; [[Release process#2_weeks_after|must be agreed and resolved so they can land to master]] early in the process, remaining defined and stable over the next, 6 months of, development cycle.&lt;br /&gt;
&lt;br /&gt;
== Backporting ==&lt;br /&gt;
&lt;br /&gt;
Whilst we&#039;d all like all Moodle users to be using our latest and greatest code, there is a balance to strike between improving our software and maintaining stability (both in terms of regressions, but also training and documentation materials). Large amounts of change on the stable branches make the lives difficult for institutions to manage upgrades between point releases.&lt;br /&gt;
&lt;br /&gt;
==== General policy ====&lt;br /&gt;
Our general policy is as follows:&lt;br /&gt;
&lt;br /&gt;
* Bug fixes will be backported to all (and only to) supported stable branches. &lt;br /&gt;
** When fixing a bug, please provide a fix for all supported stable branches. &lt;br /&gt;
** If a fix doesn&#039;t make sense to be backported to every branch, please make it clear in the issue.&lt;br /&gt;
* Improvements or new features will only land in master.&lt;br /&gt;
&lt;br /&gt;
==== Process for requesting a non bug-fix backport ====&lt;br /&gt;
Improvements or new features can be requested to be backported to the stable branches. We urge developers to consider this request carefully. In recent years, Moodle has moved to a short and predicatable time based release schedule and we use a very effective distributed source control system. Both of these process changes should ensure that a change not being backported to the stable branches is not as problematic as it may have used to be. &lt;br /&gt;
&lt;br /&gt;
Should you feel that a new feature or improvement needs backporting, please follow this process:&lt;br /&gt;
&lt;br /&gt;
# File a new issue.&lt;br /&gt;
# Set the issue title using our backport template guide.  (i.e. &amp;quot;Fix forum alignment (backport of MDL-99999)&amp;quot;) - see [https://docs.moodle.org/dev/Tracker_guide#Tracker_fields Tracker_guide]&lt;br /&gt;
# Link the original issue&lt;br /&gt;
# You should include clear rationale for the request to backport&lt;br /&gt;
&lt;br /&gt;
The integration team will process backport requests, with the following guidelines:&lt;br /&gt;
# The integration team will together consider each request individually considering the needs of the community (influenced by forum posts, moodle partners, nagging developers etc).&lt;br /&gt;
# Backports will happen not earlier than 3 weeks and not later than 2 months after the issue has landed in master.&lt;br /&gt;
# Rationale will be given for rejection&lt;br /&gt;
&lt;br /&gt;
If the backport request is approved, please follow the usual development process to submit the feature or improvement on earlier branches.&lt;br /&gt;
&lt;br /&gt;
==== Polite note about bug classification ====&lt;br /&gt;
Many issues can be appropiately classified as borderline bugfix/improvements. We politely request that developers do not try and &#039;game the system&#039; by clasifying their improvements as bugs intentionally. If your fix is in a grey area, please state your case for it being a bug fix clearly. The integration team will use their discretion where necessary.&lt;br /&gt;
&lt;br /&gt;
==== Backport fixes to unsupported branches ====&lt;br /&gt;
* Given the [[#General policy|general policy]] above, only supported stable branches are candidates normally.&lt;br /&gt;
* Also security and dataloss issues are accepted to be fixed into security-only supported branches.&lt;br /&gt;
* Apart from the previous, backport to unsupported branches only will happen when the issue is a &#039;&#039;&#039;direct regression caused by a bug fix&#039;&#039;&#039; introduced by the latest releases. This applies to both security-only and out-of-support branches. A new weekly release will be performed including the fix.&lt;br /&gt;
&lt;br /&gt;
== Fixing issues identified during integration review/ testing ==&lt;br /&gt;
&lt;br /&gt;
When a branch has been merged by an integrator, it is important that you do not modify the existing history of your branch (e.g. by amending or squashing your commits) and instead add new commits on top. If you modify the history of your branch, it makes it extremely difficult for the integrator to merge your changes (and see the differences).&lt;br /&gt;
&lt;br /&gt;
As a general rule, this means that if your issue has entered the &#039;in integration review&#039; stage of the development process, please only add new commits on top of your existing commits. There are circumstances when your issue will be &#039;in integration review&#039; but not merged (and thus possible to squash changes) but if in any doubt, please add new commits and ask the integrator to squash your changes for you.&lt;br /&gt;
&lt;br /&gt;
== Commit squashing ==&lt;br /&gt;
&lt;br /&gt;
The Integration team will sometimes recommend squashing commits when things do not look natural (and may offer to do this for you), especially when there are &amp;quot;fix-commits&amp;quot; in the history happening before integration. But [https://moodle.org/local/chatlogs/index.php?conversationid=13987#c489485 our policy] is &amp;quot;if you want your history of commits to look like bad, it&#039;s your history&amp;quot;. You will not be forced to squash your changes. You should pay close attention to https://docs.moodle.org/dev/Coding_style#Git_commits and intend to  &amp;quot;Tell a perfect, cleaned up version of the history. As if the code was written perfectly first time.&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Category: Processes]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53368</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53368"/>
		<updated>2017-11-20T02:03:51Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Architecture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.&lt;br /&gt;
&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note: The MUA requires the ability to pull random questions from multiple categories. It needs to be confirmed if pulling questions from a parent category including sub categories, combined with filtering by a tag will fullfill this requirement.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* Type of thing that can be added to a quiz &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
After these changes there will only be 2 possible slot types (single question, or random question). The random question will require new fields in the quiz_slots table storing questioncategoryid, includesubcats, and tagid. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
Currently there is a &amp;quot;fake&amp;quot; question category for each context. It does not exist in the database, but in places in the UI it is shown as a &amp;quot;fake&amp;quot; question category named top. We need to turn this into a real question category in the database, and enforce some validation rules to prevent modifying it, adding questions to it, or adding new questions categories as siblings of it. This allows us to (for example) add questions from any category in this course that have the label &amp;quot;midterm4&amp;quot; (because all categories will be a child of this top question category). We will need to modify import/restore to auto-create this top level category for backups older than $versionnumber (and enforce the other validation rules). &lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim suggests that before making the changes requested here might be the appropriate moment to improve parts of the quiz code, because then implementing the new features would be easier, and could be done using the latest coding practices:&lt;br /&gt;
* There are currently two separate classes classes/structure.php and classes/repaginate.php. There is not good reason for this split. Implementing this proposal may require more new classes. These could all be in a new namespace mod_quiz\local\structure namespace and combine, and the two spearate historical classes could be merged.&lt;br /&gt;
* The Edit quiz page currently uses old YUI javascript, renderers and a custom ajax script mod/quiz/edit_rest.php. This would be better as AMD, Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, questioncategoryid, subcats, tagid, maxmark)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: please keep all the columns relating to what question gets slected together. That means that maxmark needs to go after them all, or before them all.)&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Add a random question from a category + tag]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from category + tag added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
===== A problem =====&lt;br /&gt;
&lt;br /&gt;
Note: There is currently a limitation in the question bank. There is no categoryid meaning &amp;quot;all the questions in this context&amp;quot;, for example &amp;quot;All the questions in this course&amp;quot;. In some places in the UI, that is shown as &#039;Top&#039; under the context name, but it does not really exist - and the UI options (but fortunately not the database) adopt a horrible convention where the argument is $categoryid,$contextid, but if $categoryid is 0 then it means any category in this context. The kind of problem this causes is that you cannot export all the questions in a course.&lt;br /&gt;
&lt;br /&gt;
This is also a problem for this bit of work. We want to be able to add a random question which is &amp;quot;Any question in this course with tag X&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
I think the minimal change to allow this is to create in the database a question_category for &amp;quot;Top level of this Course question bank&amp;quot; for each context which has question. I think we can do that with only minimal changes in the question bank (e.g. we don&#039;t need to clean up to nasty $categoryid,$contextid params now. However, we would need to ensure that adding this category did not break things.)&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid, subcats and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar. Although it should not happen we need to allow for the same random question instance being used by 2 quizzes. &lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
* Create a new question category for every context that has questions. Update the existing question categories in that context with parent = 0 to parent = new &amp;quot;Top&amp;quot; question category id&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
(&amp;quot;... the component will be core_course ...&amp;quot; it was not immediately obvious to me that this was &#039;right&#039;. After some thought I have concluded that is, indeed, the least bad way to represent it. Would it be good to explain this choice?)&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
Is the long list of icons really good UI. Is this the moment to do what has been done elsewhere in Moodle, and go for an &amp;quot;Edit&amp;quot; menu?&lt;br /&gt;
&lt;br /&gt;
Also, editing question tags is done on the Edit quiestion form. Should we consolidate it, so that all question tag editing is done in one place? (Probably in the proposed new page, not in the Edit question form.)&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53367</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53367"/>
		<updated>2017-11-20T02:01:59Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Architecture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.&lt;br /&gt;
&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note: The MUA requires the ability to pull random questions from multiple categories. It needs to be confirmed if pulling questions from a parent category including sub categories, combined with filtering by a tag will fullfill this requirement.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* Type of thing that can be added to a quiz &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
After these changes there will only be 2 possible slot types (single question, or random question). The random question will require new fields in the quiz_slots table storing questioncategoryid, includesubcats, and tagid. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
Currently there is a &amp;quot;fake&amp;quot; question category for each context. It does not exist in the database, but in places in the UI it is shown as a &amp;quot;fake&amp;quot; question category named top. We need to turn this into a real question category in the database, and enforce some validation rules to prevent modifying it, adding questions to it, or adding new questions categories as siblings of it. This allows us to (for example) add questions from any category in this course that have the label &amp;quot;midterm4&amp;quot; (because all categories will be a child of this top question category).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim suggests that before making the changes requested here might be the appropriate moment to improve parts of the quiz code, because then implementing the new features would be easier, and could be done using the latest coding practices:&lt;br /&gt;
* There are currently two separate classes classes/structure.php and classes/repaginate.php. There is not good reason for this split. Implementing this proposal may require more new classes. These could all be in a new namespace mod_quiz\local\structure namespace and combine, and the two spearate historical classes could be merged.&lt;br /&gt;
* The Edit quiz page currently uses old YUI javascript, renderers and a custom ajax script mod/quiz/edit_rest.php. This would be better as AMD, Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, questioncategoryid, subcats, tagid, maxmark)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: please keep all the columns relating to what question gets slected together. That means that maxmark needs to go after them all, or before them all.)&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Add a random question from a category + tag]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from category + tag added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
===== A problem =====&lt;br /&gt;
&lt;br /&gt;
Note: There is currently a limitation in the question bank. There is no categoryid meaning &amp;quot;all the questions in this context&amp;quot;, for example &amp;quot;All the questions in this course&amp;quot;. In some places in the UI, that is shown as &#039;Top&#039; under the context name, but it does not really exist - and the UI options (but fortunately not the database) adopt a horrible convention where the argument is $categoryid,$contextid, but if $categoryid is 0 then it means any category in this context. The kind of problem this causes is that you cannot export all the questions in a course.&lt;br /&gt;
&lt;br /&gt;
This is also a problem for this bit of work. We want to be able to add a random question which is &amp;quot;Any question in this course with tag X&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
I think the minimal change to allow this is to create in the database a question_category for &amp;quot;Top level of this Course question bank&amp;quot; for each context which has question. I think we can do that with only minimal changes in the question bank (e.g. we don&#039;t need to clean up to nasty $categoryid,$contextid params now. However, we would need to ensure that adding this category did not break things.)&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid, subcats and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar. Although it should not happen we need to allow for the same random question instance being used by 2 quizzes. &lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
* Create a new question category for every context that has questions. Update the existing question categories in that context with parent = 0 to parent = new &amp;quot;Top&amp;quot; question category id&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
(&amp;quot;... the component will be core_course ...&amp;quot; it was not immediately obvious to me that this was &#039;right&#039;. After some thought I have concluded that is, indeed, the least bad way to represent it. Would it be good to explain this choice?)&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
Is the long list of icons really good UI. Is this the moment to do what has been done elsewhere in Moodle, and go for an &amp;quot;Edit&amp;quot; menu?&lt;br /&gt;
&lt;br /&gt;
Also, editing question tags is done on the Edit quiestion form. Should we consolidate it, so that all question tag editing is done in one place? (Probably in the proposed new page, not in the Edit question form.)&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53366</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53366"/>
		<updated>2017-11-20T01:57:54Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Upgrade Steps Required */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.&lt;br /&gt;
&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note: The MUA requires the ability to pull random questions from multiple categories. It needs to be confirmed if pulling questions from a parent category including sub categories, combined with filtering by a tag will fullfill this requirement.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* Type of thing that can be added to a quiz &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
After these changes there will only be 2 possible slot types (single question, or random question). The random question will require new fields in the quiz_slots table storing questioncategoryid, includesubcats, and tagid. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim suggests that before making the changes requested here might be the appropriate moment to improve parts of the quiz code, because then implementing the new features would be easier, and could be done using the latest coding practices:&lt;br /&gt;
* There are currently two separate classes classes/structure.php and classes/repaginate.php. There is not good reason for this split. Implementing this proposal may require more new classes. These could all be in a new namespace mod_quiz\local\structure namespace and combine, and the two spearate historical classes could be merged.&lt;br /&gt;
* The Edit quiz page currently uses old YUI javascript, renderers and a custom ajax script mod/quiz/edit_rest.php. This would be better as AMD, Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, questioncategoryid, subcats, tagid, maxmark)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: please keep all the columns relating to what question gets slected together. That means that maxmark needs to go after them all, or before them all.)&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Add a random question from a category + tag]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from category + tag added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
===== A problem =====&lt;br /&gt;
&lt;br /&gt;
Note: There is currently a limitation in the question bank. There is no categoryid meaning &amp;quot;all the questions in this context&amp;quot;, for example &amp;quot;All the questions in this course&amp;quot;. In some places in the UI, that is shown as &#039;Top&#039; under the context name, but it does not really exist - and the UI options (but fortunately not the database) adopt a horrible convention where the argument is $categoryid,$contextid, but if $categoryid is 0 then it means any category in this context. The kind of problem this causes is that you cannot export all the questions in a course.&lt;br /&gt;
&lt;br /&gt;
This is also a problem for this bit of work. We want to be able to add a random question which is &amp;quot;Any question in this course with tag X&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
I think the minimal change to allow this is to create in the database a question_category for &amp;quot;Top level of this Course question bank&amp;quot; for each context which has question. I think we can do that with only minimal changes in the question bank (e.g. we don&#039;t need to clean up to nasty $categoryid,$contextid params now. However, we would need to ensure that adding this category did not break things.)&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid, subcats and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar. Although it should not happen we need to allow for the same random question instance being used by 2 quizzes. &lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
* Create a new question category for every context that has questions. Update the existing question categories in that context with parent = 0 to parent = new &amp;quot;Top&amp;quot; question category id&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
(&amp;quot;... the component will be core_course ...&amp;quot; it was not immediately obvious to me that this was &#039;right&#039;. After some thought I have concluded that is, indeed, the least bad way to represent it. Would it be good to explain this choice?)&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
Is the long list of icons really good UI. Is this the moment to do what has been done elsewhere in Moodle, and go for an &amp;quot;Edit&amp;quot; menu?&lt;br /&gt;
&lt;br /&gt;
Also, editing question tags is done on the Edit quiestion form. Should we consolidate it, so that all question tag editing is done in one place? (Probably in the proposed new page, not in the Edit question form.)&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53293</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53293"/>
		<updated>2017-11-16T09:18:50Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* User Stories / Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.&lt;br /&gt;
&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note: The MUA requires the ability to pull random questions from multiple categories. It needs to be confirmed if pulling questions from a parent category including sub categories, combined with filtering by a tag will fullfill this requirement.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
After these changes there will only be 2 possible slot types (single question, or random question). The random question will require new fields in the quiz_slots table storing questioncategoryid, includesubcats, and tagid. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, questioncategoryid, subcats, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Add a random question from a category + tag]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from category + tag added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid, subcats and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar. Although it should not happen we need to allow for the same random question instance being used by 2 quizzes. &lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:QBankTags-DBChanges.png&amp;diff=53292</id>
		<title>File:QBankTags-DBChanges.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:QBankTags-DBChanges.png&amp;diff=53292"/>
		<updated>2017-11-16T09:16:45Z</updated>

		<summary type="html">&lt;p&gt;Damyon: Damyon uploaded a new version of File:QBankTags-DBChanges.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53291</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53291"/>
		<updated>2017-11-16T09:14:01Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.&lt;br /&gt;
&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note: The MUA requires the ability to pull random questions from multiple categories. It needs to be confirmed if pulling questions from a parent category including sub categories, combined with filtering by a tag will fullfill this requirement.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
After these changes there will only be 2 possible slot types (single question, or random question). The random question will require new fields in the quiz_slots table storing questioncategoryid, includesubcats, and tagid. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, questioncategoryid, subcats, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Add a random question from a category + tag]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from category + tag added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid, subcats and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar. Although it should not happen we need to allow for the same random question instance being used by 2 quizzes. &lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53290</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53290"/>
		<updated>2017-11-16T09:00:36Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Updates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.&lt;br /&gt;
&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category (optionally including sub categories) with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note: The MUA requires the ability to pull random questions from multiple categories. It needs to be confirmed if pulling questions from a parent category including sub categories, combined with filtering by a tag will fullfill this requirement.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Add a random question from a category + tag]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from category + tag added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar. Although it should not happen we need to allow for the same random question instance being used by 2 quizzes. &lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:RandomQuestionInQuiz.png&amp;diff=53289</id>
		<title>File:RandomQuestionInQuiz.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:RandomQuestionInQuiz.png&amp;diff=53289"/>
		<updated>2017-11-16T08:57:27Z</updated>

		<summary type="html">&lt;p&gt;Damyon: Damyon uploaded a new version of File:RandomQuestionInQuiz.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53288</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53288"/>
		<updated>2017-11-16T08:52:57Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* UI changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.&lt;br /&gt;
&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note for Tim: We discussed having all the data in the slots table, but that&#039;s not really possible because the MUA requires the ability to pull random questions from multiple categories. So it needs to be stored as a list of question categories, and optional tags.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Add a random question from a category + tag]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from category + tag added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar. Although it should not happen we need to allow for the same random question instance being used by 2 quizzes. &lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:RandomQuestionFromListMenu.png&amp;diff=53287</id>
		<title>File:RandomQuestionFromListMenu.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:RandomQuestionFromListMenu.png&amp;diff=53287"/>
		<updated>2017-11-16T08:51:38Z</updated>

		<summary type="html">&lt;p&gt;Damyon: Damyon uploaded a new version of File:RandomQuestionFromListMenu.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53286</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53286"/>
		<updated>2017-11-16T03:45:37Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Updates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.&lt;br /&gt;
&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note for Tim: We discussed having all the data in the slots table, but that&#039;s not really possible because the MUA requires the ability to pull random questions from multiple categories. So it needs to be stored as a list of question categories, and optional tags.&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar. Although it should not happen we need to allow for the same random question instance being used by 2 quizzes. &lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53285</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53285"/>
		<updated>2017-11-16T03:45:05Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Upgrade Steps Required */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.&lt;br /&gt;
&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note for Tim: We discussed having all the data in the slots table, but that&#039;s not really possible because the MUA requires the ability to pull random questions from multiple categories. So it needs to be stored as a list of question categories, and optional tags.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar. Although it should not happen we need to allow for the same random question instance being used by 2 quizzes. &lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53284</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53284"/>
		<updated>2017-11-16T03:43:45Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Updates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually). It also becomes more difficult to prevent a student from seeing the same random question in the same quiz more than once.&lt;br /&gt;
&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note for Tim: We discussed having all the data in the slots table, but that&#039;s not really possible because the MUA requires the ability to pull random questions from multiple categories. So it needs to be stored as a list of question categories, and optional tags.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53283</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53283"/>
		<updated>2017-11-16T03:42:51Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Updates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every question instance using the set. Adding 10 random questions from a set would create 10 individual questions with the list of question ids stored in each (and each would then require updating individually).&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note for Tim: We discussed having all the data in the slots table, but that&#039;s not really possible because the MUA requires the ability to pull random questions from multiple categories. So it needs to be stored as a list of question categories, and optional tags.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53282</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53282"/>
		<updated>2017-11-16T03:40:17Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* UI Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note for Tim: We discussed having all the data in the slots table, but that&#039;s not really possible because the MUA requires the ability to pull random questions from multiple categories. So it needs to be stored as a list of question categories, and optional tags.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question bank shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:CourseTagsIconForQuestions.png&amp;diff=53281</id>
		<title>File:CourseTagsIconForQuestions.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:CourseTagsIconForQuestions.png&amp;diff=53281"/>
		<updated>2017-11-16T03:39:46Z</updated>

		<summary type="html">&lt;p&gt;Damyon: Damyon uploaded a new version of File:CourseTagsIconForQuestions.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53280</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53280"/>
		<updated>2017-11-16T03:11:46Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Search for question by tag */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note for Tim: We discussed having all the data in the slots table, but that&#039;s not really possible because the MUA requires the ability to pull random questions from multiple categories. So it needs to be stored as a list of question categories, and optional tags.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
We should be able to search for questions by tag from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53279</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53279"/>
		<updated>2017-11-16T03:06:47Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Architecture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note for Tim: We discussed having all the data in the slots table, but that&#039;s not really possible because the MUA requires the ability to pull random questions from multiple categories. So it needs to be stored as a list of question categories, and optional tags.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
===== Other related code improvements =====&lt;br /&gt;
&lt;br /&gt;
Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53278</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53278"/>
		<updated>2017-11-16T03:06:22Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Architecture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note for Tim: We discussed having all the data in the slots table, but that&#039;s not really possible because the MUA requires the ability to pull random questions from multiple categories. So it needs to be stored as a list of question categories, and optional tags.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there.&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\local\structure\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the \mod_quiz\local\structure\slot_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the \mod_quiz\local\structure\slot_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
Other related code improvements: Tim has requested to move the classes from classes/structure.php and classes/repaginate.php to the mod_quiz\local\structure namespace and combine them. &lt;br /&gt;
&lt;br /&gt;
Before modifying the existing quiz editing UI, Tim has requested that we move it from YUI + custom ajax to AMD + Templates and webservices.&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53277</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53277"/>
		<updated>2017-11-16T02:59:49Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Updates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note for Tim: We discussed having all the data in the slots table, but that&#039;s not really possible because the MUA requires the ability to pull random questions from multiple categories. So it needs to be stored as a list of question categories, and optional tags.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53276</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53276"/>
		<updated>2017-11-16T02:56:49Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* DB changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_randomslot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:QBankTags-DBChanges.png&amp;diff=53275</id>
		<title>File:QBankTags-DBChanges.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:QBankTags-DBChanges.png&amp;diff=53275"/>
		<updated>2017-11-16T02:55:18Z</updated>

		<summary type="html">&lt;p&gt;Damyon: Damyon uploaded a new version of File:QBankTags-DBChanges.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53274</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53274"/>
		<updated>2017-11-16T02:51:33Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* DB changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
quiz_random_slot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53273</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53273"/>
		<updated>2017-11-16T02:51:16Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Random question from a question category + tag */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a new table storing a list of questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Update the quiz_slots table to change questionid to allow null.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introduce 1 new table to store a list of questioncategoryid + optional tagid for each random question slot.&lt;br /&gt;
&lt;br /&gt;
quiz_random_slot(id, quizslotid, category, tagid *allow null*)&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53272</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53272"/>
		<updated>2017-11-16T02:46:22Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Updates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag. We also need to meet the use case where we want to use questions from different question categories.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from multiple question categories with optional filtering by tags.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Make questionid allow null and add 1 new fields to the quiz_slots table.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53271</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53271"/>
		<updated>2017-11-16T02:31:34Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Architecture */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category. The list of questions can be further restricted by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will make this field optional (allow null). The slot type can be determined by the presence or absence of the questionid field.&lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin).&lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Make questionid allow null and add 1 new fields to the quiz_slots table.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53270</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53270"/>
		<updated>2017-11-16T02:29:45Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category. The list of questions can be further restricted by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a question category + tag&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will change this table to abstract the logic for determining the question from the slot. &lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin). &lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Make questionid allow null and add 1 new fields to the quiz_slots table.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53269</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53269"/>
		<updated>2017-11-16T02:28:56Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Updates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category. The list of questions can be further restricted by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a set of questions&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will change this table to abstract the logic for determining the question from the slot. &lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin). &lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Make questionid allow null and add 1 new fields to the quiz_slots table.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53268</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53268"/>
		<updated>2017-11-16T02:28:34Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Updates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
This impacts one of the user requirements for the project:&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
would have to be modified to:&lt;br /&gt;
&amp;quot;As a teacher, I can add a &#039;random question&#039; to my quiz where the question is taken from a question category. The list of questions can be further restricted by specifying a tag.&amp;quot;&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a set of questions&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will change this table to abstract the logic for determining the question from the slot. &lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin). &lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Make questionid allow null and add 1 new fields to the quiz_slots table.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53266</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53266"/>
		<updated>2017-11-16T02:22:20Z</updated>

		<summary type="html">&lt;p&gt;Damyon: /* Update */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
16th Nov 2017&lt;br /&gt;
&lt;br /&gt;
It was discussed that the &amp;quot;random question from a set of questions&amp;quot; is not ideal because it is hard to &amp;quot;manage&amp;quot; the set of questions, e.g. adding or deleting questions from a set would have to be done individually for every quiz instance using the set.&lt;br /&gt;
Initially &amp;quot;random question from a tag&amp;quot; was discarded earlier because there are problems when users with different permissions are editing the question. If we add the questioncategory (context) to the information that would solve the ambiguity.&lt;br /&gt;
So we would have only one random question type, which could be further restricted by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a set of questions&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will change this table to abstract the logic for determining the question from the slot. &lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin). &lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Make questionid allow null and add 1 new fields to the quiz_slots table.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53265</id>
		<title>Improved Question Bank Tags</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Improved_Question_Bank_Tags&amp;diff=53265"/>
		<updated>2017-11-16T02:16:14Z</updated>

		<summary type="html">&lt;p&gt;Damyon: Updates changing &amp;quot;random question from a set of questions&amp;quot; to &amp;quot;random question from a category + tagid&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.&lt;br /&gt;
&lt;br /&gt;
The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465&lt;br /&gt;
&lt;br /&gt;
The requirements / user stories have been written by the MUA - a copy is included here for clarity&lt;br /&gt;
&lt;br /&gt;
== User Stories / Requirements ==&lt;br /&gt;
&lt;br /&gt;
Must:&lt;br /&gt;
&lt;br /&gt;
* As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.&lt;br /&gt;
* As a teacher, I can filter my questions in courses based on tags.&lt;br /&gt;
* As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.&lt;br /&gt;
* As another teacher in the same course, I have access to the question tags on the questions in that course context.&lt;br /&gt;
* As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)&lt;br /&gt;
* As a teacher, I am able to add/modify/remove tags on questions.&lt;br /&gt;
* As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.&lt;br /&gt;
* As a teacher, I can add a &#039;random question from question set&#039; question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.&lt;br /&gt;
&lt;br /&gt;
Nice to have:&lt;br /&gt;
* Tags can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.&lt;br /&gt;
* As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.&lt;br /&gt;
* As a teacher, I can export/import questions with their tags.&lt;br /&gt;
* As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.&lt;br /&gt;
* As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.&lt;br /&gt;
&lt;br /&gt;
== Update ==&lt;br /&gt;
Following a meeting between Tim / Damyon I&#039;m saving a record of the chat conversation here. I&#039;ll then update this design page based on those notes and delete the notes (but they will exist in the history).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
thanks - here are my notes (sorry they are rough - feel free to add more detail / correct them)&lt;br /&gt;
&lt;br /&gt;
Damyon, [08.11.17 21:06]&lt;br /&gt;
# drop random question from set, replace with random question from tag + context, that makes to manage multiple questions from the same tag + context and we can store it all in the slots table&lt;br /&gt;
&lt;br /&gt;
# plugin vs classes - much easier to do the ui and if it&#039;s all in one table classes makes sense. &lt;br /&gt;
&lt;br /&gt;
structure.php could contain the classes. &lt;br /&gt;
&lt;br /&gt;
correct to move category to this new model. upgrade is scary.&lt;br /&gt;
&lt;br /&gt;
OU has 40,000 questions - need progress bar.&lt;br /&gt;
&lt;br /&gt;
possible to have one random question from category in 2 quizes.&lt;br /&gt;
&lt;br /&gt;
need to ensure that 3 random questions in a row do not get the same question.&lt;br /&gt;
&lt;br /&gt;
mobile needs to duplicate this a bit.&lt;br /&gt;
&lt;br /&gt;
use existing hooks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How much re-work for AMD?&lt;br /&gt;
&lt;br /&gt;
re-do edit quiz page using templates + AMD + webservices - need to investigate how much work.&lt;br /&gt;
&lt;br /&gt;
Move tagging UI into the question bank - not in the quiz.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:53]&lt;br /&gt;
Re: structure.php could contain the classes - Better to say: Classes could go in a new namespace corresponding to mod/quiz/classes/local/structure/. Should rpobalby move the existing classes/structure.php &amp;amp; repaginate.php in there. (There is no good reason why those are two separate classes. Feel free to change.)&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:54]&lt;br /&gt;
Re structure.php could contain the classes - I would say that the fact that the OU only has 40,000 questions is a sign that this upgrade is not a scary as it might have been. No need for excessive measures, just a progress bar.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:55]&lt;br /&gt;
Re: possible to have one random question from category in 2 quizes - this certainly exists in the data, but really only because  of past bugs. THe upgrade needs to deal with this, but that shoudl be possible.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:56]&lt;br /&gt;
Re: mobile needs to duplicate this a bit. - sorry, I was not clear. Mobile does not need to duplicate this. It calls a start attempt function, which uses the same sever-side PHP to build the quiz attempt, and returns a list of questions, so no worries there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
Both startattempt.php and mobile web service call quiz_prepare_and_start_new_attempt, which calls quiz_start_new_attempt, which is where the randomisation is currently done, so that is the key code to read. The other key class to understand is random_question_loader, used there.&lt;br /&gt;
&lt;br /&gt;
Tim Hunt, [08.11.17 23:59]&lt;br /&gt;
I hope those clarifications are helpful. Other than that, good complete notes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
The requirements listed above can be met by implementing the following changes (which are described in detail further down):&lt;br /&gt;
* New question type &amp;quot;Random question from a set of questions&amp;quot;&lt;br /&gt;
* Enhanced question search allowing search/filter by tag everywhere&lt;br /&gt;
* Allow adding course level tags to questions that exist in a category&lt;br /&gt;
&lt;br /&gt;
=== Random question from a question category + tag ===&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
Currently the quiz_slots DB table has a questionid column that directly links to the question for that slot. We will change this table to abstract the logic for determining the question from the slot. &lt;br /&gt;
&lt;br /&gt;
The slot type can be determined from the fields in the quiz_slots table. After these changes there will only be 2 possible slot types (single question, or random question). The random question will require a questioncategoryid and an optional tag. &lt;br /&gt;
&lt;br /&gt;
We will introduce a new abstract class &amp;quot;mod_quiz\slot_type&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The slot_type subclass will be responsible for:&lt;br /&gt;
* Determining a specific question id from a quizid + slotid + userid. A new question id is only queried when a new attempt is started, or a question is re-attempted.&lt;br /&gt;
* Display of UI to configure this slot type (JS and non-JS). &lt;br /&gt;
&lt;br /&gt;
When the slottype is &amp;quot;single&amp;quot; - the slot_type_single class is loaded directly from the quiz (not a sub-plugin). When the slottype is &amp;quot;random&amp;quot; the slot_type_random class is loaded directly from the quiz (also not a sub-plugin). &lt;br /&gt;
&lt;br /&gt;
==== DB changes ====&lt;br /&gt;
&lt;br /&gt;
Make questionid allow null and add 1 new fields to the quiz_slots table.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
quiz_slots(id, slot, quizid, page, requireprevious, question, maxmark, category, tagid)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:QBankTags-DBChanges.png|frame|center|DB structure changes]]&lt;br /&gt;
&lt;br /&gt;
==== UI changes ====&lt;br /&gt;
These images are mockups &#039;&#039;&#039;for illustration only&#039;&#039;&#039; and are not to be taken as the final UI design.&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionFromListMenu.png|frame|center|Random question from list added to quiz structure menu]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPopup.png|frame|center|Dialog to edit the list of random questions]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionPicker.png|frame|center|Question picker to add questions to the random list]]&lt;br /&gt;
&lt;br /&gt;
[[File:RandomQuestionInQuiz.png|frame|center|Random question from list added to a quiz]]&lt;br /&gt;
&lt;br /&gt;
==== Upgrade Steps Required ====&lt;br /&gt;
* We will need to change the questionid column of the quiz_slots table to allow null. (Quick DB update, no conflicts to resolve).&lt;br /&gt;
* We will need to add columns to the quiz_slots table for questioncategoryid and tagid. (Quick update, columns will be initially null).&lt;br /&gt;
* We will need to search for all &amp;quot;random&amp;quot; questions in the question bank and for each one - move the configuration data to the quiz_slots table. This will be the slow part of the upgrade and will require a progress bar.&lt;br /&gt;
* We will then need to delete all &amp;quot;random&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
=== Search for question by tag ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
There are 2 places we could (should) be able to search questions by tag. &lt;br /&gt;
&lt;br /&gt;
The first is from the tag management page. This work has been started on https://tracker.moodle.org/browse/MDL-59781, all that remains to complete it is to create a moodle page that can show a single question from a question bank (so the tag search results page can link to the question).&lt;br /&gt;
&lt;br /&gt;
The second is to be able to search for questions by tag in the question picker while adding questions to a quiz. There is an existing API to extend this search form and an example in the local plugin https://github.com/MorrisR2/moodle_local_searchquestions. This would just require adding a new plugin that implements the get_question_bank_search_conditions callback to return an instance of core_question\bank\search\condition for searching tags. The search field for tags should just be a text field. The current API does not allow javascript to be used in search conditions, if a full &amp;quot;autocomplete&amp;quot; element is required for the tags search we will need to extend the question bank API.&lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
[[File:SearchQuestionsByTags.png|frame|center|Search for questions from global tag search]]&lt;br /&gt;
&lt;br /&gt;
[[File:SearchByTagsInQuestionPicker.png|frame|center|Search by tags while picking questions from the question bank]]&lt;br /&gt;
&lt;br /&gt;
=== Course level tags for questions ===&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
This will be implemented by defining a new &amp;quot;tag area&amp;quot; for &amp;quot;course questions&amp;quot;. The itemtype will be question and the component will be core_course. We will still have to implement the UI for adding and deleting &amp;quot;course question tags&amp;quot;, and make sure that searching for questions by tags returns results from both the question tags, and the course question tags. We will add this new tag area to the backup/restore and ensure questions tagged in a course are included in the course backup file. Viewing the coursetags for a question will be controlled by a new capability: &amp;quot;moodle/course:viewquestiontags&amp;quot;. Changing the course tags for a question will be controlled by a new capability &amp;quot;moodle/course:managequestiontags&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==== UI Changes ====&lt;br /&gt;
&lt;br /&gt;
[[File:CourseTagsIconForQuestions.png|frame|center|Question shows course tags icon]]&lt;br /&gt;
&lt;br /&gt;
[[File:ManageCourseTagsForQuestion.png|frame|center|Edit the course tags for a question]]&lt;/div&gt;</summary>
		<author><name>Damyon</name></author>
	</entry>
</feed>