<?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=Mattc</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=Mattc"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Mattc"/>
	<updated>2026-06-06T10:47:18Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=LESS&amp;diff=42489</id>
		<title>LESS</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=LESS&amp;diff=42489"/>
		<updated>2013-10-02T21:28:43Z</updated>

		<summary type="html">&lt;p&gt;Mattc: node is something other than node.js&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
LESS ([http://lesscss.org lesscss.org]) extends CSS with dynamic behavior such as variables, mixins, operations and functions.  It&#039;s an advanced way of writing CSS that we use in some themes within Moodle.&lt;br /&gt;
&lt;br /&gt;
Browsers don&#039;t interpret it themselves, however, so LESS files need to be converted into normal CSS before use.&lt;br /&gt;
&lt;br /&gt;
Recess is one tool used to compile and compress LESS into CSS under *nix based systems.  There are [https://github.com/cloudhead/less.js/wiki/GUI-compilers-that-use-LESS.js many others tools for LESS].&lt;br /&gt;
&lt;br /&gt;
== The bootstrapbase theme ==&lt;br /&gt;
&lt;br /&gt;
Moodle&#039;s [[Bootstrap]] base theme has rules written using LESS.&lt;br /&gt;
&lt;br /&gt;
The main LESS file is &#039;&#039;&#039;theme/bootstrapbase/less/moodle.less&#039;&#039;&#039;, with additional files  in &#039;&#039;&#039;theme/bootstrapbase/less/moodle/&#039;&#039;&#039; imported by the main file. &lt;br /&gt;
&lt;br /&gt;
After compiling the LESS files, CSS ends up in &#039;&#039;&#039;theme/bootstrapbase/style/moodle.css&#039;&#039;&#039;.  This file should not be edited manually.&lt;br /&gt;
&lt;br /&gt;
== Installing Recess ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu ===&lt;br /&gt;
&lt;br /&gt;
The following commands should be run to install Recess&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
sudo apt-get install npm nodejs&lt;br /&gt;
# If the above fails due to the error &amp;quot;The following packages have unmet dependencies&amp;quot;,&lt;br /&gt;
# run the commands separately, ie.&lt;br /&gt;
#     sudo apt-get install npm&lt;br /&gt;
# and then&lt;br /&gt;
#     sudo apt-get install nodejs&lt;br /&gt;
npm install recess -g&lt;br /&gt;
# If the above fails with a &amp;quot;..permission denied..&amp;quot; error,&lt;br /&gt;
# run npm install with sudo:&lt;br /&gt;
#     sudo npm install recess -g&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;npm&amp;lt;/code&amp;gt; stands for Node Package Manager, and is the equivalent of apt-get for node.js packages.&lt;br /&gt;
&lt;br /&gt;
=== Mac OS X ===&lt;br /&gt;
1. Install the basic node packages from the web site: [http://nodejs.org http://nodejs.org]   (or use your favourite package manager to install &amp;lt;code&amp;gt;node&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;npm&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
2. On the command line, install recess like this:&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
npm install recess -g&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windows 7 ===&lt;br /&gt;
&lt;br /&gt;
In order to install Recess you need to have Node.js installed first, which is relatively simple to do.&lt;br /&gt;
&lt;br /&gt;
Go to nodejs.org click install. &lt;br /&gt;
&lt;br /&gt;
When installed go to -&amp;gt; Start -&amp;gt; All Programs -&amp;gt; type Node.js into the Search box, then select Node.js Command prompt (black icon) from the list. Now you are ready to install Recess. So at the command line prompt type the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
npm install recess -g&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;npm&amp;lt;/code&amp;gt; stands for Node Package Manager, and is the equivalent of apt-get for node.js packages.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Using Recess ==&lt;br /&gt;
&lt;br /&gt;
After editing the LESS files, compile (minified) your CSS as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
cd theme/bootstrapbase/less/&lt;br /&gt;
recess --compile --compress moodle.less &amp;gt; ../style/moodle.css&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or if you prefer to run it from the top-level:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
recess --compile --compress theme/bootstrapbase/less/moodle.less &amp;gt; theme/bootstrapbase/style/moodle.css&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will compile and compress the moodle.less file (and all the LESS and CSS files it imports) into a single file, moodle.css, and store it in the style folder of the bootstrapbase theme.&lt;br /&gt;
&lt;br /&gt;
Alternatively if you want to view the normal (un-minified) CSS then use the following method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
recess --compile moodle.less &amp;gt; ../style/moodle.css&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; if you are getting an empty moodle.css file, this is being caused by a parsing error in your LESS code. A bug in &amp;lt;code&amp;gt;recess&amp;lt;/code&amp;gt; currently prevents it giving you helpful error messages in many cases. You will need to examine what you have altered or written to make sure it is complete and the syntax is correct. The &amp;lt;code&amp;gt;lessc&amp;lt;/code&amp;gt; compiler is what is used by &amp;lt;code&amp;gt;recess&amp;lt;/code&amp;gt; to do the actual compiling and will have been installed automatically along with it. If you call it directly as &amp;lt;code&amp;gt;lessc moodle.less&amp;lt;/code&amp;gt; it should give you a helpful error message that points you to where the problem is.&lt;/div&gt;</summary>
		<author><name>Mattc</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File_API&amp;diff=33970</id>
		<title>File API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File_API&amp;diff=33970"/>
		<updated>2012-05-22T22:12:32Z</updated>

		<summary type="html">&lt;p&gt;Mattc: /* Delete file */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.0}}&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
The File API is for managing all the files stored by Moodle. If you are interested in how the file API works internally, see [[File API internals]]. The page is just about what you need to know to use the file API. Related is the [[Repository API]], which lets users get files into Moodle.&lt;br /&gt;
&lt;br /&gt;
If you are looking for an explanation on how to manage moodle files in moodle forms, you most likely need to read [[Using_the_File_API_in_Moodle_forms|Using the File API in Moodle forms]].&lt;br /&gt;
&lt;br /&gt;
==File areas==&lt;br /&gt;
&lt;br /&gt;
Files are conceptually stored in &#039;&#039;&#039;file areas&#039;&#039;&#039;. A file area is uniquely identified by:&lt;br /&gt;
* A context id.&lt;br /&gt;
* full component name (using [[Frankenstyle]]), for example &#039;course&#039;, &#039;mod_forum&#039;, &#039;mod_glossary&#039;, &#039;block_html&#039;.&lt;br /&gt;
* A file area type, for example &#039;intro&#039; or &#039;post&#039;.&lt;br /&gt;
* A unique itemid. Normally, the itemid relates to something depending on the file area type. For example, for a &#039;course&#039;, &#039;intro&#039; file area, the itemid is 0. For forum post, it is the post id.&lt;br /&gt;
&lt;br /&gt;
File areas are not listed separately anywhere, they are stored implicitly in the files table. Please note that each subsystem is allowed to access only own file areas, for example only code in /mod/assignment/* may access files with component &#039;mod_assignment&#039;.&lt;br /&gt;
&lt;br /&gt;
===Naming file areas===&lt;br /&gt;
&lt;br /&gt;
The names of the file areas are not strictly defined, but it is strongly recommended to use singulars and common names of areas if possible (intro, post, attachment, description, ...).&lt;br /&gt;
&lt;br /&gt;
==Serving files to users==&lt;br /&gt;
&lt;br /&gt;
You must refer to the file with a URL that includes a file-serving script, often pluginfile.php. For example&lt;br /&gt;
&lt;br /&gt;
The general form of the URL is something like&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$url = $CFG-&amp;gt;wwwroot/pluginfile.php/$contextid/$component/$filearea/arbitrary/extra/infomation.ext&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A specific example might be&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$url = $CFG-&amp;gt;wwwroot/pluginfile.php/$forumcontextid/mod_forum/post/$postid/image.jpg&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The file serving script then looks at the context id, and component name, and the file area name, and based on that arranges for the file to be served, following appropriate security checks.&lt;br /&gt;
&lt;br /&gt;
In most cases this is done by calling a callback function in the appropriate plugin, these functions are stored in lib.php files and named component_name_pluginfile() . The arbitrary/extra/infomation.ext is passed to the callback. For example, files in the mod_forum+post file area end up being served by the mod_forum_pluginfile function in mod/forum/lib.php.&lt;br /&gt;
&lt;br /&gt;
You normally use an API function to generate these URL automatically, most often the &amp;lt;tt&amp;gt;file_rewrite_pluginfile_urls&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
==Getting files from the user==&lt;br /&gt;
&lt;br /&gt;
* See [[Using_the_File_API_in_Moodle_forms|Using the File API in Moodle forms]]&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
Please note that in reality developers outside of core will not deal with file api directly in majority of cases, instead use formslib elements which are doing all this automatically.&lt;br /&gt;
&lt;br /&gt;
===Browsing files===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$browser = get_file_browser();&lt;br /&gt;
$context = get_system_context();&lt;br /&gt;
&lt;br /&gt;
$filearea = null;&lt;br /&gt;
$itemid   = null;&lt;br /&gt;
$filename = null;&lt;br /&gt;
if ($fileinfo = $browser-&amp;gt;get_file_info($context, $component, $filearea, $itemid, &#039;/&#039;, $filename)) {&lt;br /&gt;
    // build a Breadcrumb trail&lt;br /&gt;
    $level = $fileinfo-&amp;gt;get_parent();&lt;br /&gt;
    while ($level) {&lt;br /&gt;
        $path[] = array(&#039;name&#039;=&amp;gt;$level-&amp;gt;get_visible_name());&lt;br /&gt;
        $level = $level-&amp;gt;get_parent();&lt;br /&gt;
    }&lt;br /&gt;
    $path = array_reverse($path);&lt;br /&gt;
    $children = $fileinfo-&amp;gt;get_children();&lt;br /&gt;
    foreach ($children as $child) {&lt;br /&gt;
        if ($child-&amp;gt;is_directory()) {&lt;br /&gt;
            echo $child-&amp;gt;get_visible_name();&lt;br /&gt;
            // display contextid, itemid, component, filepath and filename&lt;br /&gt;
            var_dump($child-&amp;gt;get_params());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moving files around===&lt;br /&gt;
&lt;br /&gt;
For example, if you have just built a file at the path&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $from_zip_file = $CFG-&amp;gt;dataroot . &#039;/temp/backup/&#039; . $preferences-&amp;gt;backup_unique_code .&lt;br /&gt;
         &#039;/&#039; . $preferences-&amp;gt;backup_name;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
And you want to move it into the course_backup file area, do&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $context = get_context_instance(CONTEXT_COURSE, $preferences-&amp;gt;backup_course);&lt;br /&gt;
 $fs = get_file_storage();&lt;br /&gt;
 $file_record = array(&#039;contextid&#039;=&amp;gt;$context-&amp;gt;id, &#039;component&#039;=&amp;gt;&#039;course&#039;, &#039;filearea&#039;=&amp;gt;&#039;backup&#039;,&lt;br /&gt;
         &#039;itemid&#039;=&amp;gt;0, &#039;filepath&#039;=&amp;gt;&#039;/&#039;, &#039;filename&#039;=&amp;gt;$preferences-&amp;gt;backup_name,&lt;br /&gt;
         &#039;timecreated&#039;=&amp;gt;time(), &#039;timemodified&#039;=&amp;gt;time());&lt;br /&gt;
 $fs-&amp;gt;create_file_from_pathname($file_record, $from_zip_file);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List area files ===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$fs = get_file_storage();&lt;br /&gt;
$files = $fs-&amp;gt;get_area_files($contextid, &#039;mod_assignment&#039;, &#039;submission&#039;, $submission-&amp;gt;id);&lt;br /&gt;
foreach ($files as $f) {&lt;br /&gt;
    // $f is an instance of stored_file&lt;br /&gt;
    echo $f-&amp;gt;get_filename();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or as links...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$out = array();&lt;br /&gt;
        &lt;br /&gt;
$fs = get_file_storage();&lt;br /&gt;
$files = $fs-&amp;gt;get_area_files($contextid, &#039;mod_assignment&#039;, &#039;submission&#039;, $submission-&amp;gt;id);&lt;br /&gt;
            &lt;br /&gt;
foreach ($files as $file) {&lt;br /&gt;
    $url = &amp;quot;{$CFG-&amp;gt;wwwroot}/pluginfile.php/{$file-&amp;gt;get_contextid()}/mod_assignment/submission}&amp;quot;;&lt;br /&gt;
    $filename = $file-&amp;gt;get_filename();&lt;br /&gt;
    $fileurl = $url.$file-&amp;gt;get_filepath().$file-&amp;gt;get_itemid().&#039;/&#039;.$filename;&lt;br /&gt;
    $out[] = html_writer::link($fileurl, $filename);&lt;br /&gt;
}&lt;br /&gt;
      &lt;br /&gt;
$br = html_writer::empty_tag(&#039;br&#039;);&lt;br /&gt;
        &lt;br /&gt;
return implode($br, $out);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create file ===&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how to create a file whose contents will be a text string. This is the equivalent of the PHP function &amp;lt;tt&amp;gt;file_put_contents&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$fs = get_file_storage();&lt;br /&gt;
&lt;br /&gt;
// Prepare file record object&lt;br /&gt;
$fileinfo = array(&lt;br /&gt;
    &#039;contextid&#039; =&amp;gt; $context-&amp;gt;id, // ID of context&lt;br /&gt;
    &#039;component&#039; =&amp;gt; &#039;mod_mymodule&#039;,     // usually = table name&lt;br /&gt;
    &#039;filearea&#039; =&amp;gt; &#039;myarea&#039;,     // usually = table name&lt;br /&gt;
    &#039;itemid&#039; =&amp;gt; 0,               // usually = ID of row in table&lt;br /&gt;
    &#039;filepath&#039; =&amp;gt; &#039;/&#039;,           // any path beginning and ending in /&lt;br /&gt;
    &#039;filename&#039; =&amp;gt; &#039;myfile.txt&#039;); // any filename&lt;br /&gt;
&lt;br /&gt;
// Create file containing text &#039;hello world&#039;&lt;br /&gt;
$fs-&amp;gt;create_file_from_string($fileinfo, &#039;hello world&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to create a file in the Moodle file area based on a &#039;real&#039; file e.g. in a temporary folder, you can use &amp;lt;tt&amp;gt;create_file_from_pathname&amp;lt;/tt&amp;gt; instead.&lt;br /&gt;
&lt;br /&gt;
Unlike with ordinary files, this method will not automatically overwrite an existing file. If you wish to overwrite a file, you must first get the file and (if it exists) delete it, and only then create it again.&lt;br /&gt;
&lt;br /&gt;
=== Read file ===&lt;br /&gt;
&lt;br /&gt;
This is a way to read a file, equivalent to &amp;lt;tt&amp;gt;file_get_contents&amp;lt;/tt&amp;gt;. &#039;&#039;&#039;Please note your are allowed to do this ONLY from mod/mymodule/* code, it is not acceptable to do this anywhere else.&#039;&#039;&#039; Other code has to use file_browser interface instead.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$fs = get_file_storage();&lt;br /&gt;
&lt;br /&gt;
// Prepare file record object&lt;br /&gt;
$fileinfo = array(&lt;br /&gt;
    &#039;component&#039; =&amp;gt; &#039;mod_mymodule&#039;,     // usually = table name&lt;br /&gt;
    &#039;filearea&#039; =&amp;gt; &#039;myarea&#039;,     // usually = table name&lt;br /&gt;
    &#039;itemid&#039; =&amp;gt; 0,               // usually = ID of row in table&lt;br /&gt;
    &#039;contextid&#039; =&amp;gt; $context-&amp;gt;id, // ID of context&lt;br /&gt;
    &#039;filepath&#039; =&amp;gt; &#039;/&#039;,           // any path beginning and ending in /&lt;br /&gt;
    &#039;filename&#039; =&amp;gt; &#039;myfile.txt&#039;); // any filename&lt;br /&gt;
&lt;br /&gt;
// Get file&lt;br /&gt;
$file = $fs-&amp;gt;get_file($fileinfo[&#039;contextid&#039;], $fileinfo[&#039;component&#039;], $fileinfo[&#039;filearea&#039;],&lt;br /&gt;
                      $fileinfo[&#039;itemid&#039;], $fileinfo[&#039;filepath&#039;], $fileinfo[&#039;filename&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Read contents&lt;br /&gt;
if ($file) {&lt;br /&gt;
    $contents = $file-&amp;gt;get_content();&lt;br /&gt;
} else {&lt;br /&gt;
    // file doesn&#039;t exist - do something&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to access the file directly on disk, this is not permitted. Instead, you need to make a copy of the file in a temporary area and use that. You can do this with &amp;lt;tt&amp;gt;$file-&amp;gt;copy_content_to($pathname)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Delete file ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$fs = get_file_storage();&lt;br /&gt;
&lt;br /&gt;
// Prepare file record object&lt;br /&gt;
$fileinfo = array(&lt;br /&gt;
    &#039;component&#039; =&amp;gt; &#039;mod_mymodule&#039;,&lt;br /&gt;
    &#039;filearea&#039; =&amp;gt; &#039;myarea&#039;,     // usually = table name&lt;br /&gt;
    &#039;itemid&#039; =&amp;gt; 0,               // usually = ID of row in table&lt;br /&gt;
    &#039;contextid&#039; =&amp;gt; $context-&amp;gt;id, // ID of context&lt;br /&gt;
    &#039;filepath&#039; =&amp;gt; &#039;/&#039;,           // any path beginning and ending in /&lt;br /&gt;
    &#039;filename&#039; =&amp;gt; &#039;myfile.txt&#039;); // any filename&lt;br /&gt;
&lt;br /&gt;
// Get file&lt;br /&gt;
$file = $fs-&amp;gt;get_file($fileinfo[&#039;contextid&#039;], $fileinfo[&#039;component&#039;], $fileinfo[&#039;filearea&#039;], &lt;br /&gt;
        $fileinfo[&#039;itemid&#039;], $fileinfo[&#039;filepath&#039;], $fileinfo[&#039;filename&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Delete it if it exists&lt;br /&gt;
if ($file) {&lt;br /&gt;
    $file-&amp;gt;delete();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Core APIs]]&lt;br /&gt;
* [[File API internals]] how the File API works internally.&lt;br /&gt;
* [[Using the File API in Moodle forms]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Files]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Mattc</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Filters_1.9_and_before&amp;diff=3305</id>
		<title>Filters 1.9 and before</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Filters_1.9_and_before&amp;diff=3305"/>
		<updated>2009-05-07T23:11:41Z</updated>

		<summary type="html">&lt;p&gt;Mattc: /* Adding a settings screen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Please note:&#039;&#039;&#039; This page contains information for developers. You may prefer to read the [[Filters| information about filters for teachers and administrators]].&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Filters&#039;&#039;&#039; allow for the for the automatic transformation of entered text into different, often more complex forms. For example the titles of [[Resources]] can automatically become hyperlinks that take you to the relevant resource, URLs pointing to [[mp3]] files can become [[Flash]] controls embedded in the webpage that let you pause and rewind the audio. The possibilities are endless and there are a number of standard filters included with Moodle and many more specialized filters contributed by the community.&lt;br /&gt;
&lt;br /&gt;
==To create a filter==&lt;br /&gt;
&lt;br /&gt;
To create a filter that removes all occurrences of the letter &amp;quot;x&amp;quot; - we&#039;ll call it &amp;quot;removex&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
# Create a new folder inside Moodle&#039;s /filter/ folder, called &amp;quot;removex&amp;quot;&lt;br /&gt;
# Create a new PHP script file inside the folder you&#039;ve just created - name it &amp;quot;filter.php&amp;quot;&lt;br /&gt;
# Write a new PHP function in this file, called &amp;quot;removex_filter()&amp;quot; which takes two parameters - a course ID and a piece of text to be filtered - and returns the processed text.&lt;br /&gt;
&lt;br /&gt;
For our example the filter.php file would look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
function removex_filter($courseid, $text) {&lt;br /&gt;
    return str_replace(&#039;x&#039;, &#039;&#039;, $text);&lt;br /&gt;
}&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When trying this out, remember to make sure that you activate the filter in the [[Filters|filters administration screen]].&lt;br /&gt;
&lt;br /&gt;
Also remember that text filtering functions, when activated, will be used intensively by the server, so you should optimise the filters as far as possible (cut down on database calls etc). Moodle caches the results of filtering to help with processing speed, but it&#039;s still worth being careful about your filter design.&lt;br /&gt;
&lt;br /&gt;
Filters are applied to all text that is printed with the [[Output functions|output functions]] format_text() or format_string(). One thing to keep in mind when designing the filter is that the function format_text() first applies other transformations (for example text_to_html() or replace_smilies()) before the strings are passed to your filter. The function format_string() on the other hand passes the string as it is.&lt;br /&gt;
&lt;br /&gt;
==Adding a settings screen==&lt;br /&gt;
&lt;br /&gt;
Moodle 1.6 added the options for filters to have their own settings screen. To do this perform the following steps:&lt;br /&gt;
* In the same folder as the filter create a file called &#039;&#039;&#039;filtersettings.php&#039;&#039;&#039;.&lt;br /&gt;
* Add admin_setting objects to the $settings page like this:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_configcheckbox(&#039;filter_myfilter/mysetting&#039;,&lt;br /&gt;
        get_string(&#039;mysetting&#039;, &#039;filter_myfilter&#039;),&lt;br /&gt;
        get_string(&#039;configmysetting&#039;, &#039;filter_myfilter&#039;), 0));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In standard Moodle, the censor, mediaplugin and tex filters have good examples of what you need to do.&lt;br /&gt;
&lt;br /&gt;
==A note on language strings==&lt;br /&gt;
&lt;br /&gt;
As the sharp-eyed will have noticed in the last section, the language strings for your filter (if any) should go in the file filter/myfilter/lang/en_utf8/filter_myfilter.php, and can be accessed using&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;mystring&#039;, &#039;filter_myfilter&#039;).&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that every filter must define the string &#039;filtername&#039;, so you can copy and paste the following to start your filter_myfilter.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php // $Id$&lt;br /&gt;
// Language string for filter/myfilter.&lt;br /&gt;
&lt;br /&gt;
$string[&#039;filtername&#039;] = &#039;My magic filter.&#039;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Filters 2.0]] The new version of these instructions for after Moodle 2.0 is released.&lt;br /&gt;
* [[Filters schema]] - a page containing some ideas and thoughts about modifications to the filters system&lt;br /&gt;
* [[Filters]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Filters]]&lt;br /&gt;
[[Category:Filter]]&lt;/div&gt;</summary>
		<author><name>Mattc</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Validation&amp;diff=6083</id>
		<title>lib/formslib.php Validation</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Validation&amp;diff=6083"/>
		<updated>2007-12-10T19:38:06Z</updated>

		<summary type="html">&lt;p&gt;Mattc: /* MoodleQuickForm::addRule() */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Formslib}}&lt;br /&gt;
&lt;br /&gt;
There are two ways to add validation in the forms lib.&lt;br /&gt;
&lt;br /&gt;
== MoodleQuickForm::addRule() ==&lt;br /&gt;
&lt;br /&gt;
You use this typically inside your moodleform::definition method. For example to set a field as required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;,&#039;shortname&#039;, get_string(&#039;shortname&#039;),&#039;maxlength=&amp;quot;15&amp;quot; size=&amp;quot;10&amp;quot;&#039;);&lt;br /&gt;
        $mform-&amp;gt;setHelpButton(&#039;shortname&#039;, array(&#039;courseshortname&#039;, get_string(&#039;shortname&#039;)), true);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;shortname&#039;, get_string(&#039;defaultcourseshortname&#039;));&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;shortname&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;shortname&#039;, PARAM_MULTILANG);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is good documentation for this on the [http://pear.php.net/manual/en/package.html.html-quickform.intro-validation.php PEAR web site]&lt;br /&gt;
&lt;br /&gt;
In Moodle formslib you can set certain rules&#039; error message to null and a default error message will automatically be used. The default messages are defined in lang/{language}/form.php. Here are the English definitions :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$string[&#039;err_alphanumeric&#039;]=&#039;You must enter only letters or numbers here.&#039;;&lt;br /&gt;
$string[&#039;err_email&#039;]=&#039;You must enter a valid email address here.&#039;;&lt;br /&gt;
$string[&#039;err_lettersonly&#039;]=&#039;You must enter only letters here.&#039;;&lt;br /&gt;
$string[&#039;err_maxlength&#039;]=&#039;You must enter not more than $a-&amp;gt;format characters here.&#039;;&lt;br /&gt;
$string[&#039;err_minlength&#039;]=&#039;You must enter at least $a-&amp;gt;format characters here.&#039;;&lt;br /&gt;
$string[&#039;err_nopunctuation&#039;]=&#039;You must enter no punctuation characters here.&#039;;&lt;br /&gt;
$string[&#039;err_nonzero&#039;]=&#039;You must enter a number not starting with a 0 here.&#039;;&lt;br /&gt;
$string[&#039;err_numeric&#039;]=&#039;You must enter a number here.&#039;;&lt;br /&gt;
$string[&#039;err_rangelength&#039;]=&#039;You must enter between {$a-&amp;gt;format[0]} and {$a-&amp;gt;format[1]} characters here.&#039;;&lt;br /&gt;
$string[&#039;err_required&#039;]=&#039;You must supply a value here.&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== moodleform::validation() ==&lt;br /&gt;
&lt;br /&gt;
Define a method validation on your moodleform child to make your own custom validation for the form. This is done on the client side. And data_submitted will return null until the function returns no errors. You return an array of errors if there is any error or an empty array if there are no errors.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class course_edit_form extends moodleform {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        blah blah;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/// perform some extra moodle validation&lt;br /&gt;
    function validation($data) {&lt;br /&gt;
        $errors= array();&lt;br /&gt;
        if ($foundcourses = get_records(&#039;course&#039;, &#039;shortname&#039;, $data[&#039;shortname&#039;])) {&lt;br /&gt;
            if (!empty($data[&#039;id&#039;])) {&lt;br /&gt;
                unset($foundcourses[$data[&#039;id&#039;]]);&lt;br /&gt;
            }&lt;br /&gt;
            if (!empty($foundcourses)) {&lt;br /&gt;
                foreach ($foundcourses as $foundcourse) {&lt;br /&gt;
                    $foundcoursenames[] = $foundcourse-&amp;gt;fullname;&lt;br /&gt;
                }&lt;br /&gt;
                $foundcoursenamestring = implode(&#039;,&#039;, $foundcoursenames);&lt;br /&gt;
                $errors[&#039;shortname&#039;]= get_string(&#039;shortnametaken&#039;, &#039;&#039;, $foundcoursenamestring);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (empty($data[&#039;enrolenddisabled&#039;])){&lt;br /&gt;
            if ($data[&#039;enrolenddate&#039;] &amp;lt;= $data[&#039;enrolstartdate&#039;]){&lt;br /&gt;
                $errors[&#039;enroldateendgrp&#039;] = get_string(&#039;enrolenddaterror&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        return $errors;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Moodle 1.9}}There is a new parameter $files in Moodle 1.9, it allows validation of uploaded files too.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function validation($data, $files) {&lt;br /&gt;
        $errors = parrent::validate($data, $files);&lt;br /&gt;
        if (empty($files[&#039;userfile&#039;])) {&lt;br /&gt;
            if (array_key_exists(&#039;url&#039;, $data)) {&lt;br /&gt;
                $errors[&#039;url&#039;] = get_string(&#039;required&#039;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        return $errors;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mattc</name></author>
	</entry>
</feed>