Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Using the File API in Moodle forms: Difference between revisions

From MoodleDocs
m (Protected "Using the File API in Moodle forms": Developer Docs Migration ([Edit=Allow only administrators] (indefinite)))
 
(91 intermediate revisions by 25 users not shown)
Line 1: Line 1:
{{Moodle 2.0}}In Moodle 2.0 onwards, we introduced [[Repository API|Repository API]] to fetch files from external sources, [[Repository API|Repository API]] will move to files into draft areas, then modules will process moving draft area files into a proper file areas, this documentation will demonstrate how to do that.
{{Template:Migrated|newDocId=/docs/apis/subsystems/form/usage/files}}
 
There are three form elements involved with [[Repository API|Repository API]], they are file manager, file picker and editor, the legacy upload button will be replaced by file picker or file manager, file picker and file manager work similar, the only difference is file manager can fetch multiple files, file picker only fetch one file. Editor element is introduced to replace legacy htmleditor element, I will talk about them respectively.
 
Modules are using [[File API|File API]] for management of own files, they do not need to be aware of any repositories.
 
==Form element: file picker==
 
File picker (''filepicker'') is a direct replacement of older ''file'' formslib element. It is intended for situations when user uploads one file, the file is immediately processed and then deleted. Examples are upload of users and grades from csv file.
 
=== Replace file with filepicker element ===
 
<code php>
$mform->addElement('filepicker', 'userfile', get_string('file'), null, array('maxbytes' => $maxbytes, 'filetypes' => '*'));
</code>
 
=== Obtain picked file ===
 
The API for getting file contents is exactly the same as for ''file'' element.
 
<code php>
$content = $mform->get_file_content('userfile');
</code>
 
==Form element: file manager==
File manager (''filemanager'') element is an improved file picker, the difference is it can be used for managing of one or more files. It is expected that the files are stored permanently for future use. Examples of use are forum and glossary attachments.
 
=== Add file manager element ===
 
<code php>
$mform->addElement('filemanager', 'attachments', get_string('attachment', 'moodle'), null,
    array('subdirs' => 0, 'maxbytes' => $maxbytes, 'maxfiles' => 50, 'filetypes' => '*'));
</code>
You can specify what file types are accepted by filemanager, all file types are listed at moodle/lib/file/file_types.mm, this is a freemind file, you can edit it freely, the changes will be reflected in moodle.
 
=== Load existing files into draft area ===
 
<code php>
if (empty($entry->id)) {
  $entry = new object();
  $entry->id = null;
}
 
$draftitemid = file_get_submitted_draft_itemid('attachments');
file_prepare_draft_area($draftitemid, $context->id, 'glossary_attachment', $entry->id , false);
$entry->attachements = $draftitemid;
 
$mform->set_data($entry);
 
</code>
 
=== Store updated set of files ===
 
<code php>
if ($data = $mform->get_data()) {
    // ... store or update $entry
    file_save_draft_area_files($draftitemid, $context->id, 'glossary_attachment', $entry->id, array('subdirs' => 0, 'maxbytes' => $maxbytes, 'maxfiles' => 50, 'filetypes' => '*'));
}
</code>
 
==Form element: editor==
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.
 
===Simple use===
# name database fields: ''textfield'', ''textfieldformat'' (and ''textfieldtrust'' if required)
# create options array <code php>$textfieldoptions = array('trusttext'=>true, 'subdirs'=>true, 'maxfiles'=>$maxfiles, 'maxbytes'=>$maxbytes);</code>
# add editor ''textfield_editor'' to moodle form, pass options through custom data in form constructor, set $data->id to null if data not exist yet <code php>$mform->addElement('editor', 'textfield_editor', get_string('fieldname', 'somemodule'), null, $textfieldoptions);</code>
# prepare data <code php>$data = file_prepare_standard_editor($data, 'textfield', $textfieldoptions, $context, 'somemodule_somearea', $data->id);</code>
# get submitted data and after inserting/updating of data <code php>$data = file_postupdate_standard_editor($data, 'textfield', $textfieldoptions, $context, 'somemodule_somearea', $data->id);</code>
 
Real work examples are in mod/glossary/edit.php and mod/glossary/comment.php
 
===Low level use===
 
When using editor element you  need to preprocess and postprocess the data:
# detect if form was already submitted (usually means draft is area already exists) - ''file_get_submitted_draft_itemid()''
# prepare draft file area, temporary storage of all files attached to the text - ''file_prepare_draft_area()''
# convert encoded relative links to absolute links - ''file_prepare_draft_area()''
# create form and set current data
# after submission the changed files must be merged back into original area - ''file_save_draft_area_files()''
# absolute links have to be replaced by relative links - ''file_save_draft_area_files()''
 
====Replace old htmleditor with editor====
 
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:
<code php>
$mform->addElement('editor', 'entry', get_string('definition', 'glossary'),
        array('maxfiles' => EDITOR_UNLIMITED_FILES, 'filearea' => 'glossary_entry'));
</code>
The editor element can take following options: maxfiles, maxbytes, filearea, subdirs and changeformat. Please note that the embedded files is optional feature and is not expected be used everywhere.
 
'''Note''': the editor element now includes text format option. You should no longer use the separate format element type.
 
====Prepare current data - text and files====
 
<code php>
if (empty($entry->id)) {
  $entry = new object();
  $entry->id = null;
  $entry->definition = '';
  $entry->format = FORMAT_HTML;
}
 
$draftid_editor = file_get_submitted_draft_itemid('entry');
$currenttext = file_prepare_draft_area($draftid_editor, $context->id, 'glossary_entry', $entry->id, true, $entry->definition);
$entry->entry = array('text'=>$currenttext, 'format'=>$entry->format, 'itemid'=>$draftid_editor);
 
$mform->set_data($entry);
</code>
 
If there are multiple files, they will share the same itemid.
 
====Obtain text, format and save draft files====
 
To retrieve editor content, you need to use following code:
 
<code php>
if ($fromform = $mform->get_data()) {
    // content of editor
    $messagetext = $fromform->message['text'];
    // format of content
    $messageformat  = $fromform->message['format'];
}
</code>
 
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.
 
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->update_record('tablename', $data); to have the other parts of the form submission stored correctly.)
 
The save_files_from_draft_area function and replace absolute links with internal relative links do:
<code php>
$messagetext = file_save_draft_area_files($draftid_editor, $context->id, 'glossary_entry', $entry->id, true, $messagetext);
</code>
; $context->id, 'proper_file_area' and $entry->id : correspond to the contextid, filearea and itemid columns in the [[File_API#Table:_files|files table]].
; $messagetext : this is the message text. As the files are saved to the real file area, the URLs in this content are rewritten.
 
All URLs in content that point to files managed to the File API are converted to a form that starts '@@PLUGINFILE@@/' before the content is stored in the database. That is what we mean by rewriting.
 
== File serving==
 
=== Convert internal relative links to absolute links ===
 
Before text content is displayed to the user, any URLs in the '@@PLUGINFILE@@/' form in the content need to be rewritten to the real URL where the user can access the files.
<code php>
$messagetext = file_rewrite_pluginfile_urls($messagetext, 'pluginfile.php',
        "$context->id/proper_file_area/$itemid/");
</code>
; $messagetext : is the content containing the @@PLUGINFILE@@ URLs from the database.
; 'pluginfile.php' : there are a number of different scripts that can serve files with different permissions checks. You need to specify which one to use.
; "$context->id/proper_file_area/$itemid/" : uniquely identifies the file area, as before.
 
=== Implement file serving access control ===
 
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 ''module/lib.php'' file in function ''module_pluginfile()''.
 
 
== File browsing support ==
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.
 
Activities may specify browsing support in own module/lib.php file by implementing functions module_get_file_areas() and module_get_file_info().
 
== See also ==
 
* [[File API]]
* [[Using the file API]]
* [[Repository API]]
* [[Portfolio API]]
* MDL-14589 - File API Meta issue
 
{{CategoryDeveloper}}
[[Category:Files]]
[[Category:Repositories]]

Latest revision as of 12:57, 16 January 2023

Important:

This content of this page has been updated and migrated to the new Moodle Developer Resources. The information contained on the page should no longer be seen up-to-date.

Why not view this page on the new site and help us to migrate more content to the new site!