<?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=Farhan6318</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=Farhan6318"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Farhan6318"/>
	<updated>2026-06-04T06:14:59Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=61754</id>
		<title>lib/formslib.php Form Definition</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=61754"/>
		<updated>2022-02-28T18:29:01Z</updated>

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

		<summary type="html">&lt;p&gt;Farhan6318: /* Logstores */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
Moodle PHPUnit integration is designed to allow easy adding of new tests. At the start of each test the state is automatically reset to fresh new installation (unless explicitly told not to reset).&lt;br /&gt;
&lt;br /&gt;
=Namespaces=&lt;br /&gt;
&lt;br /&gt;
All the stuff under **/tests directories is [[Coding style#Namespaces_within_.2A.2A.2Ftests_directories|subject to some simple rules]] when using namespaces. They apply to test cases, fixtures, generators and, in general, any class within those directories. Take a look to them! (grand summary = 100% the same rules that are applied to **/classes directories).&lt;br /&gt;
&lt;br /&gt;
=Testcase classes=&lt;br /&gt;
&lt;br /&gt;
There are three basic test class that are supposed to used in all Moodle unit tests - basic_testcase, advanced_testcase and provider_testcase. &#039;&#039;&#039;Please note it is strongly recommended to put only one testcase into each class file.&#039;&#039;&#039;&lt;br /&gt;
;basic_testcase : Very simple tests that do not modify database, dataroot or any PHP globals. It can be used for example when trying examples from the official PHPUnit tutorial.&lt;br /&gt;
;advanced_testcase : Enhanced testcase class enhanced for easy testing of Moodle code.&lt;br /&gt;
;provider_testcase: Enhanced testcase class, enhanced for easy testing of [[Privacy API|Privacy Providers]].&lt;br /&gt;
&lt;br /&gt;
There is a fourth testcase class that is specially designed for testing of our Moodle database layer, it should not be used for other purposes.&lt;br /&gt;
&lt;br /&gt;
== Assertions ==&lt;br /&gt;
&lt;br /&gt;
The complete list of assertions can be found in the [https://phpunit.readthedocs.io/en/7.0/assertions.html].&lt;br /&gt;
&lt;br /&gt;
==Sample plugin testcase==&lt;br /&gt;
&lt;br /&gt;
PHPUnit tests are located in &amp;lt;code&amp;gt;tests/*_test.php&amp;lt;/code&amp;gt; files in your plugin, for example mod/myplugin/tests/sample_test.php, the file should contain only one class that extends &amp;lt;code&amp;gt;advanced_testcase&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_sample_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_adding() {&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, 1+2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[PHPUnit integration#Class and file naming rules]] for more information.&lt;br /&gt;
&lt;br /&gt;
==Inclusion of Moodle library files==&lt;br /&gt;
&lt;br /&gt;
If you want to include some Moodle library files you should always declare &#039;&#039;&#039;global $CFG&#039;&#039;&#039;. The reason is that testcase files may be included from non-moodle code which does not make the global $CFG available automatically.&lt;br /&gt;
&lt;br /&gt;
==Automatic state reset==&lt;br /&gt;
By default after each test Moodle database and dataroot is automatically reset to the original state which was present right after installation. make sure to use $this-&amp;gt;resetAfterTest() to indicate that the database or changes of standard global variables are expected.&lt;br /&gt;
&lt;br /&gt;
If you received the error &amp;quot;Warning: unexpected database modification, resetting DB state&amp;quot; it is because the test is not using $this-&amp;gt;resetAfterTest().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_deleting() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;resetAfterTest(true);&lt;br /&gt;
         $DB-&amp;gt;delete_records(&#039;user&#039;);&lt;br /&gt;
         $this-&amp;gt;assertEmpty($DB-&amp;gt;get_records(&#039;user&#039;));&lt;br /&gt;
     }&lt;br /&gt;
     public function test_user_table_was_reset() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, $DB-&amp;gt;count_records(&#039;user&#039;, array()));&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Generators=&lt;br /&gt;
&lt;br /&gt;
Tests that need to modify default installation may use generators to create new courses, users, etc. All examples on this page should be used from test methods of a test class derived from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
Note if you are using PHPUnit [https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers @dataProvider] functions to provide parameters to unit tests, you can not use the data generator or change the user etc in the data provider function.&lt;br /&gt;
&lt;br /&gt;
==Creating users==&lt;br /&gt;
At the start of each test there are only two users present - guest and administrator. If you need to add more test accounts use:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also specify properties of the user account, for example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user(array(&#039;email&#039;=&amp;gt;&#039;user1@example.com&#039;, &#039;username&#039;=&amp;gt;&#039;user1&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default no user is logged-in, use setUser() method to change current $USER value:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser($user1);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Guest and admin accounts have a shortcut methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setGuestUser();&lt;br /&gt;
 $this-&amp;gt;setAdminUser();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Null can be used to set current user back to not-logged-in:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser(null);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating course categories==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $category1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $category2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category(array(&#039;name&#039;=&amp;gt;&#039;Some subcategory&#039;, &#039;parent&#039;=&amp;gt;$category1-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating courses==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 &lt;br /&gt;
 $category = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $course2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course(array(&#039;name&#039;=&amp;gt;&#039;Some course&#039;, &#039;category&#039;=&amp;gt;$category-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating activities==&lt;br /&gt;
&lt;br /&gt;
Some activity plugins include instance generators. The generator class are defined in plugindirectory/tests/generator/lib.php.&lt;br /&gt;
&lt;br /&gt;
Example of creation of new course with one page resource:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 $generator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator(&#039;mod_page&#039;);&lt;br /&gt;
 $generator-&amp;gt;create_instance(array(&#039;course&#039;=&amp;gt;$course-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following is functionally the same, but a bit shorter:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 $page = $this-&amp;gt;getDataGenerator()-&amp;gt;create_module(&#039;page&#039;, array(&#039;course&#039; =&amp;gt; $course-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating cohorts==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Since 2.4 there the data generator supports creation of new cohorts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $cohort = $this-&amp;gt;getDataGenerator()-&amp;gt;create_cohort();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Simplified user enrolments==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Instead of standard enrolment API it is possible to use simplified method in data generator. It is intended to be used with self and manual enrolment plugins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid, &#039;manual&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating scales==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_scale();&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_scale(array(&#039;name&#039; =&amp;gt; $name, &#039;scale&#039; =&amp;gt; $scale, &#039;courseid&#039; =&amp;gt; $courseid, &#039;userid&#039; =&amp;gt; $userid, &#039;description&#039; =&amp;gt; description, &#039;descriptionformat&#039; =&amp;gt; $descriptionformat));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating roles==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_role();&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_role(array(&#039;shortname&#039; =&amp;gt; $shortname, &#039;name&#039; =&amp;gt; $name, &#039;description&#039; =&amp;gt; description, &#039;archetype&#039; =&amp;gt; $archetype));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating tags==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_tag();&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_tag(array(&lt;br /&gt;
    &#039;userid&#039; =&amp;gt; $userid, &lt;br /&gt;
    &#039;rawname&#039; =&amp;gt; $rawname,&lt;br /&gt;
    &#039;name&#039; =&amp;gt; $name, &lt;br /&gt;
    &#039;description&#039; =&amp;gt; $description, &lt;br /&gt;
    &#039;descriptionformat&#039; =&amp;gt; $descriptionformat,&lt;br /&gt;
    &#039;flag&#039; =&amp;gt; $flag&lt;br /&gt;
));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Groups==&lt;br /&gt;
&lt;br /&gt;
===Creating groups===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_group(array(&#039;courseid&#039; =&amp;gt; $courseid));&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_group(array(&#039;courseid&#039; =&amp;gt; $courseid, &#039;name&#039; =&amp;gt; $name, &#039;description&#039; =&amp;gt; $description, &#039;descriptionformat&#039; =&amp;gt; $descriptionformat));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adding users to groups===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_group_member(array(&#039;userid&#039; =&amp;gt; $userid, &#039;groupid&#039; =&amp;gt; $groupid));&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_group_member(array(&#039;userid&#039; =&amp;gt; $userid, &#039;groupid&#039; =&amp;gt; $groupid, &#039;component&#039; =&amp;gt; $component, &#039;itemid&#039; =&amp;gt; $itemid));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creating groupings===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_grouping(array(&#039;courseid&#039; =&amp;gt; $courseid));&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_grouping(array(&#039;courseid&#039; =&amp;gt; $courseid, &#039;name&#039; =&amp;gt; $name, &#039;description&#039; =&amp;gt; $description, &#039;descriptionformat&#039; =&amp;gt; $descriptionformat));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adding groups to groupings===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_grouping_group(array(&#039;groupingid&#039; =&amp;gt; $groupingid, &#039;groupid&#039; =&amp;gt; $groupid));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Repositories==&lt;br /&gt;
&lt;br /&gt;
===Creating repository instances===&lt;br /&gt;
{{Moodle 2.5}}&lt;br /&gt;
Some respository plugins include instance generators. The generator class are defined in plugindirectory/tests/generator/lib.php..&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_repository($type, $record, $options);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creating repository types===&lt;br /&gt;
{{Moodle 2.5}}&lt;br /&gt;
Some respository plugins include type generators. The generator class are defined in plugindirectory/tests/generator/lib.php..&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_repository_type($type, $record, $options);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating grades==&lt;br /&gt;
&lt;br /&gt;
===Grade categories===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_grade_category(array(&#039;courseid&#039; =&amp;gt; $courseid));&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_grade_category(array(&#039;courseid&#039; =&amp;gt; $courseid, &#039;fullname&#039; =&amp;gt; $fullname));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Grade items===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_grade_item();&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_grade_item(array(&#039;itemtype&#039; =&amp;gt; $itemtype, &#039;itemname&#039; =&amp;gt; $itemname, &#039;outcomeid&#039; =&amp;gt; $outcomeid, &#039;scaleid&#039; =&amp;gt; $scaleid, &#039;gradetype&#039; =&amp;gt; $gradetype));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Outcomes===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_grade_outcome();&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;create_grade_item(array(&#039;fullname&#039; =&amp;gt; $fullname));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Other types of plugin==&lt;br /&gt;
{{Moodle 2.5}}&lt;br /&gt;
Any other type of plugin can have a generator. The generator class should extend component_generator_base, and then you can get an instance using $mygenerator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator($frankenstylecomponentname);&lt;br /&gt;
&lt;br /&gt;
For some types of plugin, like mod documented above, there may be a more specific class than component_generator_base to extend, like testing_module_generator. That will give a consistent set of method names to use. Otherwise, you can create whatever methods you like on your generator, to create the different things you need to work whith.&lt;br /&gt;
&lt;br /&gt;
=Long tests=&lt;br /&gt;
&lt;br /&gt;
All standard test should execute as fast as possible. Tests that take a loner time to execute (&amp;gt;10s) or are otherwise expensive (such as querying external servers that might be flooded by all dev machines) should be execute only when PHPUNIT_LONGTEST is true. This constant can be set in phpunit.xml or directly in config.php.&lt;br /&gt;
&lt;br /&gt;
=Large test data=&lt;br /&gt;
See advanced_testcase::createXMLDataSet() and advanced_testcase::createCsvDataSet() and related functions there for easier ways to manage large test data sets within files rather than arrays in code. See [[PHPUnit_integration#Extra_methods]]&lt;br /&gt;
&lt;br /&gt;
=Testing sending of messages=&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
You can temporarily redirect all messages sent via message_send() to a message sink object. This allows developers to verify that the tested code is sending expected messages.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first disable the use of transactions and then redirect the messaging into a new message sink, you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;preventResetByRollback();&lt;br /&gt;
$sink = $this-&amp;gt;redirectMessages();&lt;br /&gt;
//... code that is sending messages&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(3, count($messages));&lt;br /&gt;
//.. test messages were generated in correct order with appropriate content&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Testing sending of emails=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
You can temporarily redirect emails sent via email_to_user() to a email message sink object. This allows developers to verify that the tested code is sending expected emails.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first unset &#039;noemailever&#039; setting and then redirect the emails into a new message sink where you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
unset_config(&#039;noemailever&#039;);&lt;br /&gt;
$sink = $this-&amp;gt;redirectEmails();&lt;br /&gt;
//... code that is sending email&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(1, count($messages));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Logstores=&lt;br /&gt;
You can test events which were written to a logstore, but you must disable transactions, enable at least one valid logstore, and disable logstore buffering to ensure that the events are written to the database before the tests execute.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;preventResetByRollback();&lt;br /&gt;
set_config(&#039;enabled_stores&#039;, &#039;logstore_standard&#039;, &#039;tool_log&#039;);&lt;br /&gt;
set_config(&#039;buffersize&#039;, 0, &#039;logstore_standard&#039;);&lt;br /&gt;
get_log_manager(true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Check your coverage=&lt;br /&gt;
PHPUnit has the ability to generate code coverage information for your unit tests.&lt;br /&gt;
&lt;br /&gt;
Prior to Moodle 3.7, this coverage would load all files and generate coverage for everything regardless of whether that file could be covered at all, or whether it was intentionally covered.&lt;br /&gt;
&lt;br /&gt;
Since Moodle 3.7 the &#039;&#039;&#039;phpunit.xml&#039;&#039;&#039; configuration includes  generated Whitelist and Blacklist information for each component.  In addition to this the &#039;&#039;&#039;strict-coverage&#039;&#039;&#039; option is also set in the &#039;&#039;&#039;phpunit.xml&#039;&#039;&#039; which ensures that code is only marked as covered if it was intentionally covered.&lt;br /&gt;
&lt;br /&gt;
==Generating blacklist and whitelist configuration==&lt;br /&gt;
&lt;br /&gt;
You can programatically describe which files will be checked for coverage by creating a coverage.php file alongside the tests that you are writing.&lt;br /&gt;
&lt;br /&gt;
The coverage.php file allows you to list white-listed and black-listed files and folders within the component being&lt;br /&gt;
tested. All paths specified are relative to the component being tested. For example, when working with &#039;&#039;&#039;mod_forum&#039;&#039;&#039; your&lt;br /&gt;
code will be in &#039;&#039;&#039;mod/forum&#039;&#039;&#039;, and its unit tests will be in &#039;&#039;&#039;mod/forum/tests/example_test.php&#039;&#039;&#039;. The coverage file&lt;br /&gt;
for this would be in &#039;&#039;&#039;mod/forum/tests/coverage.php&#039;&#039;&#039; and all paths specified would be relative to &#039;&#039;&#039;mod/forum&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
It is possible to specify a combination of whilte-listed files, white-listed folders, black-listed files, and&lt;br /&gt;
black-listed folders. This would allow you, for example, to whitelist the entire &#039;&#039;&#039;classes&#039;&#039;&#039; directory, but blacklist&lt;br /&gt;
a specific file or folder within it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following is an example coverage file from &#039;&#039;&#039;mod_forum&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
return new class extends phpunit_coverage_info {&lt;br /&gt;
    /** @var array The list of folders relative to the plugin root to whitelist in coverage generation. */&lt;br /&gt;
    protected $whitelistfolders = [&lt;br /&gt;
        &#039;classes/local&#039;,&lt;br /&gt;
        &#039;externallib.php&#039;,&lt;br /&gt;
    ];&lt;br /&gt;
&lt;br /&gt;
    /** @var array The list of files relative to the plugin root to whitelist in coverage generation. */&lt;br /&gt;
    protected $whitelistfiles = [];&lt;br /&gt;
&lt;br /&gt;
    /** @var array The list of folders relative to the plugin root to excludelist in coverage generation. */&lt;br /&gt;
    protected $excludelistfolders = [];&lt;br /&gt;
&lt;br /&gt;
    /** @var array The list of files relative to the plugin root to excludelist in coverage generation. */&lt;br /&gt;
    protected $excludelistfiles = [];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Strict coverage==&lt;br /&gt;
Since Moodle 3.7, PHPUnit code coverage is strict about what is covered. This is to ensure that tests only cover the functions that they intend to test which is a best practice. Without this, much of Moodle is accidentally covered by virtue of being in the code-path, and it becomes very difficult to accurately determine whether a class or function is intentionally covered fully and correctly.&lt;br /&gt;
&lt;br /&gt;
This is a PHPUnit feature and is [https://phpunit.readthedocs.io/en/8.1/code-coverage-analysis.html#specifying-covered-code-parts described in their documention].&lt;br /&gt;
&lt;br /&gt;
=Best practice=&lt;br /&gt;
&lt;br /&gt;
There are several best practices, suggestions, and things to avoid which you should consider when writing unit tests. Some of these are described below.&lt;br /&gt;
&lt;br /&gt;
==Check your coverage==&lt;br /&gt;
PHPUnit has the ability to generate code coverage information for your unit tests and this is well supported since&lt;br /&gt;
Moodle 3.7. We recommend that you consider checking the coverage of your plugins when you write your code.&lt;br /&gt;
&lt;br /&gt;
==Keep use of resetAfterTest to a minimum==&lt;br /&gt;
Although many of the examples described above use the &amp;lt;code&amp;gt;resetAfterTest&amp;lt;/code&amp;gt; nomenclature to reset the database and filesystem after your test completes, you should ideally not use this unless you have to.&lt;br /&gt;
Generally speaking you should aim to write code which is mockable, and does not require real fixtures.&lt;br /&gt;
Use of resetAfterTest will also slow your tests down.&lt;br /&gt;
&lt;br /&gt;
==Be careful with shared setUp and instance variables==&lt;br /&gt;
&lt;br /&gt;
You should be careful of how you create and use instance variables in PHPUnit tests for two main reasons:&lt;br /&gt;
&lt;br /&gt;
Firstly, if you create any fixtures in the setUp, or call the resetAfterTest function, these fixtures and conditions will apply for _all_ tests in the testsuite.&lt;br /&gt;
You will not be able to add another test to the suite which does not require these conditions without those conditions being fulfilled anyway.&lt;br /&gt;
This can lead to slow tests.&lt;br /&gt;
&lt;br /&gt;
Secondly, because of the way in which PHPUnit operates. it creates an instance of each testcase during its bootstrap phase. These are stored in memory until the _entire suite_ completes.&lt;br /&gt;
This means that any fixture which is setup and not actively discarded will not be garbage collected and lead to memory bloat.&lt;br /&gt;
In severe cases this can lead to memory exhaustion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Make use of the dataProvider functionality==&lt;br /&gt;
&lt;br /&gt;
The dataProvider functionality of PHPUnit is an extremely powerful and useful feature which allows you to verify a function quickly and easily with a range of different conditions.&lt;br /&gt;
However, the following rules should be followed when using dataProviders:&lt;br /&gt;
* Keep addition of resettable data requring resetAfterTest to a minimum - this will lead to many slow tests&lt;br /&gt;
* You can only _describe_ data in a dataProvider, you cannot create the data. The dataProvider is called after the testSuite is instantiated, but before any tests are run. Each test will run a full setUp and tearDown, which will destroy any data which was created.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Test function accepts parameters passed from the specified data provider.&lt;br /&gt;
 *&lt;br /&gt;
 * @dataProvider foobar_provider&lt;br /&gt;
 * @param int $foor&lt;br /&gt;
 * @param int $bar&lt;br /&gt;
 */&lt;br /&gt;
public function test_foobar(int $foo, int $bar) {&lt;br /&gt;
    // Perform the tests here.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Data provider for {@see self::test_foobar()}.&lt;br /&gt;
 *&lt;br /&gt;
 * @return array List of data sets - (string) data set name =&amp;gt; (array) data&lt;br /&gt;
 */&lt;br /&gt;
public function foobar_provider(): array {&lt;br /&gt;
    return [&lt;br /&gt;
        &#039;Same numbers&#039; =&amp;gt; [&lt;br /&gt;
            &#039;foo&#039; =&amp;gt; 42,&lt;br /&gt;
            &#039;bar&#039; =&amp;gt; 42,&lt;br /&gt;
        ],&lt;br /&gt;
        &#039;Different numbers&#039; =&amp;gt; [&lt;br /&gt;
            &#039;foo&#039; =&amp;gt; 21,&lt;br /&gt;
            &#039;bar&#039; =&amp;gt; 84,&lt;br /&gt;
        ],&lt;br /&gt;
    ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Extra test settings=&lt;br /&gt;
&lt;br /&gt;
Usually the test should not interact with any external systems and it should work the same on all systems. But sometimes you need to specify some option for connection to external systems or system configuration. It is intentionally not possible to use $CFG settings from config.php.&lt;br /&gt;
&lt;br /&gt;
There are several ways how to inject your custom settings:&lt;br /&gt;
* define test setting constants in your phpunit.xml file&lt;br /&gt;
* define test setting constants in your config.php&lt;br /&gt;
&lt;br /&gt;
These constants may be then used in your test or plugin code.&lt;br /&gt;
&lt;br /&gt;
=Upgrading unit tests to work with Moodle 3.10 and up (PHPUnit 8.5)=&lt;br /&gt;
{{Moodle 3.10}}&lt;br /&gt;
&lt;br /&gt;
With Moodle 3.10, &#039;&#039;&#039;PHPUnit was upgraded to 8.5&#039;&#039;&#039; (from 7.5 being used in older version). This was done to &#039;&#039;&#039;better align&#039;&#039;&#039; the testing environment with PHP versions supported by Moodle 3.10 (7.2, 7.3 and 7.4) and also to provide an &#039;&#039;&#039;easier jump to PHPUnit 9.x&#039;&#039;&#039; that will be needed for Moodle 3.11 (php versions 7.3, 7.4 and 8.0), removing a lot of deprecated stuff in advance. (see MDL-67673 and MDL-64600 for more details).&lt;br /&gt;
&lt;br /&gt;
While 99% of existing tests will work without modification with PHPUnit 8.5, you will get a &#039;&#039;&#039;good number of deprecation warnings&#039;&#039;&#039; (&amp;quot;W&amp;quot; in the tests output) that &#039;&#039;&#039;should be replaced by their new counterparts as soon as possible&#039;&#039;&#039;, because all those warnings will become errors with next PHPUnit upgrade.&lt;br /&gt;
&lt;br /&gt;
To find more information about the changes coming with PHPUnit 8.5, it&#039;s recommended to read the following resources:&lt;br /&gt;
&lt;br /&gt;
* [https://thephp.cc/news/2019/02/help-my-tests-stopped-working A good article] explaining all the main changes in the release.&lt;br /&gt;
* [https://phpunit.de/announcements/phpunit-8.html PHPUnit 8 release Announcement].&lt;br /&gt;
* [https://github.com/sebastianbergmann/phpunit/blob/130104cf796a88dd1547dc5beb8bd555c2deb55e/ChangeLog-8.0.md Detailed changelog of the release].&lt;br /&gt;
* [https://phpunit.readthedocs.io/en/8.5/ Official PHPUnit manual].&lt;br /&gt;
* A good summary of all the &#039;&#039;&#039;changes and replacements to perform&#039;&#039;&#039; is available in the [https://github.com/moodle/moodle/blob/6594c54b2eef62499d304bfa0939999e3a14246e/lib/upgrade.txt#L5-L37 lib/upgrade.txt] file. With main points being:&lt;br /&gt;
** Support for PHP 7.0 dropped (because all template methods (&amp;lt;tt&amp;gt;setUp()&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;tearDown()&amp;lt;/tt&amp;gt;..) now require to return void. This will mostly impact 3rd-part plugins that were still running the same tests against old branches of Moodle with PHP 7.0 support.&lt;br /&gt;
** &amp;lt;tt&amp;gt;PHPUnit/DBUnit&amp;lt;/tt&amp;gt; has been removed are replaced by a lightweight alternative.&lt;br /&gt;
** Deprecations, deprecations, deprecations. Lots of them in often used assertions (&amp;lt;tt&amp;gt;assertContains()&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;assertEquals()&amp;lt;/tt&amp;gt;...) and also &amp;lt;tt&amp;gt;@expectedExceptionXXX&amp;lt;/tt&amp;gt; annotations. Again, note that all them will become errors with PHPUnit 9.&lt;br /&gt;
* Finally, it&#039;s also a good idea to [https://github.com/moodle/moodle/compare/5903054...b13ec3c browse the changes associated with the issue], hopefully with useful enough explanations in the commit messages.&lt;br /&gt;
&lt;br /&gt;
=Upgrading unit tests to work with Moodle 3.7 and up (PHPUnit 7.5)=&lt;br /&gt;
{{Moodle 3.7}}&lt;br /&gt;
&lt;br /&gt;
With Moodle 3.7, &#039;&#039;&#039;PHPUnit was upgraded to 7.5&#039;&#039;&#039; (from 6.x being used in older version). This was done to better align the testing environment with PHP versions supported by Moodle 3.7 (7.1, 7.2 and 7.3). (see MDL-65204 and linked issues for more details). While internally [https://phpunit.de/announcements/phpunit-7.html a lot of things changed with PHPUnit 7] (PHP 7.1-isms, typed signatures, void returns, assertEquals() changes), thanks to our &#039;&#039;&#039;wrapping layer&#039;&#039;&#039; (basic and advanced testcases...) impact expected into old existing unit tests is expected to be reduced and upgrades, easy to achieve.&lt;br /&gt;
&lt;br /&gt;
To find more information about the changes coming with PHPUnit 7, it&#039;s recommended to read the following resources:&lt;br /&gt;
* [https://phpunit.de/announcements/phpunit-7.html  PHPUnit 7 release Announcement].&lt;br /&gt;
* [https://github.com/sebastianbergmann/phpunit/blob/520723129e2b3fc1dc4c0953e43c9d40e1ecb352/ChangeLog-7.5.md Detailed changelog of the release], paying special attention to the added, deprecated, changed and deleted sections.&lt;br /&gt;
* [https://phpunit.readthedocs.io/en/7.5/ Official PHPUnit manual].&lt;br /&gt;
* Changes performed into core, mainly: new, stricter, signatures ([https://github.com/moodle/moodle/commit/26218b7 26218b7]) and assertEquals() changes, specially important when comparing strings, now performed using strict (===) equals ([https://github.com/moodle/moodle/commit/85f47ba 85f47ba]).&lt;br /&gt;
&lt;br /&gt;
=Upgrading unit tests to work with Moodle 3.4 and up (PHPUnit 6)=&lt;br /&gt;
{{Moodle 3.4}}&lt;br /&gt;
&lt;br /&gt;
With Moodle 3.4, &#039;&#039;&#039;PHPUnit was upgraded to 6.4&#039;&#039;&#039; (from 5.5 being used in older version). This was done to better align the testing environment with PHP versions supported by Moodle 3.4 (7.0, 7.1 and 7.2). (see MDL-60611 and linked issues for more details). While internally [https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-6.0.0#backwards-compatibility-issues a lot of things changed with PHPUnit 6] (namespaced classes being the more noticeable), thanks to our &#039;&#039;&#039;wrapping layer&#039;&#039;&#039; (basic and advanced testcases...) impact expected into old existing unit tests is expected to be reduced and upgrades, easy to achieve.&lt;br /&gt;
&lt;br /&gt;
Still, in &#039;&#039;&#039;some cases, it will impossible to maintain compatibility&#039;&#039;&#039; of tests between old (pre 3.4) tests and new ones, especially &#039;&#039;&#039;when direct use of any phpunit class is performed&#039;&#039;&#039;. Luckily, both travis and CI tests will detect this situation and it shouldn&#039;t be hard to keep all supported branches in core passing ok. Plugins may be trickier, if the same branch is attempting to work against multiple core branches and they are using some phpunit class directly.&lt;br /&gt;
&lt;br /&gt;
To find more information about the changes coming with PHPUnit 6, it&#039;s recommended to read the following resources:&lt;br /&gt;
* [https://thephp.cc/news/2017/02/migrating-to-phpunit-6 A very good mini-guide] showing all the important changes.&lt;br /&gt;
* [https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-6.0.0#backwards-compatibility-issues PHPUnit 6 release Announcement].&lt;br /&gt;
* [https://github.com/sebastianbergmann/phpunit/blob/9d0c024d2099531442d862b66b0ad7cf35ed8e78/ChangeLog-6.0.md Detailed changelog of the release], paying special attention to the changed and deleted sections.&lt;br /&gt;
* Changes performed into core, mainly: namespace class renaming ([https://github.com/moodle/moodle/commit/801a372dadb6e11c8781547603e3f0a59ce5638f 801a372]) and deprecated stuff ([https://github.com/moodle/moodle/commit/796e48a58bf18533bdca423fff7949ab119101c4 796e48a])&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[PHPUnit integration]]&lt;br /&gt;
* [[PHPUnit]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Farhan6318</name></author>
	</entry>
</feed>