<?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=Sunner</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=Sunner"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Sunner"/>
	<updated>2026-09-16T16:05:26Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Using_the_File_API_in_Moodle_forms&amp;diff=26829</id>
		<title>Using the File API in Moodle forms</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Using_the_File_API_in_Moodle_forms&amp;diff=26829"/>
		<updated>2011-07-05T02:15:45Z</updated>

		<summary type="html">&lt;p&gt;Sunner: /* Add file manager element */ The default value of subdirs is 1 not 0. I tried and proved this.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
This document shows you exactly how to use Moodle forms to get files from users in a standard and secure way.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.0 all files are stored in a central database accessible via the [[File API|File API]], and every file is associated with a component and a &amp;quot;file area&amp;quot; in Moodle, such as a particular module.&lt;br /&gt;
&lt;br /&gt;
A common use case is to provide a form (using Moodle&#039;s [[lib/formslib.php|Forms API]]) which allows users to upload or import files as attachments or media embedded into HTML.&lt;br /&gt;
&lt;br /&gt;
Normally this works like this:&lt;br /&gt;
# User starts creation or re-edits an existing item in Moodle (eg forum post, resource, glossary entry etc)&lt;br /&gt;
# User presses some sort of button to browse for new files to attach or embed&lt;br /&gt;
# User sees our &amp;quot;Choose file...&amp;quot; dialog, which contains one or more repository instances. &lt;br /&gt;
# User chooses a file, the [[Repository API|Repository API]] takes care of copying the file into a &amp;quot;draft file area&amp;quot; within Moodle&lt;br /&gt;
# File appears in the text or as an attachment in the form.&lt;br /&gt;
# When the user hits save, the [[File API|File API]] is invoked to move the file from the draft file area into a permanent file area associated with that data &lt;br /&gt;
&lt;br /&gt;
This document shows you exactly how to use Moodle forms to interact with users in a standard and secure way.&lt;br /&gt;
&lt;br /&gt;
If you just want to write code to manipulate Moodle files internally (without user input) then see [[Using_the_File_API]].&lt;br /&gt;
&lt;br /&gt;
==Form elements== &lt;br /&gt;
&lt;br /&gt;
In Moodle 2.0 there are three file-related form elements for interacting with users:&lt;br /&gt;
&lt;br /&gt;
# filemanager - the way to attach one or more files as a set&lt;br /&gt;
# editor - the way to specify a textarea with a HTML editor, and all the handling of images and movies within that HTML&lt;br /&gt;
# filepicker - a way to specify one file for the case when you want to process the file and throw it away &lt;br /&gt;
&lt;br /&gt;
In Moodle 1.9 there were two other types which are now &#039;&#039;&#039;deprecated&#039;&#039;&#039; (they work, but please do not use these anymore)&lt;br /&gt;
# file - used to just allow a normal file upload from the desktop only.&lt;br /&gt;
# htmleditor - this old method of embedding a HTML editor in a textarea is not able to support repositories etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===filepicker===&lt;br /&gt;
&lt;br /&gt;
File picker (&#039;&#039;filepicker&#039;&#039;) is a direct replacement of the older &#039;&#039;file&#039;&#039; formslib element. &lt;br /&gt;
&lt;br /&gt;
It is intended for situations when you want the user to upload &#039;&#039;&#039;one&#039;&#039;&#039; file so you can process it and delete it, such as when you are importing data from a CSV file.&lt;br /&gt;
&lt;br /&gt;
==== Using the filepicker element ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;filepicker&#039;, &#039;userfile&#039;, get_string(&#039;file&#039;), null, array(&#039;maxbytes&#039; =&amp;gt; $maxbytes, &#039;accepted_types&#039; =&amp;gt; &#039;*&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Obtain the chosen file ====&lt;br /&gt;
&lt;br /&gt;
The API for getting file contents is exactly the same as for &#039;&#039;file&#039;&#039; element.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$content = $mform-&amp;gt;get_file_content(&#039;userfile&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== filemanager ===&lt;br /&gt;
&lt;br /&gt;
The File Manager element improves on file picker by allowing you to manage more than one file.  It is expected that the files will be stored permanently for future use (such as forum and glossary attachments).&lt;br /&gt;
&lt;br /&gt;
==== Add file manager element ====&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;filemanager&#039;, &#039;attachments&#039;, get_string(&#039;attachment&#039;, &#039;moodle&#039;), null,&lt;br /&gt;
                    array(&#039;subdirs&#039; =&amp;gt; 0, &#039;maxbytes&#039; =&amp;gt; $maxbytes, &#039;maxfiles&#039; =&amp;gt; 50, &#039;accepted_types&#039; =&amp;gt; array(&#039;document&#039;) ));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here are the fields for filemanager:&lt;br /&gt;
&lt;br /&gt;
;&#039;filemanager&#039;:This is a filemanager element :)&lt;br /&gt;
;elementname:The unique name of the element in the form&lt;br /&gt;
;elementlabel:The label string that users see &lt;br /&gt;
;attributes:(leave it as null)&lt;br /&gt;
;options: an array of further options for the filepicker (see below)&lt;br /&gt;
&lt;br /&gt;
The options array can contain:&lt;br /&gt;
&lt;br /&gt;
;subdirs:(Default 1) Are subdirectories allowed?  (true or false)&lt;br /&gt;
;maxbytes:(Default 0) Restricts the total size of all the files.&lt;br /&gt;
;maxfiles:(Default -1) Restricts the total number of files.&lt;br /&gt;
;accepted_types:(Default *) You can specify what file types are accepted by filemanager.  All current file types are listed in this file: [http://cvs.moodle.org/moodle/lib/filestorage/file_types.mm moodle/lib/filestorage/file_types.mm].  This is a [http://freemind.sourceforge.net/wiki/index.php/Main_Page freemind] file: if it is edited the changes will be immediately reflected in Moodle.  Example usage:  &#039;&#039;&#039;array(&#039;audio&#039;, &#039;video&#039;, &#039;documents&#039;)&#039;&#039;&#039;, you can include file extensions as well, for example: &#039;&#039;&#039;array(&#039;*.txt&#039;, &#039;*.jpg&#039;, &#039;audio&#039;)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Load existing files into draft area ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (empty($entry-&amp;gt;id)) {&lt;br /&gt;
    $entry = new object();&lt;br /&gt;
    $entry-&amp;gt;id = null;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$draftitemid = file_get_submitted_draft_itemid(&#039;attachments&#039;);&lt;br /&gt;
file_prepare_draft_area($draftitemid, $context-&amp;gt;id, &#039;mod_glossary&#039;, &#039;attachment&#039;, $entry-&amp;gt;id, array(&#039;subdirs&#039; =&amp;gt; 0, &#039;maxbytes&#039; =&amp;gt; $maxbytes, &#039;maxfiles&#039; =&amp;gt; 50));&lt;br /&gt;
$entry-&amp;gt;attachments = $draftitemid;&lt;br /&gt;
&lt;br /&gt;
$mform-&amp;gt;set_data($entry);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Store updated set of files ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
    // ... store or update $entry&lt;br /&gt;
    file_save_draft_area_files($data-&amp;gt;attachments, $context-&amp;gt;id, &#039;mod_glossary&#039;, &#039;attachment&#039;, $entry-&amp;gt;id, array(&#039;subdirs&#039; =&amp;gt; 0, &#039;maxbytes&#039; =&amp;gt; $maxbytes, &#039;maxfiles&#039; =&amp;gt; 50));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===editor===&lt;br /&gt;
There are two way for using of editor element in code, the first one is easier but expects some standardized fields. The second method is more low level.&lt;br /&gt;
&lt;br /&gt;
====Simple use====&lt;br /&gt;
# name database fields: &#039;&#039;textfield&#039;&#039;, &#039;&#039;textfieldformat&#039;&#039; (and &#039;&#039;textfieldtrust&#039;&#039; if required)&lt;br /&gt;
# create options array &amp;lt;code php&amp;gt;$textfieldoptions = array(&#039;trusttext&#039;=&amp;gt;true, &#039;subdirs&#039;=&amp;gt;true, &#039;maxfiles&#039;=&amp;gt;$maxfiles, &#039;maxbytes&#039;=&amp;gt;$maxbytes);&amp;lt;/code&amp;gt;&lt;br /&gt;
# add editor &#039;&#039;textfield_editor&#039;&#039; to moodle form, pass options through custom data in form constructor, set $data-&amp;gt;id to null if data not exist yet &amp;lt;code php&amp;gt;$mform-&amp;gt;addElement(&#039;editor&#039;, &#039;textfield_editor&#039;, get_string(&#039;fieldname&#039;, &#039;somemodule&#039;), null, $textfieldoptions);&amp;lt;/code&amp;gt;&lt;br /&gt;
# prepare data &amp;lt;code php&amp;gt;$data = file_prepare_standard_editor($data, &#039;textfield&#039;, $textfieldoptions, $context, &#039;mod_somemodule&#039;, &#039;somearea&#039;, $data-&amp;gt;id);&amp;lt;/code&amp;gt;&lt;br /&gt;
# get submitted data and after inserting/updating of data &amp;lt;code php&amp;gt;$data = file_postupdate_standard_editor($data, &#039;textfield&#039;, $textfieldoptions, $context, &#039;mod_somemodule&#039;, &#039;somearea&#039;, $data-&amp;gt;id);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Real world examples are in mod/glossary/edit.php and mod/glossary/comment.php&lt;br /&gt;
&lt;br /&gt;
====Low level use====&lt;br /&gt;
&lt;br /&gt;
When using editor element you  need to preprocess and postprocess the data:&lt;br /&gt;
# detect if form was already submitted (usually means draft is area already exists) - &#039;&#039;file_get_submitted_draft_itemid()&#039;&#039;&lt;br /&gt;
# prepare draft file area, temporary storage of all files attached to the text - &#039;&#039;file_prepare_draft_area()&#039;&#039;&lt;br /&gt;
# convert encoded relative links to absolute links - &#039;&#039;file_prepare_draft_area()&#039;&#039;&lt;br /&gt;
# create form and set current data&lt;br /&gt;
# after submission the changed files must be merged back into original area - &#039;&#039;file_save_draft_area_files()&#039;&#039;&lt;br /&gt;
# absolute links have to be replaced by relative links - &#039;&#039;file_save_draft_area_files()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=====Replace old htmleditor with editor=====&lt;br /&gt;
&lt;br /&gt;
The file picker has been integrated with with TinyMCE to make the editor element. This new element should support all types on editors and should be able to switch them on-the-fly. Instances of the old htmleditor element in your forms should be replaced by the new editor element, this may need adding of new format and trusttext columns. For example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;editor&#039;, &#039;entry&#039;, get_string(&#039;definition&#039;, &#039;glossary&#039;), null,&lt;br /&gt;
        array(&#039;maxfiles&#039; =&amp;gt; EDITOR_UNLIMITED_FILES));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The editor element can take following options: maxfiles, maxbytes, subdirs and changeformat. Please note that the embedded files is optional feature and is not expected be used everywhere.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: the editor element now includes text format option. You should no longer use the separate format element type.&lt;br /&gt;
&lt;br /&gt;
=====Prepare current data - text and files=====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (empty($entry-&amp;gt;id)) {&lt;br /&gt;
  $entry = new object();&lt;br /&gt;
  $entry-&amp;gt;id = null;&lt;br /&gt;
  $entry-&amp;gt;definition = &#039;&#039;;&lt;br /&gt;
  $entry-&amp;gt;format = FORMAT_HTML;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$draftid_editor = file_get_submitted_draft_itemid(&#039;entry&#039;);&lt;br /&gt;
$currenttext = file_prepare_draft_area($draftid_editor, $context-&amp;gt;id, &#039;mod_glossary&#039;, &#039;entry&#039;, $entry-&amp;gt;id, array(&#039;subdirs&#039;=&amp;gt;true), $entry-&amp;gt;definition);&lt;br /&gt;
$entry-&amp;gt;entry = array(&#039;text&#039;=&amp;gt;$currenttext, &#039;format&#039;=&amp;gt;$entry-&amp;gt;format, &#039;itemid&#039;=&amp;gt;$draftid_editor);&lt;br /&gt;
&lt;br /&gt;
$mform-&amp;gt;set_data($entry);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If there are multiple files, they will share the same itemid.&lt;br /&gt;
&lt;br /&gt;
=====Obtain text, format and save draft files=====&lt;br /&gt;
&lt;br /&gt;
To retrieve editor content, you need to use following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if ($fromform = $mform-&amp;gt;get_data()) {&lt;br /&gt;
    // content of editor&lt;br /&gt;
    $messagetext = $fromform-&amp;gt;entry[&#039;text&#039;];&lt;br /&gt;
    // format of content&lt;br /&gt;
    $messageformat  = $fromform-&amp;gt;entry[&#039;format&#039;];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user selects a file using the file picker, the file is initially stored in a draft file area, and a URL is inserted into the HTML in the editor that lets the person editing the content (but no one else) see the file.&lt;br /&gt;
&lt;br /&gt;
When the user submits the form, we then need to save the draft files to the correct place in permanent storage. (Just like you have to call $DB-&amp;gt;update_record(&#039;tablename&#039;, $data); to have the other parts of the form submission stored correctly.)&lt;br /&gt;
&lt;br /&gt;
The save_files_from_draft_area function and replace absolute links with internal relative links do:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$messagetext = file_save_draft_area_files($draftid_editor, $context-&amp;gt;id, &#039;mod_glossary&#039;, &#039;entry&#039;, $entry-&amp;gt;id, array(&#039;subdirs&#039;=&amp;gt;true), $messagetext);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
; $context-&amp;gt;id, &#039;component&#039;, &#039;proper_file_area&#039; and $entry-&amp;gt;id : correspond to the contextid, filearea and itemid columns in the [[File_API#Table:_files|files table]].&lt;br /&gt;
; $messagetext : this is the message text. As the files are saved to the real file area, the URLs in this content are rewritten.&lt;br /&gt;
&lt;br /&gt;
All URLs in content that point to files managed to the File API are converted to a form that starts &#039;@@PLUGINFILE@@/&#039; before the content is stored in the database. That is what we mean by rewriting.&lt;br /&gt;
&lt;br /&gt;
== File serving==&lt;br /&gt;
&lt;br /&gt;
=== Convert internal relative links to absolute links ===&lt;br /&gt;
&lt;br /&gt;
Before text content is displayed to the user, any URLs in the &#039;@@PLUGINFILE@@/&#039; form in the content need to be rewritten to the real URL where the user can access the files. &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$messagetext = file_rewrite_pluginfile_urls($messagetext, &#039;pluginfile.php&#039;,&lt;br /&gt;
        $context-&amp;gt;id, &#039;mod_mymodule&#039;, &#039;proper_file_area&#039;, $itemid);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
; $messagetext : is the content containing the @@PLUGINFILE@@ URLs from the database.&lt;br /&gt;
; &#039;pluginfile.php&#039; : there are a number of different scripts that can serve files with different permissions checks. You need to specify which one to use.&lt;br /&gt;
; $context-&amp;gt;id, &#039;mod_mymodule&#039;, &#039;proper_file_area&#039;, $itemid : uniquely identifies the file area, as before.&lt;br /&gt;
&lt;br /&gt;
=== Implement file serving access control ===&lt;br /&gt;
&lt;br /&gt;
Attachments and embedded images should have the same access control like the text itself, in majority of cases these files are served using pluginfile.php. Access control is defined in &#039;&#039;module/lib.php&#039;&#039; file in function &#039;&#039;module_pluginfile()&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File browsing support ==&lt;br /&gt;
Only owner of each file area is allowed to use low level File API function to access files, other parts of Moodle should use file browsing API.&lt;br /&gt;
&lt;br /&gt;
Activities may specify browsing support in own module/lib.php file by implementing functions module_get_file_areas() and module_get_file_info().&lt;br /&gt;
&lt;br /&gt;
== Upgrading your code ==&lt;br /&gt;
Here I will attempt to describe some simple steps you can take to upgrade your file-handling form elements from pre-2.0 code to 2.0. We will use the example of glossary, since it has been used above.&lt;br /&gt;
&lt;br /&gt;
=== Preparing your options ===&lt;br /&gt;
Unless you are happy with the defaults, you will need to define an array of options for each file-handling form element. You could define it at different places, but it&#039;s best to put it in one place and make the array(s) available to other files if they need it. In the majority of cases, this will be in a file like edit.php&lt;br /&gt;
&lt;br /&gt;
Previous code in mod/glossary/edit.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform =&amp;amp; new mod_glossary_entry_form(null, compact(&#039;cm&#039;, &#039;glossary&#039;, &#039;hook&#039;, &#039;mode&#039;, &#039;e&#039;, &#039;context&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
New code:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$maxbytes = $course-&amp;gt;maxbytes; // Could also use $CFG-&amp;gt;maxbytes if you are not coding within a course context&lt;br /&gt;
$definitionoptions = array(&#039;subdirs&#039;=&amp;gt;false, &#039;maxfiles&#039;=&amp;gt;99, &#039;maxbytes&#039;=&amp;gt;$maxbytes, &#039;trusttext&#039;=&amp;gt;true, &#039;context&#039;=&amp;gt;$context);&lt;br /&gt;
$attachmentoptions = array(&#039;subdirs&#039;=&amp;gt;false, &#039;maxfiles&#039;=&amp;gt;99, &#039;maxbytes&#039;=&amp;gt;$maxbytes);&lt;br /&gt;
$mform = new mod_glossary_entry_form(null, array(&lt;br /&gt;
        &#039;current&#039;=&amp;gt;$entry, &lt;br /&gt;
        &#039;cm&#039;=&amp;gt;$cm, &lt;br /&gt;
        &#039;glossary&#039;=&amp;gt;$glossary,&lt;br /&gt;
        &#039;definitionoptions&#039;=&amp;gt;$definitionoptions, &lt;br /&gt;
        &#039;attachmentoptions&#039;=&amp;gt;$attachmentoptions));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Note that the data being passed to the form constructor have changed also, but this is not part of the file API changes, I just include them to avoid confusion.&lt;br /&gt;
&lt;br /&gt;
These options are for the htmleditor (definition field) and the filemanager (attachment field). They are used by a file called edit_form.php.&lt;br /&gt;
&lt;br /&gt;
=== Element preparation ===&lt;br /&gt;
Before we look at this, however, we need to &amp;quot;prepare&amp;quot; the elements so that they can correctly display existing embedded images and attached files when you are editing a record instead of just creating one. So, let&#039;s take the code we&#039;ve got so far in edit.php and add to it:&lt;br /&gt;
&lt;br /&gt;
Currently upgraded code in edit.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform = new mod_glossary_entry_form(null, array(&lt;br /&gt;
        &#039;current&#039;=&amp;gt;$entry, &lt;br /&gt;
        &#039;cm&#039;=&amp;gt;$cm, &lt;br /&gt;
        &#039;glossary&#039;=&amp;gt;$glossary,&lt;br /&gt;
        &#039;definitionoptions&#039;=&amp;gt;$definitionoptions, &lt;br /&gt;
        &#039;attachmentoptions&#039;=&amp;gt;$attachmentoptions));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
New code with element preparation:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$entry = file_prepare_standard_editor($entry, &#039;definition&#039;, $definitionoptions, $context, &#039;mod_glossary&#039;, &#039;entry&#039;, $entry-&amp;gt;id);&lt;br /&gt;
$entry = file_prepare_standard_filemanager($entry, &#039;attachment&#039;, $attachmentoptions, $context, &#039;mod_glossary&#039;, &#039;attachment&#039;, $entry-&amp;gt;id);&lt;br /&gt;
$mform = new mod_glossary_entry_form(null, array(&lt;br /&gt;
        &#039;current&#039;=&amp;gt;$entry, &lt;br /&gt;
        &#039;cm&#039;=&amp;gt;$cm, &lt;br /&gt;
        &#039;glossary&#039;=&amp;gt;$glossary,&lt;br /&gt;
        &#039;definitionoptions&#039;=&amp;gt;$definitionoptions, &lt;br /&gt;
        &#039;attachmentoptions&#039;=&amp;gt;$attachmentoptions));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Things to note:&lt;br /&gt;
* $entry in this case is simply a stdClass object which may either represent a new glossary entry or an existing one.&lt;br /&gt;
* $entry-&amp;gt;id must be the unique identifier for the current object. If we are creating a new entry, it will be null, but in all cases it must be defined.&lt;br /&gt;
* These two functions (file_prepare_standard_editor and file_prepare_standard_filemanager) are shortcuts functions that take care of some of the tedious setting up for you, but they make a couple of assumptions:&lt;br /&gt;
*# You &#039;&#039;&#039;must&#039;&#039;&#039; name the form element as {element}_editor or {element}_filemanager (see next section)&lt;br /&gt;
*# You &#039;&#039;&#039;must&#039;&#039;&#039; have at least the following fields in the database: {element} and {element}summary, as described earlier in this documentation&lt;br /&gt;
&lt;br /&gt;
We can now look at the upgrades needed in the form definition file.&lt;br /&gt;
&lt;br /&gt;
=== Form definition ===&lt;br /&gt;
Previous code in mod/glossary/edit_form.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;htmleditor&#039;, &#039;definition&#039;, get_string(&#039;definition&#039;, &#039;glossary&#039;), array(&#039;rows&#039;=&amp;gt;20));&lt;br /&gt;
$mform-&amp;gt;setType(&#039;definition&#039;, PARAM_RAW);&lt;br /&gt;
$mform-&amp;gt;addRule(&#039;definition&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
$mform-&amp;gt;setHelpButton(&#039;definition&#039;, array(&#039;writing&#039;, &#039;richtext&#039;), false, &#039;editorhelpbutton&#039;);&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;format&#039;);&lt;br /&gt;
// a bit further...&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;setHelpButton(&#039;attachment&#039;, array(&#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;glossary&#039;), &#039;glossary&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
New code:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$definitionoptions = $this-&amp;gt;_customdata[&#039;definitionoptions&#039;];&lt;br /&gt;
$attachmentoptions = $this-&amp;gt;_customdata[&#039;attachmentoptions&#039;];&lt;br /&gt;
// a bit further...&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;editor&#039;, &#039;definition_editor&#039;, get_string(&#039;definition&#039;, &#039;glossary&#039;), null, $definitionoptions);&lt;br /&gt;
$mform-&amp;gt;setType(&#039;definition_editor&#039;, PARAM_RAW);&lt;br /&gt;
$mform-&amp;gt;addRule(&#039;definition_editor&#039;, get_string(&#039;required&#039;), &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
// a bit further...&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;filemanager&#039;, &#039;attachment_filemanager&#039;, get_string(&#039;attachment&#039;, &#039;glossary&#039;), null, $attachmentoptions);&lt;br /&gt;
$mform-&amp;gt;setHelpButton(&#039;attachment_filemanager&#039;, array(&#039;attachment2&#039;, get_string(&#039;attachment&#039;, &#039;glossary&#039;), &#039;glossary&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the following:&lt;br /&gt;
* The format element and the help button are no longer required for the HTML editor element&lt;br /&gt;
* The name of the form element needs to be changed by adding &#039;_editor&#039; or &#039;_manager&#039; to the original name. This is a naming convention that is used by a couple of functions we will look at shortly&lt;br /&gt;
&lt;br /&gt;
=== Handling submitted data ===&lt;br /&gt;
The final step is to handle the submitted data properly, i.e. retrieve the files and save them to disk, associating them with the record we have just created (a glossary entry in our example). This happens in edit.php:&lt;br /&gt;
&lt;br /&gt;
Previous code in edit.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Section that updates an entry:&lt;br /&gt;
$todb-&amp;gt;id = $e;&lt;br /&gt;
$dir = glossary_file_area_name($todb);&lt;br /&gt;
if ($mform-&amp;gt;save_files($dir) and $newfilename = $mform-&amp;gt;get_new_filename()) {&lt;br /&gt;
    $todb-&amp;gt;attachment = $newfilename;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Section that adds an entry:&lt;br /&gt;
if ($todb-&amp;gt;id = insert_record(&amp;quot;glossary_entries&amp;quot;, $todb)) {&lt;br /&gt;
    $e = $todb-&amp;gt;id;&lt;br /&gt;
    $dir = glossary_file_area_name($todb);&lt;br /&gt;
    if ($mform-&amp;gt;save_files($dir) and $newfilename = $mform-&amp;gt;get_new_filename()) {&lt;br /&gt;
        set_field(&amp;quot;glossary_entries&amp;quot;, &amp;quot;attachment&amp;quot;, $newfilename, &amp;quot;id&amp;quot;, $todb-&amp;gt;id);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
New code:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// $todb was renamed to $entry, and the code was refactored &lt;br /&gt;
// so that the file-handling code is only used once for either an add or an update action.&lt;br /&gt;
// If an entry is being added, $DB-&amp;gt;insert() has already been called, so we have a valid $entry-&amp;gt;id&lt;br /&gt;
$entry = file_postupdate_standard_editor($entry, &#039;definition&#039;, $definitionoptions, $context, &#039;mod_glossary&#039;, &#039;entry&#039;, $entry-&amp;gt;id);&lt;br /&gt;
$entry = file_postupdate_standard_filemanager($entry, &#039;attachment&#039;, $attachmentoptions, $context, &#039;mod_glossary&#039;, &#039;attachment&#039;, $entry-&amp;gt;id);&lt;br /&gt;
// store the updated value values&lt;br /&gt;
$DB-&amp;gt;update_record(&#039;glossary_entries&#039;, $entry);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Things to note:&lt;br /&gt;
* If you are adding a new record, you will still need to call update_record after calling the file_postupdate* functions&lt;br /&gt;
&lt;br /&gt;
=== Gotchas ===&lt;br /&gt;
A few things to keep in mind:&lt;br /&gt;
* Make sure that you instantiate the moodle form before any call to $OUTPUT-&amp;gt;header()&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[File API]]&lt;br /&gt;
* [[Using the file API]]&lt;br /&gt;
* [[Repository API]]&lt;br /&gt;
* [[Portfolio API]]&lt;br /&gt;
* MDL-14589 - File API Meta issue&lt;br /&gt;
&lt;br /&gt;
[[Category:Files]]&lt;br /&gt;
[[Category:Repositories]]&lt;/div&gt;</summary>
		<author><name>Sunner</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File_API&amp;diff=11543</id>
		<title>File API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File_API&amp;diff=11543"/>
		<updated>2011-04-05T04:35:03Z</updated>

		<summary type="html">&lt;p&gt;Sunner: /* File areas */ Fix a typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.0}}&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]]. 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 upgrade pre-2.0 code to using the file API, 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, for example &#039;course&#039;, &#039;mod_forum&#039;, &#039;mod_glossary&#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 file_rewrite_pluginfile_urls 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;
==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;
        $params = base64_encode(serialize($level-&amp;gt;get_params()));&lt;br /&gt;
        $path[] = array(&#039;name&#039;=&amp;gt;$level-&amp;gt;get_visible_name(), &#039;path&#039;=&amp;gt;$params);&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;
===Create a copy of stored file===&lt;br /&gt;
 TODO: this example is bogus, nobody should ever write code like this (skodak)&lt;br /&gt;
If you need to create a copy of stored file (actually, it add a new record in database):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$context  = get_context_instance_by_id($contextid);&lt;br /&gt;
$file_info = $browser-&amp;gt;get_file_info($context, $component, $filearea, $fileitemid, $filepath, $filename);&lt;br /&gt;
// copy this file to draft area&lt;br /&gt;
$file_info-&amp;gt;copy_to_storage($user_context-&amp;gt;id, &#039;user&#039;, &#039;draft&#039;, $newitemid, &#039;/&#039;, $title);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code is intended for user-interface behaviour which respects the current user&#039;s permissions. If you need to write code which copies files at the back-end in areas which are not directly editable by users (for example, when copying a glossary entry to another glossary, and you want to copy its attachments), you do not need to use the user-level $browser at all. All operations are carried out with the file_storage object (usually $fs). The method to use is create_file_from_storedfile.&lt;br /&gt;
&lt;br /&gt;
For example, the glossary stores per-entry files in two areas (&#039;mod_glossary&#039;, &#039;attachment&#039; which stores attachments and &#039;mod_glossary&#039;, &#039;entry&#039; which stores files directly related to the HTML definition, such as embedded images). The following code copies all the files relating to a specific glossary entry from one such area to a different glossary item in a different glossary. Note that it changes the context ID and item ID of each file to represent the new context (for the different glossary module) and the new glossary entry (a new row was added to glossary_entries).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$fs = get_file_storage();&lt;br /&gt;
if ($files = $fs-&amp;gt;get_area_files($oldcontextid, &#039;mod_glossary&#039;, &#039;attachment&#039;, $oldentryid)) {&lt;br /&gt;
    foreach ($files as $file) {&lt;br /&gt;
        $fs-&amp;gt;create_file_from_storedfile(array(&lt;br /&gt;
                &#039;contextid&#039; =&amp;gt; $newcontextid,&lt;br /&gt;
                &#039;itemid&#039; =&amp;gt; $newentryid), $file);&lt;br /&gt;
    }&lt;br /&gt;
}&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;
=== 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-&amp;gt;contextid, $fileinfo-&amp;gt;component, $fileinfo-&amp;gt;filearea, &lt;br /&gt;
        $fileinfo-&amp;gt;itemid, $fileinfo-&amp;gt;filepath, $fileinfo-&amp;gt;filename);&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;filearea&#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-&amp;gt;contextid, $fileinfo-&amp;gt;component, $fileinfo-&amp;gt;filearea, &lt;br /&gt;
        $fileinfo-&amp;gt;itemid, $fileinfo-&amp;gt;filepath, $fileinfo-&amp;gt;filename);&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;
* [[File API]] how the File API works internally.&lt;br /&gt;
* [[Roadmap|Moodle 2.0 roadmap]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Files]]&lt;/div&gt;</summary>
		<author><name>Sunner</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File_API&amp;diff=11542</id>
		<title>File API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File_API&amp;diff=11542"/>
		<updated>2011-04-05T04:33:59Z</updated>

		<summary type="html">&lt;p&gt;Sunner: /* File areas */ Remove a duplicated &amp;#039;is&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.0}}&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]]. 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 upgrade pre-2.0 code to using the file API, 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, for example &#039;course&#039;, &#039;mod_forum&#039;, &#039;mod_glossary&#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 onnly 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 file_rewrite_pluginfile_urls 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;
==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;
        $params = base64_encode(serialize($level-&amp;gt;get_params()));&lt;br /&gt;
        $path[] = array(&#039;name&#039;=&amp;gt;$level-&amp;gt;get_visible_name(), &#039;path&#039;=&amp;gt;$params);&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;
===Create a copy of stored file===&lt;br /&gt;
 TODO: this example is bogus, nobody should ever write code like this (skodak)&lt;br /&gt;
If you need to create a copy of stored file (actually, it add a new record in database):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$context  = get_context_instance_by_id($contextid);&lt;br /&gt;
$file_info = $browser-&amp;gt;get_file_info($context, $component, $filearea, $fileitemid, $filepath, $filename);&lt;br /&gt;
// copy this file to draft area&lt;br /&gt;
$file_info-&amp;gt;copy_to_storage($user_context-&amp;gt;id, &#039;user&#039;, &#039;draft&#039;, $newitemid, &#039;/&#039;, $title);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code is intended for user-interface behaviour which respects the current user&#039;s permissions. If you need to write code which copies files at the back-end in areas which are not directly editable by users (for example, when copying a glossary entry to another glossary, and you want to copy its attachments), you do not need to use the user-level $browser at all. All operations are carried out with the file_storage object (usually $fs). The method to use is create_file_from_storedfile.&lt;br /&gt;
&lt;br /&gt;
For example, the glossary stores per-entry files in two areas (&#039;mod_glossary&#039;, &#039;attachment&#039; which stores attachments and &#039;mod_glossary&#039;, &#039;entry&#039; which stores files directly related to the HTML definition, such as embedded images). The following code copies all the files relating to a specific glossary entry from one such area to a different glossary item in a different glossary. Note that it changes the context ID and item ID of each file to represent the new context (for the different glossary module) and the new glossary entry (a new row was added to glossary_entries).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$fs = get_file_storage();&lt;br /&gt;
if ($files = $fs-&amp;gt;get_area_files($oldcontextid, &#039;mod_glossary&#039;, &#039;attachment&#039;, $oldentryid)) {&lt;br /&gt;
    foreach ($files as $file) {&lt;br /&gt;
        $fs-&amp;gt;create_file_from_storedfile(array(&lt;br /&gt;
                &#039;contextid&#039; =&amp;gt; $newcontextid,&lt;br /&gt;
                &#039;itemid&#039; =&amp;gt; $newentryid), $file);&lt;br /&gt;
    }&lt;br /&gt;
}&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;
=== 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-&amp;gt;contextid, $fileinfo-&amp;gt;component, $fileinfo-&amp;gt;filearea, &lt;br /&gt;
        $fileinfo-&amp;gt;itemid, $fileinfo-&amp;gt;filepath, $fileinfo-&amp;gt;filename);&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;filearea&#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-&amp;gt;contextid, $fileinfo-&amp;gt;component, $fileinfo-&amp;gt;filearea, &lt;br /&gt;
        $fileinfo-&amp;gt;itemid, $fileinfo-&amp;gt;filepath, $fileinfo-&amp;gt;filename);&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;
* [[File API]] how the File API works internally.&lt;br /&gt;
* [[Roadmap|Moodle 2.0 roadmap]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Files]]&lt;/div&gt;</summary>
		<author><name>Sunner</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=DB_layer_2.0_migration_docs&amp;diff=9117</id>
		<title>DB layer 2.0 migration docs</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=DB_layer_2.0_migration_docs&amp;diff=9117"/>
		<updated>2010-08-11T08:02:20Z</updated>

		<summary type="html">&lt;p&gt;Sunner: /* The golden changes */  fix a typo (actually two)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Development:dmllib 2.0}}{{Moodle_2.0}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Much of the following documentation will not make much sense unless you first read [[XMLDB_Documentation|the XMLDB documentation]]. Please read it first if you would like to join the effort to convert Moodle&#039;s code to the new dmllib.&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s recommended to read the whole [[wikipedia:Data_Definition_Language|DDL]] and [[wikipedia:Data_Manipulation_Language|DML]] documentation before start with the migration. That will allow you to have some initial knowledge about the new architecture.&lt;br /&gt;
&lt;br /&gt;
This article defines all the changes that need to be performed in Moodle 1.9 code in order to make it run properly under new Moodle 2.0 DB layer. Changes below are grouped into 2 main blocks ([[XMLDB_Documentation|xmldb]] and [[wikipedia:Data_Manipulation_Language|dml]]) to have them organised. Additional minor changes may be required in the [[wikipedia:Data_Definition_Language|ddl]] code, but won&#039;t be documented here.&lt;br /&gt;
&lt;br /&gt;
Although the order of changes showed in this page isn&#039;t mandatory at all, it can be interesting to follow it in the migration progress to be able to understand and learn a bit more about all them. That way, you&#039;ll end up knowing not only what to change but how and why those changes are required.&lt;br /&gt;
&lt;br /&gt;
Each change will be as simple as possible, representing one easy rule to follow to adapt the code. When anything become too complex to be explained as one simple rule, it will contain one link to the [[dmllib_2.0_examples|examples page]].&lt;br /&gt;
&lt;br /&gt;
For any problem in the migration of code, it&#039;s recommended to use the [http://moodle.org/mod/forum/view.php?id=45 Databases forum] at [http://moodle.org moodle.org]. Also if you find any bug in the process, please report it in the [http://tracker.moodle.org/browse/MDL-14679 Moodle Tracker], that way developers will be able to fix it ASAP.&lt;br /&gt;
&lt;br /&gt;
The Glossary module was used as the basis for many of the examples below.&lt;br /&gt;
&lt;br /&gt;
And finally, feel free to complete/fix the list below with the changes you find in the progress of migration, that will certainly help many developers. Thanks!&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== check_db_syntax: One helper script ==&lt;br /&gt;
&lt;br /&gt;
Before start migrating your code to Moodle 2.0, it&#039;s recommended to install and run the [http://cvs.moodle.org/contrib/tools/check_db_syntax/ check_db_syntax.php] script. Simply copy it to the main folder of your plugin and execute it (from command line or via web). I&#039;ll show you the list of old DB usages that need to be transformed following the information below in this article.&lt;br /&gt;
&lt;br /&gt;
If you think that something is missing in the script or have any idea to improve it, feel free to do that yourself, commenting about it in MDL-15237. Thanks!&lt;br /&gt;
&lt;br /&gt;
Also, this (perl-compatible - works in Eclipse, hopefully elsewhere) regex:&lt;br /&gt;
&lt;br /&gt;
 (?&amp;lt;!-&amp;gt;)(?&amp;lt;!function )(?&amp;lt;!\$)\b(?:(?:count|delete|get|insert|update)_record(?!s_csv)|[gs]et_field|record_exists|execute_sql)|\$CFG-&amp;gt;prefix|rs_(?:fetch|close)|(add|strip)slashes(?!_js)&lt;br /&gt;
&lt;br /&gt;
Will find most of the things in your code that need attention, with few false positives.&lt;br /&gt;
&lt;br /&gt;
== XMLDB/DDL changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
&lt;br /&gt;
* When changing DB structures it&#039;s highly recommended to use the [[XMLDB editor|XMLDB Editor]] (Admin-&amp;gt;Development-&amp;gt;XMLDB Editor). It is a safe way to edit install.xml files and to get correct PHP code to be used in upgrade.php scripts.&lt;br /&gt;
* If you have some doubts about the list of changes below, it&#039;s highly recommended to take a look at some code in core modules, blocks... whatever you need. They are a good reference.&lt;br /&gt;
* The most noticeable change (from a migration perspective) in the DDL stuff is that, starting with Moodle 2.0, we have decided to &#039;&#039;&#039;drop support for enum (check constraint) fields completely&#039;&#039;&#039;. See MDL-18577 and [http://moodle.org/mod/forum/discuss.php?d=118852 this discussion]. That implies changes in different parts of the DB stuff (xml files, function parameters, dropping existing enums...) and are commented with more detail below.&lt;br /&gt;
&lt;br /&gt;
=== The changes ===&lt;br /&gt;
&lt;br /&gt;
* No changes are required in install.xml files at all (that&#039;s good news!). Although you must know these:&lt;br /&gt;
** The &#039;&#039;&#039;ENUM&#039;&#039;&#039; and &#039;&#039;&#039;ENUMVALUES&#039;&#039;&#039; attributes present in your install.xml files will be completely ignored both by the DLL generation stuff and by the XMLDB Editor.&lt;br /&gt;
** In Moodle 2.1, those attributes (&#039;&#039;&#039;ENUM&#039;&#039;&#039; and &#039;&#039;&#039;ENUMVALUES&#039;&#039;&#039;) will be 100% forbidden, so it&#039;s highly recommended to erase them since now (Moodle 2.0).&lt;br /&gt;
** The XMLDB Editor will detect them when loading any install.xml file and will suggest you to fix that easily with one 1-click® option.&lt;br /&gt;
** No matter if you have fixed that with the 1-click® option when loading the files... the [[XMLDB editor|XMLDB Editor]] will save any edited install.xml files without those attributes.&lt;br /&gt;
** If your Moodle 1.9.x code &#039;&#039;&#039;has some enum defined in the database&#039;&#039;&#039;, you will need to create one upgrade block (in db/upgrade.php) to drop it (the enum, not the field! ;-) as part of the migration from Moodle 1.9 to 2.0 by using the new &#039;&#039;&#039;[[DB layer 2.0 examples#Dropping one enum from one field|drop_enum_from_field()]]&#039;&#039;&#039; method.&lt;br /&gt;
** Of course, if you don&#039;t use/like the XMLDB Editor, you can erase them manually with something like this:&lt;br /&gt;
 perl -p -e &#039;s/ENUM(VALUES)?=&amp;quot;.*?&amp;quot; //g&#039; &amp;lt; install.xml &amp;gt; install.xml.new&lt;br /&gt;
&lt;br /&gt;
* All upgrade.php scripts, within the main xxxx_upgrade function must have &#039;&#039;&#039;$DB&#039;&#039;&#039; (uppercase) in the globals declaration (along with others if needed). Example (from glossary module):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_glossary_upgrade($oldversion=0) {&lt;br /&gt;
    &lt;br /&gt;
    global $CFG, $THEME, $DB;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All upgrade.php scripts, must NOT have &#039;&#039;&#039;$db&#039;&#039;&#039; (lowercase) in the globals declaration. Delete it if present.&lt;br /&gt;
* After the global declaration in the points above, this line must be present (we&#039;ll need it later):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$dbman = $DB-&amp;gt;get_manager(); /// loads ddl manager and xmldb classes&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* All &#039;&#039;&#039;XMLDBTable&#039;&#039;&#039; instances in your upgrade code must be replaced by &#039;&#039;&#039;xmldb_table&#039;&#039;&#039; (no change in parameters)&lt;br /&gt;
* All &#039;&#039;&#039;XMLDBField&#039;&#039;&#039; instances in your upgrade code must be replaced by &#039;&#039;&#039;xmldb_field&#039;&#039;&#039; (with change in params, both enum and enumvalues are out from function declaration!)&lt;br /&gt;
* All &#039;&#039;&#039;XMLDBIndex&#039;&#039;&#039; instances in your upgrade code must be replaced by &#039;&#039;&#039;xmldb_index&#039;&#039;&#039; (no change in parameters)&lt;br /&gt;
* All &#039;&#039;&#039;XMLDBKey&#039;&#039;&#039; instances in your upgrade code must be replaced by &#039;&#039;&#039;xmldb_key&#039;&#039;&#039; (no change in parameters)&lt;br /&gt;
* All the &#039;&#039;&#039;addFieldInfo()&#039;&#039;&#039; methods must be replaced by &#039;&#039;&#039;add_field()&#039;&#039;&#039; (with change in params, both enum and enumvalues are out from function declaration!)&lt;br /&gt;
* All the &#039;&#039;&#039;addIndexInfo()&#039;&#039;&#039; methods must be replaced by &#039;&#039;&#039;add_index()&#039;&#039;&#039; (no change in parameters)&lt;br /&gt;
* All the &#039;&#039;&#039;addKeyInfo()&#039;&#039;&#039; methods must be replaced by &#039;&#039;&#039;add_key()&#039;&#039;&#039; (no change in parameters)&lt;br /&gt;
* All the &#039;&#039;&#039;setAttributes()&#039;&#039;&#039; methods must be replaced by &#039;&#039;&#039;set_attributes()&#039;&#039;&#039; (with change in params, both enum and enumvalues are out from function declaration!)&lt;br /&gt;
* All the DDL functions used in upgrade code, must be transformed as detailed below (it&#039;s only about to add &#039;&#039;&#039;&amp;quot;$dbman-&amp;gt;&amp;quot;&#039;&#039;&#039; - without the quotes - before each function call). No changes in parameters are required:&lt;br /&gt;
** table_exists ==&amp;gt; $dbman-&amp;gt;table_exists&lt;br /&gt;
** field_exists ==&amp;gt; $dbman-&amp;gt;field_exists&lt;br /&gt;
** index_exists ==&amp;gt; $dbman-&amp;gt;index_exists&lt;br /&gt;
** find_index_name ==&amp;gt; $dbman-&amp;gt;find_index_name&lt;br /&gt;
** find_check_constraint_name ==&amp;gt; $dbman-&amp;gt;find_check_constraint_name (&#039;&#039;&#039;DEPRECATED in 2.0. OUT in 2.1&#039;&#039;&#039;)&lt;br /&gt;
** check_constraint_exists ==&amp;gt; $dbman-&amp;gt;check_constraint_exists (&#039;&#039;&#039;DEPRECATED in 2.0. OUT in 2.1&#039;&#039;&#039;)&lt;br /&gt;
** find_sequence_name ==&amp;gt; &#039;&#039;&#039;OUT in 2.0&#039;&#039;&#039;, see MDL-20349&lt;br /&gt;
** create_table ==&amp;gt; $dbman-&amp;gt;create_table&lt;br /&gt;
** drop_table ==&amp;gt; $dbman-&amp;gt;drop_table&lt;br /&gt;
** rename_table ==&amp;gt; $dbman-&amp;gt;rename_table&lt;br /&gt;
** add_field ==&amp;gt; $dbman-&amp;gt;add_field&lt;br /&gt;
** drop_field ==&amp;gt; $dbman-&amp;gt;drop field&lt;br /&gt;
** rename_field ==&amp;gt; $dbman-&amp;gt;rename_field&lt;br /&gt;
** change_field_type ==&amp;gt; $dbman-&amp;gt;change_field_type&lt;br /&gt;
** change_field_precision =&amp;gt; $dbman-&amp;gt;change_field_precision&lt;br /&gt;
** change_field_unsigned ==&amp;gt; $dbman-&amp;gt;change_field_unsigned&lt;br /&gt;
** change_field_notnull ==&amp;gt; $dbman-&amp;gt;change_field_notnull&lt;br /&gt;
** change_field_enum ==&amp;gt; $dbman-&amp;gt;change_field_enum (&#039;&#039;&#039;OUT in 2.0&#039;&#039;&#039;, see &#039;&#039;&#039;[[DB layer 2.0 examples#Dropping one enum from one field|drop_enum_from_field()]]&#039;&#039;&#039; to get rid of remaining ENUMs in code).&lt;br /&gt;
** change_field_default ==&amp;gt; $dbman-&amp;gt;change_field_default&lt;br /&gt;
** add_key ==&amp;gt; $dbman-&amp;gt;add_key&lt;br /&gt;
** drop_key ==&amp;gt; $dbman-&amp;gt;drop_key&lt;br /&gt;
** add_index ==&amp;gt; $dbman-&amp;gt;add_index&lt;br /&gt;
** drop_index ==&amp;gt; $dbman-&amp;gt;drop_index&lt;br /&gt;
* Finally, and not less important, your code (module, block... plugin) must guarantee that it can be upgraded &#039;&#039;&#039;ONLY&#039;&#039;&#039; from Moodle 1.9, so any previous upgrade code can be safely deleted. &#039;&#039;&#039;Moodle 2.0 requires Moodle 1.9&#039;&#039;&#039; to be upgraded, so everybody will run the 1.9 =&amp;gt; 2.0 upgrade (with other paths like 1.8 =&amp;gt; 2.0 not being possible). One good time to clean-up a bit your upgrade code ;-). Don&#039;t forget to take a look to the [[XMLDB editor|XMLDB Editor]] and to core modules to see how [http://cvs.moodle.org/moodle/lib/db/upgrade.php?view=markup upgrade.php] files look like in Moodle 2.0.&lt;br /&gt;
&lt;br /&gt;
== DML changes ==&lt;br /&gt;
&lt;br /&gt;
=== Some comments ===&lt;br /&gt;
* The ENTIRE CODEBASE requires an update of ALL database query function calls. Expect most moodle files to be affected by this change.&lt;br /&gt;
&lt;br /&gt;
* This is the more complex part to migrate to have the code working under Moodle 2.0, not because of the complexity of the changes themselves (90% of them will be really easy), but because you&#039;ll need to triple-check everything works as expected after changes.&lt;br /&gt;
&lt;br /&gt;
* Along the changes below, you&#039;ll find links to some examples that will try to make things easier. Anyway, if you are blocked at any point, please ask in forums or tracker (see links at the beginning of the page). Sure it has a good enough solution.&lt;br /&gt;
&lt;br /&gt;
* Once more it&#039;s highly recommended to take a look to Moodle core code, searching for similar examples. Of course, new meaningful examples are welcome, and also any clarification in the list of changes below. Feel free to do it, this is a wiki!&lt;br /&gt;
&lt;br /&gt;
* Finally, one more explanation: The changes below have been split into three sections. First one, (called &#039;&#039;&#039;&amp;quot;The golden changes&amp;quot;&#039;&#039;&#039;) are modifications that must be applied to ALL the transformations defined in the second section (&#039;&#039;&#039;&amp;quot;The iron changes&amp;quot;&#039;&#039;&#039;). Sure you&#039;ll understand that after reading them (it&#039;s basically a matter of not repeating the golden ones within each iron one, just imagine they are everywhere). Finally other changes details can be found in the &#039;&#039;&#039;&amp;quot;The tin changes&amp;quot;&#039;&#039;&#039; section.&lt;br /&gt;
&lt;br /&gt;
=== The golden changes ===&lt;br /&gt;
&#039;&#039;PLEASE read the API before going crazy with search &amp;amp; replace&#039;&#039;! You can find all the new methods in lib/dml/moodle_database.php. This is essential because some method signatures have changed (params are different), and some method names have even changed (execute_sql() is now execute()).&lt;br /&gt;
&lt;br /&gt;
Each of the golden changes below is given one short name (G1, G2, G3...) for further reference in the rest of the documentation. Let&#039;s go:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Wherever old functions are used (get_record*, get_field*, set_field, insert_record, update_record, count_records*, delete_records, record_exists), the global $DB must be used as the object on which these functions are called (e.g. get_record_select() becomes $DB-&amp;gt;get_record_select()).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
get_record_select($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$sql = &amp;quot;WHERE id = 1&amp;quot;;&lt;br /&gt;
$DB-&amp;gt;get_record_select($sql);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: for some functions, the $params array is not the second function parameter. For example, set_field:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Old syntax&lt;br /&gt;
set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, &#039;id&#039;, 1);&lt;br /&gt;
  &lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$DB-&amp;gt;set_field(&#039;user&#039;, &#039;firstname&#039;, &#039;Peter&#039;, array(&#039;id&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g2&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All uses of addslashes() &#039;&#039;&#039;must be removed&#039;&#039;&#039;. They are no longer needed&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g3&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G3&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: All the functions that used to accept a list of string params in the form &amp;quot;param1, value1, param2, value2&amp;quot; now need to be given an array of key=&amp;gt;value pairs as a replacement for these params. Other params remain as before. Check the new API for any exceptions.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$user = get_record(&amp;quot;user&amp;quot;, &amp;quot;firstname&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot;, &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// New syntax:&lt;br /&gt;
global $DB;&lt;br /&gt;
$conditions = array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;);&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, $conditions);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
::Note: The example above has been written out in full for clarity. You can use the array() directly within the function call, without using a temporary variable, if you prefer:&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $DB;&lt;br /&gt;
$user = $DB-&amp;gt;get_record(&amp;quot;user&amp;quot;, array(&amp;quot;firstname&amp;quot; =&amp;gt; &amp;quot;Peter&amp;quot;, &amp;quot;lastname&amp;quot; =&amp;gt; &amp;quot;Cantrophus&amp;quot;) );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g4&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G4&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: rs_fetch_next_record($rs) is deprecated, in favour of the simple foreach($rs as $var). Calls to rs_close() must be replaced by $rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
while($result = rs_fetch_next_record($rs)) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
rs_close();&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
foreach ($rs as $result) {&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
$rs-&amp;gt;close();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g5&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G5&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Placeholders must be used for table names. Instead of {$CFG-&amp;gt;prefix}tablename, use {tablename}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {$CFG-&amp;gt;prefix}user&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM {user}&amp;quot;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g6&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G6&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: When PHP variables are used in SQL queries, they must be replaced by parameters. You have the choice between two approaches: ordered parameters, or named parameters.&lt;br /&gt;
** Ordered parameters use a simple array of values, which are given to the DML function as $params. The values in the SQL code are simply question marks (?) replacing the values. They are replaced by the DML code one by one, substituting each question mark (?) with the next value in the $params array.&lt;br /&gt;
** Named parameters use an associative array of name =&amp;gt; value pairs as the $params array. The values in the SQL code are replaced with a colon (:) followed by the key associated with the value, in the $params array. Note that named params &#039;&#039;&#039;must be unique&#039;&#039;&#039;, no matter if the value passed is the same.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {$CFG-&amp;gt;prefix}user WHERE firstname = &#039;Peter&#039; AND lastname = &#039;Cantrophus&#039;&amp;quot;;&lt;br /&gt;
$user = get_record_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// New syntax: ordered params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;Peter&#039;, &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = ? AND lastname = ?&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&lt;br /&gt;
// New syntax: named params&lt;br /&gt;
global $DB;&lt;br /&gt;
$params = array(&#039;firstname&#039; =&amp;gt; &#039;Peter&#039;, &#039;lastname&#039; =&amp;gt; &#039;Cantrophus&#039;);&lt;br /&gt;
$sql = &amp;quot;SELECT id, firstname FROM {user} WHERE firstname = :firstname AND lastname = :lastname&amp;quot;;&lt;br /&gt;
$user = $DB-&amp;gt;get_record_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To obtain a value for the LIKE operator, include any % signs into the parameter string. For example, code that was previously &amp;lt;tt&amp;gt;&amp;quot;LIKE &#039;$value%&#039;&amp;quot;&amp;lt;/tt&amp;gt; becomes &amp;lt;tt&amp;gt;&amp;quot;LIKE ?&amp;quot;&amp;lt;/tt&amp;gt; with the parameter &amp;lt;tt&amp;gt;$value.&#039;%&#039;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g7&amp;quot;&amp;gt;&amp;lt;b&amp;gt;G7&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Replacement of the IN(...) syntax: We no longer hard-code this in our SQL queries, we use a function which determines whether the IN() syntax is needed, or, if there is only one value to compare, the equal (=) sign can be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax:&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
$gis = implode(&#039;,&#039;, $depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
          FROM {$CFG-&amp;gt;prefix}grade_items&lt;br /&gt;
         WHERE id IN ($gis)&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql);&lt;br /&gt;
  &lt;br /&gt;
// new syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$depends_on = array(1, 43, 553);&lt;br /&gt;
list($usql, $params) = $DB-&amp;gt;get_in_or_equal($depends_on);&lt;br /&gt;
$sql = &amp;quot;SELECT *&lt;br /&gt;
          FROM {grade_items}&lt;br /&gt;
         WHERE id $usql&amp;quot;;&lt;br /&gt;
$items = $DB-&amp;gt;get_records_sql($sql, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; to combine the last two, do the G7 IN SQL stuff first to generate the params array, then do something like&lt;br /&gt;
  $param[&#039;firstname&#039;] = &#039;peter&#039;;&lt;br /&gt;
to add the stuff for G6&lt;br /&gt;
&lt;br /&gt;
=== The iron changes ===&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;span id=&amp;quot;I1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;I1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally the &#039;&#039;&#039;sql_substr()&#039;&#039;&#039; function was used without parameters and it returned only the name of the &amp;quot;substring&amp;quot; function to be used under each DB. In Moodle 2.0 and upwards, it has 3 parameters (2 being mandatory) and it returns the complete SQL text to be used when handling substrings. Note that positions in this function are 1-based (first char has index 1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$records = get_records_sql(&amp;quot;SELECT &amp;quot; . sql_substr() . &amp;quot;(firstname, 1, 20)&amp;quot; . &amp;quot; FROM ... ...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
$records = $DB-&amp;gt;get_records_sql(&amp;quot;SELECT &amp;quot; . $DB-&amp;gt;sql_substr(&#039;firstname&#039;, 1, 20) . &amp;quot; FROM ... ...&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The tin changes ===&lt;br /&gt;
List of minor changes&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T1&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally get_records() and similar functions were returning false if no records found. All these methods are now always returning arrays, empty array in case of no records found. Please note that get_record() still returns false if specified record not found.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
if (!$posts = get_records(&#039;forum_posts&#039;, &#039;parent&#039;, 666)) {&lt;br /&gt;
    $posts = array()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$posts = $DB-&amp;gt;get_records(&#039;forum_posts&#039;, array(&#039;parent&#039;=&amp;gt;666));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span id=&amp;quot;g1&amp;quot;&amp;gt;&amp;lt;b&amp;gt;T2&amp;lt;/b&amp;gt;&amp;lt;/span&amp;gt;: Originally DML functions were returning &#039;&#039;false&#039;&#039; if error occurred - &#039;&#039;dml_exception&#039;&#039; is thrown now instead.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
// Old syntax&lt;br /&gt;
$record = new object();&lt;br /&gt;
$record-&amp;gt;course = 5;&lt;br /&gt;
if (!$id = insert_record(&#039;sometable&#039;, $record)) {&lt;br /&gt;
   error(&#039;can not insert new record&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// New syntax&lt;br /&gt;
global $DB;&lt;br /&gt;
$record = new object();&lt;br /&gt;
$record-&amp;gt;course = 5;&lt;br /&gt;
$id = $DB-&amp;gt;insert_record(&#039;sometable&#039;, $record);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[XMLDB Documentation|XMLDB Documentation]]: where both xmldb and ddl stuff is explained.&lt;br /&gt;
* [[DDL functions|DDL functions]] - Documentation for all the Data Definition Language (DDL) functions available inside Moodle.&lt;br /&gt;
* [[DML functions|DML functions]] - Documentation for all the Data Manipulation Language (DML) functions available inside Moodle.&lt;br /&gt;
* [[DDL exceptions|DDL exceptions]] - DDL exceptions information.&lt;br /&gt;
* [[DML exceptions|DML exceptions]] - DML exceptions information.&lt;/div&gt;</summary>
		<author><name>Sunner</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Developer_documentation&amp;diff=481</id>
		<title>Developer documentation</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Developer_documentation&amp;diff=481"/>
		<updated>2006-08-30T05:39:07Z</updated>

		<summary type="html">&lt;p&gt;Sunner: /* See also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Guidelines==&lt;br /&gt;
The following guidelines are crucial reading for anyone wanting to contribute to the Moodle code base:&lt;br /&gt;
*[[Coding|Coding guidelines]] have to be followed by all Moodle developers&lt;br /&gt;
*[[Moodle architecture]] spells out the basic design goals behind Moodle&lt;br /&gt;
*[[Interface guidelines]] aim to provide a common feel to the Moodle user interface&lt;br /&gt;
*[[CVS (developer)|Moodle CVS for developers]] explains how to work with the Moodle code in CVS&lt;br /&gt;
*[[Unit tests]] explains how to run the unit tests, and how to write new test cases.&lt;br /&gt;
*[[Tracker]] explains the Moodle Tracker for keeping track of bugs, issues, feature requests etc &lt;br /&gt;
&lt;br /&gt;
== Resources and tools ==&lt;br /&gt;
&lt;br /&gt;
*[[Developer FAQ]] - frequently asked questions, especially useful for newcomers to Moodle&lt;br /&gt;
*[http://tracker.moodle.org/ Moodle bug tracker] - bug reports, feature requests and other tracked issues&lt;br /&gt;
*[http://moodle.org/mod/forum/view.php?id=55 General developer forum]&lt;br /&gt;
*[http://moodle.cvs.sourceforge.net/moodle/moodle/ CVS code] - browse the Moodle code via the web&lt;br /&gt;
*[http://moodle.org/xref/nav.html?index.html Cross reference] - phpxref output for browsing Moodle source code&lt;br /&gt;
*[http://moodle.sourceforge.net/dhawes-phpdoc/ Moodle PHP doc reference] - automatically generated documentation&lt;br /&gt;
*[http://moodle.org/course/view.php?id=5#4 Development news and discussion] section of Using Moodle course&lt;br /&gt;
*[http://developer.yahoo.com/yui YUI documentation] - YUI is the official AJAX library in moodle.&lt;br /&gt;
*[[Setting up Eclipse for Moodle development]] - Eclipse is a great editor to use for php development, if you can work out how to set it up.&lt;br /&gt;
*[[Unmerged files]] - changes on the stable branch in CVS that have not been merged to HEAD&lt;br /&gt;
&lt;br /&gt;
==How you can contribute==&lt;br /&gt;
&lt;br /&gt;
The M in Moodle stands for &#039;Modular&#039;. There are many different types of components that you can contribute that can be plugged into Moodle to provide additional functionality. When you have developed a new component please publish it in the [http://moodle.org/mod/data/view.php?id=6009 database of Moodle modules and plugins]. The following types of plugins currently exist (in alphabetical order):&lt;br /&gt;
*[[Modules (developer)|Activity modules]]&lt;br /&gt;
*[[Assignment types]]&lt;br /&gt;
*[[Authentication|Authentication methods]]&lt;br /&gt;
*[[Blocks Howto|Blocks]]&lt;br /&gt;
*[[Course formats]]&lt;br /&gt;
*[[Database fields (developer)|Database fields]]&lt;br /&gt;
*[[Database presets]]&lt;br /&gt;
*[[Enrolment plugins (developer)|Enrolment plugins]]&lt;br /&gt;
*[[Filters (developer)|Filters]]&lt;br /&gt;
*[[Question_engine]]&lt;br /&gt;
*[[Question import/export formats]]&lt;br /&gt;
*[[Question types|Question types teacher docs]]&lt;br /&gt;
*[[Question_engine#Question_types|Question types developper docs]]&lt;br /&gt;
*[[Quiz reports]]&lt;br /&gt;
*[[Resource types]]&lt;br /&gt;
*[[SSO plugins]]&lt;br /&gt;
&lt;br /&gt;
There are also ways you can contribute that don&#039;t involve PHP programming:&lt;br /&gt;
*[[Themes]]&lt;br /&gt;
*[[Translation]]&lt;br /&gt;
*[[Database Schemas|Database schemas]]&lt;br /&gt;
&lt;br /&gt;
You can also help a lot by&lt;br /&gt;
*[[Tests|Testing]]&lt;br /&gt;
*[[Bug tracker|Participating in the bug tracker]]&lt;br /&gt;
&lt;br /&gt;
==Plans for the future==&lt;br /&gt;
Ideas for and details of planned future features of Moodle are initially discussed on the forums in the [http://moodle.org/course/view.php?id=5 Using Moodle] course at moodle.org. That developer discussions are intermixed with user discussions in the same forums may seem strange at first but is one of the reasons for the success of Moodle. It is important that both end-users and developers discuss the future features together.&lt;br /&gt;
&lt;br /&gt;
Once ideas begin to crystalize on the forums they can be summarized in this wiki, either as part of the [[Roadmap]] or in the form of [[Developer notes]]. These pages then form the basis for further discussion in the forums.&lt;br /&gt;
*[[Roadmap]]&lt;br /&gt;
*[[Developer notes]]&lt;br /&gt;
*[[Student projects]]&lt;br /&gt;
*[[Developer conference|Developer conferences]]&lt;br /&gt;
&lt;br /&gt;
==Documentation for core components==&lt;br /&gt;
This section is for documentation of specific components of the existing core Moodle code. Discussion of components that are under discussion or in development can be found in the [[Developer notes]] or on the [[Roadmap]].&lt;br /&gt;
&lt;br /&gt;
*[[UTF-8 migration|Migration to UTF-8]]&lt;br /&gt;
*[[Question engine]]&lt;br /&gt;
*[[Quiz developer docs|Quiz module]]&lt;br /&gt;
*[[SCORM schema|SCORM module 1.5 schema]]&lt;br /&gt;
*[[Authentication API]]&lt;br /&gt;
*[[Stats package]]&lt;br /&gt;
*[[Email processing]]&lt;br /&gt;
*[[Cookieless Sessions]]&lt;br /&gt;
&lt;br /&gt;
==Documentation for contributed code==&lt;br /&gt;
Many Moodle users contribute code for the benefit of other Moodle users. This can take the form of new activity modules, blocks, themes, resource plug-ins, assignment plug-ins, question type plug-ins, question import/export formats, quiz report plug-ins, course formats, ... This code is initially posted on the forums in the [http://moodle.org/course/view.php?id=5 Using Moodle] course and then often go into the [http://cvs.sourceforge.net/viewcvs.py/moodle/contrib/ contrib area] of the Moodle [[CVS]] repository. When you have developed a new component please publish it in the [http://moodle.org/mod/data/view.php?id=6009 database of Moodle modules and plugins]. Developer documentation for these components should be listed here.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
*[http://security.moodle.org/ Moodle Security Centre]&lt;br /&gt;
*[http://moodle.com/partners/ Moodle Partners] - providers of custom Moodle development services&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[es:Documentación para Desarrolladores]]&lt;br /&gt;
[[fr:Documentation développeur]]&lt;br /&gt;
[[zh:开发者文档]]&lt;/div&gt;</summary>
		<author><name>Sunner</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User_talk:Helen_Foster&amp;diff=22997</id>
		<title>User talk:Helen Foster</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User_talk:Helen_Foster&amp;diff=22997"/>
		<updated>2006-07-22T13:31:57Z</updated>

		<summary type="html">&lt;p&gt;Sunner: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== More hierarchy ==&lt;br /&gt;
&lt;br /&gt;
Hi Helen, I think this wiki is very useful and I would like to thank you for the work you are putting into it. I like your navigation boxes on the module pages. I have a suggestion for extending these: I think it would be nice to have an extra link that allows one to go higher up in the hierarcy to [[Teacher_documentation]]. What do you think? --[[User:Delius|Delius]] 17:48, 26 January 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:Hi Gustav, thanks for your kind words. Your contributions to the documentation are most welcome. Please feel free to edit [[Template:Quizzes]] or any other template page. You may also wish to consider further use of category pages e.g. [[:Category:Teacher]] for navigation. -- [[User:Helen|Helen]] 18:26, 26 January 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Do you monitor every article and talk page? ==&lt;br /&gt;
&lt;br /&gt;
Helen, I have posted another question for you on [[Talk:mod/quiz/index]]. Do you get alerted to anything I put on any talk page or should I post on this page if I want you to see it? --[[User:Delius|Delius]] 18:01, 26 January 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:Hi Gustav, please note that I often check [[Special:Recentchanges|Recent changes]] or the rss feed. --[[User:Helen|Helen]] 18:26, 26 January 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
::Yes, the [[Special:Recentchanges|Recent changes]] page is very useful. You can tell that I have never used a wiki intensively before. Thanks for your tips. --[[User:Gustav|Gustav]] 18:35, 26 January 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:::Hey, let&#039;s discover the wiki way together! :-) --[[User:Helen|Helen]] 00:24, 27 January 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
Helen, Just a thanks for your wonderful edits which make things look good and are reminders to me to hit that show preview button..again... and again....and then review the whole page. But I have so little to do, so much time :) Bless you.--[[User:chris collman 2|chris collman 2]] 21:13, 28 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:Hi Chris, your kind words are much appreciated :-) Thanks for your contributions to the documentation. --[[User:Helen Foster|Helen Foster]] 06:50, 29 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
==Moodle profile==&lt;br /&gt;
&lt;br /&gt;
Helen- I think you should link to your moodle profile like Martin does (assuming you have one, which I assume &amp;lt;grin&amp;gt;). -- D.I. 29Jan06&lt;br /&gt;
Wow, you&#039;re fast.. .or I&#039;m confused. --D.I. 29Jan06&lt;br /&gt;
&lt;br /&gt;
:Hi D.I. thanks for your suggestion, which [[User:UrsHunkler|someone else]] seem to be following up! ;-) --[[User:Helen|Helen]] 05:00, 30 January 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== German moodle docs possible? ==&lt;br /&gt;
&lt;br /&gt;
Hello Helen,&lt;br /&gt;
&lt;br /&gt;
thank you very much for these nice and structured doc pages.&lt;br /&gt;
When do you plan to launch a german part of the docs.moodle.org pages?&lt;br /&gt;
I ask these question because i can translate some of the english doc pages to german.&lt;br /&gt;
&lt;br /&gt;
Greetings Christoph&lt;br /&gt;
&lt;br /&gt;
:Hi Christoph, thanks for your kind offer of translation. Please email &#039;&#039;docs AT moodle DOT org&#039;&#039; so I may get in touch with you easily when the German Moodle documentation is launched. --[[User:Helen|Helen]] 05:17, 30 January 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== German User Docs ==&lt;br /&gt;
&lt;br /&gt;
Thanks a lot, Helen, for all your work. &lt;br /&gt;
I would also like to help with the German version. &lt;br /&gt;
&lt;br /&gt;
Ulrike&lt;br /&gt;
&lt;br /&gt;
:Hi Ulrike, thanks for your kind offer too. MoodleDocs in other languages will happen soon, for sure! --[[User:Helen|Helen]] 08:30, 31 January 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Documentation for different versions ==&lt;br /&gt;
&lt;br /&gt;
Helen&lt;br /&gt;
&lt;br /&gt;
Is there a mechanism for specifying which version of Moodle a particular document refers to?  If, for instance, a feature is only available in version 1.6, how would a 1.5.3 user know they couldn&#039;t follow these instructions?&lt;br /&gt;
&lt;br /&gt;
Equally, if something is done differently in two versions, how would we stop an edit war breaking out between 1.5.3 and 1.6 users?&lt;br /&gt;
&lt;br /&gt;
I appreciate this probably isn&#039;t an issue just yet, but it&#039;s possible it may become one in later versions.&lt;br /&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
&lt;br /&gt;
[[User:CHRISF|CHRISF]] 19:20, 1 February 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:Hi ChrisF, thanks for highlighting the issue of differences in Moodle versions. Perhaps a Moodle 1.6 template, inserted using the code &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{Moodle 1.6}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, may be used to show features specific to Moodle 1.6. What do you think? --[[User:Helen|Helen]] 04:22, 4 February 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
::Good idea.  I think that would clear it up nicely.  [[User:CHRISF|CHRISF]] 18:08, 7 February 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
==Hungarian Moodle Docs==&lt;br /&gt;
&lt;br /&gt;
Hello Helen,&lt;br /&gt;
I may be knocking at the wrong door.&lt;br /&gt;
Could you please create a folder for me to start Moodle documentation in Hungarian please?&lt;br /&gt;
Thanks a lot.&lt;br /&gt;
Karoly&lt;br /&gt;
&lt;br /&gt;
(Karoly Fabricz, kfabricz AT vnet DOT hu)&lt;br /&gt;
&lt;br /&gt;
:Hi Karoly, thanks for your kind offer. Please read the information on [[MoodleDocs:Starting MoodleDocs|starting Moodle Docs in another language]]. I&#039;ll be in touch soon. --[[User:Helen Foster|Helen Foster]] 17:09, 15 March 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Belarusian Docs is possible? ==&lt;br /&gt;
&lt;br /&gt;
Dear Helen,&lt;br /&gt;
&lt;br /&gt;
I would like to manage Moodle documentation on Belarusian. Could you create a folder for me to start Moodle documentation in Belarusian, please? Аlphabetic acronym of Belarusian language is be.&lt;br /&gt;
&lt;br /&gt;
Sincerely,&lt;br /&gt;
Maryia Davidouskaia&lt;br /&gt;
(maryia at iatp dot by)&lt;br /&gt;
&lt;br /&gt;
:Hi Maryia, thanks for your kind offer. As I said to Karoly, please read the information on [[MoodleDocs:Starting MoodleDocs|starting Moodle Docs in another language]], and remember that the more people that are involved in creating the documentation, the better it will be. I&#039;ll be in touch soon. --[[User:Helen Foster|Helen Foster]] 17:09, 15 March 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
Ok, You are a STAR!&lt;br /&gt;
&lt;br /&gt;
== Template styles ==&lt;br /&gt;
Hi Helen! I noticed that you reverted my edits on [[Template:Book]] and [[Template:Assignments]]. You were right -- I didn&#039;t realise that the [[MoodleDocs:Styling|style]] doesn&#039;t match [[MoodleDocs:Style guide|moodle.org style]]. However, the current template doesn&#039;t look right either. It should float to the right instead of occupying a substantial part of the upper screen (for eg. on [[Calculated question developer docs]] page) -- this wil provide easier navigation. Also, the tempalate should be colorful and/or bordered -- this looks more attractive and the reader can understand that it is not a part of the article. May be we can have orange or similar colored templates (such as [[Template:Large Installations]] and [[Template:excerpted from Jason Cole]]) that match with moodle.org style? Is there any official style documentation? Is there a moodle.org style guide which describes styles for templates -- I couldn&#039;t find one? [[User:Utkarshraj Atmaram|Utkarshraj Atmaram]] 17:40, 30 March 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:Hi Utkarshraj, thanks for your contributions to Moodle Docs. As you&#039;ve found, [[MoodleDocs:Style guide]] and [[MoodleDocs:Styling]] contain all the Moodle Docs styling documentation to-date. Please add your comments about template styling to [[MoodleDocs talk:Styling]]. --[[User:Helen Foster|Helen Foster]] 17:26, 31 March 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
::Thank you! I&#039;ve started the discussion at [[MoodleDocs talk:Styling]]. [[User:Utkarshraj Atmaram|Utkarshraj Atmaram]] 19:14, 31 March 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:::LoL, I just realized that the problem is not with the templates, but with themes. Templates just look find with the MoodleDocs theme, but when I am logged in, I use MonoBook theme -- it doesn&#039;t display them as right-aligned (at Wikipedia, we explicity make the templates right-aligned). Sorry for wasting your time! [[User:Utkarshraj Atmaram|Utkarshraj Atmaram]] 14:44, 18 April 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Slovak Moodle Documentation ==&lt;br /&gt;
&lt;br /&gt;
Hi, Helen. We would like to start work on translation on Moodle Slovak (sk) documentation. Please, do you think is it possible? Thank you.&lt;br /&gt;
&lt;br /&gt;
Sincerely, Juraj Chlebec&lt;br /&gt;
havran@gmail.com&lt;br /&gt;
&lt;br /&gt;
:Hi Juraj, thanks for your offer. Please note that, for non iso-8859-1 languages we need to wait for moodle.org to be converted to UTF-8 (since Moodle Docs authenticates against moodle.org) before setting things up. I&#039;ll be in contact when this is done. --[[User:Helen Foster|Helen Foster]] 22:05, 10 April 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Polish Moodle Documentation ==&lt;br /&gt;
&lt;br /&gt;
Hello, Helen. I saw Your comments to Juraj&#039;s post, so just want to let you know that we are ready to start polish translation. Hope the situation will change soon.&lt;br /&gt;
&lt;br /&gt;
== Removing erroneous pages ==&lt;br /&gt;
&lt;br /&gt;
How can unsuitable pages be removed? I just found [[RHLANGUAGE]] which is not documentation-quality...&lt;br /&gt;
Maybe you could do it (please) Helen? Not sure.&lt;br /&gt;
&lt;br /&gt;
Best, Dan&lt;br /&gt;
--[[User:Dan Stowell|Dan Stowell]] 04:24, 4 May 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:Thanks Dan, for future reference please add the deletion template, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{Deletion}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, to any unsuitable page you find. --[[User:Helen Foster|Helen Foster]] 04:45, 5 May 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Request for help (check) ==&lt;br /&gt;
&lt;br /&gt;
Hi, Sun, could you check this page: https://docs.moodle.org/en/Release_Notes &lt;br /&gt;
all the info written both in 1.6 and 1.5.4 relative to the Authorize plugin? Ethem Evlice requested me to do so, but you know, I&#039;m not the best English checker in the world! ;-) [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 17:35, 11 May 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:NP Sol, I&#039;ve done as requested :-) --[[User:Helen Foster|Helen Foster]] 19:51, 15 May 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Moodle Doc Is Great ==&lt;br /&gt;
&lt;br /&gt;
You have done a great job and inspired me to use Media Wiki!&lt;br /&gt;
&lt;br /&gt;
:Thanks Martin, though it&#039;s everyone&#039;s contributions that make Moodle Docs a great resource! --[[User:Helen Foster|Helen Foster]] 06:36, 24 May 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Moodle Docs Wiki accidentally switched to Portuguese? ==&lt;br /&gt;
&lt;br /&gt;
Hi Helen, all of the built in Mediawiki content is appearing in Portuguese for me, both before and after I log in. Perhaps an admin setting that&#039;s been accidentally changed? --[[User:David Scotson|David Scotson]] 17:36, 27 Maio 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:To clarify, only some of the Mediawiki content is in Portuguese. If I go to to the user preferences and choose Portuguese it changes even more text. Changing back to English only returns some text to English. However, choosing French changes all Mediawiki text to French. From this I&#039;m guessing that someone may have overwritten some of the english language files on the server with Portuguese ones. --[[User:David Scotson|David Scotson]] 17:40, 27 Maio 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
::Hi David, yes the [[Special:Allmessages|System messages]] were overwritten by accident. Anyway, it&#039;s fixed now and I&#039;ve learnt from the experience ;-) --[[User:Helen Foster|Helen Foster]] 19:39, 28 May 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== tr wiki ==&lt;br /&gt;
&lt;br /&gt;
Hi Helen,&lt;br /&gt;
&lt;br /&gt;
Can you arrange for a wiki https://docs.moodle.org/tr (Türkçe) to be set up.&lt;br /&gt;
&lt;br /&gt;
:Thanks Ethem, I&#039;ll do so as soon as possible. --[[User:Helen Foster|Helen Foster]] 17:12, 15 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Finnish Moodle Docs? ==&lt;br /&gt;
&lt;br /&gt;
Hello Helen!&lt;br /&gt;
&lt;br /&gt;
I&#039;m interested in starting and overlooking the Moodle Docs in Finnish. Can you set up https://docs.moodle.org/fi/? My email is samuli DOT karevaara AT lamk DOT fi.&lt;br /&gt;
&lt;br /&gt;
Regards, --[[User:Samuli Karevaara|Samuli Karevaara]] 14:14, 12 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:Helen, thanks, I see that https://docs.moodle.org/fi/ just happened :-). And by the way, you already undid my &amp;quot;This section is unfinished&amp;quot; that I wrote on the front page two minutes before you wrote the &amp;quot;Welcome to Moodle Docs in Finnish&amp;quot; :-) --[[User:Samuli Karevaara|Samuli Karevaara]] 01:04, 14 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
::Wow Samuli, you&#039;re so fast! Sorry for deleting your text. You&#039;re now an admin so you may rollback changes if necessary ;-) --[[User:Helen Foster|Helen Foster]] 01:53, 14 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Translation to Bosnian languages ==&lt;br /&gt;
&lt;br /&gt;
Hi Hellen,&lt;br /&gt;
&lt;br /&gt;
I&#039;m exploring the Moodle environment for DLE LMS support for one projec that I work in the former Yugoslavia countries. I&#039;ll translate documentation for my own sake, and if I can contribute to Moodle have translated documentation in four south-east europen conutries (Bosnia, Croatia, Montenegro, Serbia) it will be my pleasure. Just give me the hint how I can start this.&lt;br /&gt;
&lt;br /&gt;
Best, Latif&lt;br /&gt;
&lt;br /&gt;
:Hi Latif, thanks for your kind offer. Please read the information on [[MoodleDocs:Starting MoodleDocs|starting Moodle Docs in another language]]. Croatian is included in the list of [[MoodleDocs talk:Starting MoodleDocs|languages currently awaiting Moodle Docs]]. I hope it will be set up soon. --[[User:Helen Foster|Helen Foster]] 17:42, 15 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Word Censorship Page ==&lt;br /&gt;
&lt;br /&gt;
Hi Helen, &lt;br /&gt;
&lt;br /&gt;
Note sure why you deleted some of this page. The idea is (partly) to provide instructions on how to use the settings page of the filter. You also removed the &#039;see also&#039; back to the main filters administration page. I&#039;m not sure what&#039;s wrong with that either. Your advice appreciated :-)&lt;br /&gt;
&lt;br /&gt;
--[[User:Howard Miller|Howard Miller]] 22:54, 20 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:Oh, sorry Howard for not explaining my changes to [[Word censorship]]. I deleted text duplicated on the Word censorship settings page in Moodle and removed the See also link since [[Filters (administrator)]] is listed in [[:Category:Filter]]. However, please feel free to revert any/all of my changes. Your contributions to the documentation are always appreciated :-) --[[User:Helen Foster|Helen Foster]] 17:03, 21 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
::That&#039;s cool Helen. So is that the rule - don&#039;t put stuff in the docs that is already in the built-in help?? --[[User:Howard Miller|Howard Miller]] 18:15, 21 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:::The [http://moodle.org/help.php?file=index.html Moodle help files] will remain in each language pack and so it is not necessary to include their text in this documentation, however sometimes it makes things clearer to do so, at least to start with. --[[User:Helen Foster|Helen Foster]] 15:46, 22 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== translation moodle docs to Korean... ==&lt;br /&gt;
&lt;br /&gt;
You did great jobs! Thanks...&lt;br /&gt;
We want to translate Moodle Docs to Korean languages.&lt;br /&gt;
Please open ko field...&lt;br /&gt;
&lt;br /&gt;
:Hi, thanks for your offer. Please read the information on [[MoodleDocs:Starting MoodleDocs|starting Moodle Docs in another language]] and find out how many people are interested by discussing Moodle Docs in your moodle.org [http://moodle.org/course/category.php?id=3 community discussion] course. --[[User:Helen Foster|Helen Foster]] 15:42, 22 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Contrib code documentation ==&lt;br /&gt;
&lt;br /&gt;
Hi Helen,&lt;br /&gt;
&lt;br /&gt;
Where would you suggest I document contrib code. I have some documentation for the Moodle for Mobiles project which installs in {yourmoodleroot}/mobile The code is in cvs in contrib/mobile. It is general documentation about what MFM does.&lt;br /&gt;
&lt;br /&gt;
I guess the place to put it would be https://docs.moodle.org/en/mobile&lt;br /&gt;
&lt;br /&gt;
Jamie&lt;br /&gt;
&lt;br /&gt;
:Hi Jamie, actually the project already has a page, [[Moodle for Mobiles]] ;-) though [[mobile]] could redirect to it. You&#039;re also welcome to use any documentation pages linked to Moodle for Mobiles pages in Moodle 1.6. --[[User:Helen Foster|Helen Foster]] 15:56, 22 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
::Thanks Helen!! Adding the documentation now. Will redirect from mobile as well. [[User:Jamie Pratt|Jamie Pratt]] 16:08, 22 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
:::Cool Helen you did the redirect for me. Thanks for your very speedy response to my enquiry and all your help! -- [[User:Jamie Pratt|Jamie Pratt]] 16:22, 22 June 2006 (WST)&lt;br /&gt;
&lt;br /&gt;
== Chinese Moodle Documentation==&lt;br /&gt;
Hi Helen,&lt;br /&gt;
&lt;br /&gt;
I&#039;d like to launch the Chinese Moodle Documentation translation. As I know, MediaWiki has the function that convert charset between Simplified Chinese(GB2312, GB18030) and Traditional Chinese(BIG5). So maybe it&#039;s no need to create two. &lt;br /&gt;
&lt;br /&gt;
Now I&#039;m a translator of moodle and maintain a special moodle Chinese version.&lt;br /&gt;
&lt;br /&gt;
--[[User:Sun Sunner|Sun Sunner]] 21:31, 22 July 2006 (WST)&lt;/div&gt;</summary>
		<author><name>Sunner</name></author>
	</entry>
</feed>