Difference between revisions of "Developer Area/Core Subsystems/Artefact Plugins // Artefact Types"

From Mahara Wiki
Jump to navigation Jump to search
(Created page with "Mahara's basic funtionality is comprised of '''''Artefacts'''''. <br /><br /> The basic unit of content in Mahara is called an artefact. All sorts of things are artefacts - blog …")
 
m (Language strings)
 
(5 intermediate revisions by 3 users not shown)
Line 3: Line 3:
 
<div id="section_1">
 
<div id="section_1">
  
== Basics of an Artefact Plugin ==
+
==Basics of an Artefact Plugin==
  
When Thinking about writing a new Artefact plugin, the first step is to realise that they are comprised of several different parts. There are some required items every artefact plugin must include. For the purposes of this document we're going to assume you're writing a new artefact plugin called ''''Myplugin''''. <br /><br /> The first step is to create the required file structure by making a new directory under <span><font face="Courier New">'''htdocs/artefact/myplugin'''</font></span>. This folder will contain all of your files and items, and the basic structure is as follows:<br />
+
When Thinking about writing a new Artefact plugin, the first step is to realise that they are comprised of several different parts. There are some required items every artefact plugin must include. For the purposes of this document we're going to assume you're writing a new artefact plugin called ''''Myplugin''''. <br /><br /> The first step is to create the required file structure by making a new directory under <font face="Courier New">'''htdocs/artefact/myplugin'''</font>. This folder will contain all of your files and items, and the basic structure is as follows:<br />
  
* <span><font face="Courier New">lib.php </font></span>- Contains the class that implements the functionality of your Artefact. This is the main controller, and it must extend the abstract class PluginArtefact?
+
* <font face="Courier New">lib.php </font>- Contains the class that implements the functionality of your Artefact. This is the main controller, and it must extend the abstract class PluginArtefact.
* <span><font face="Courier New">version.php</font></span> - contains version information about the artefact.
+
* <font face="Courier New">version.php</font> - contains version information about the artefact.
* <span><font face="Courier New">index.php</font></span> - should your plugin contain content that is manipulated by the user, this file contains the functions necessary to show them.
+
* <font face="Courier New">index.php</font> - should your plugin contain content that is manipulated by the user, this file contains the functions necessary to show them.
 
* '''/theme''' -folder. This contains all of the Template files of your artefact, as well as all of the CSS and images needed in your plugin. You can also have multiple themes for your artefact. The default theme is always created under /theme/raw, but you can also create new themes by placing them in new folders under /theme. Read more about templates from their own article
 
* '''/theme''' -folder. This contains all of the Template files of your artefact, as well as all of the CSS and images needed in your plugin. You can also have multiple themes for your artefact. The default theme is always created under /theme/raw, but you can also create new themes by placing them in new folders under /theme. Read more about templates from their own article
 
* '''/db''' -folder. This folder contains two files that define the database structure of your plugin.
 
* '''/db''' -folder. This folder contains two files that define the database structure of your plugin.
** <span><font face="Courier New">install.xml</font></span> - An xml-file that defines the structure of your database according to the built-in XMLDB definition.
+
** <font face="Courier New">install.xml</font> - An xml-file that defines the structure of your database according to the built-in XMLDB definition.
** <span><font face="Courier New">upgrade.php</font></span> - Used to make checks for changes in the version of the plugin/blocktype. Needed when old versions of the plugin/blocktype must be upgraded.
+
** <font face="Courier New">upgrade.php</font> - Used to make checks for changes in the version of the plugin/blocktype. Needed when old versions of the plugin/blocktype must be upgraded.
 
* '''/lang '''-folder. Localization files for you artefact. Contains translations for strings used in the artefact under their own folder.
 
* '''/lang '''-folder. Localization files for you artefact. Contains translations for strings used in the artefact under their own folder.
 
* '''/blocktype''' -folder. If your artefacts make use of any blocktypes, they will go under here. Refer to the blocktype documentation to learn more about them.
 
* '''/blocktype''' -folder. If your artefacts make use of any blocktypes, they will go under here. Refer to the blocktype documentation to learn more about them.
Line 21: Line 21:
 
<div id="section_2">
 
<div id="section_2">
  
=== lib.php ===
+
===lib.php===
  
This file is the backbone of the whole plugin, and the most logical starting point. The first thing you must do when creating this file is write a Plugin subclass -''' PluginArtefactMyplugin''' extends''' PluginArtefac''''''t'''. Read the phpdocs for the Plugin base class in<span><font face="Courier New"> lib/mahara.php</font></span>, and PluginArtefact in <span><font face="Courier New">artefact/lib.php</font></span> to see exactly what all the methods are. Any methods you must implement will always be abstract. This it what a bare-essential class looks like:
+
This file is the backbone of the whole plugin, and the most logical starting point. The first thing you must do when creating this file is write a Plugin subclass -''' PluginArtefactMyplugin''' extends''' PluginArtefac''''''t'''. Read the phpdocs for the Plugin base class in<font face="Courier New"> lib/mahara.php</font>, and PluginArtefact in <font face="Courier New">artefact/lib.php</font> to see exactly what all the methods are. Any methods you must implement will always be abstract. This it what a bare-essential class looks like:
  
<code style="background-color: #cccccc">defined('INTERNAL') || die();<br /><br /> require_once('activity.php');<br /><br /> class PluginArtefactMyPlugin? extends PluginArtefact? {<br /><br /> public static function get_artefact_types() {<br /> return array(<br /> 'MyPlugin',<br /> );<br /> }<br /><br /> public static function get_block_types() {<br /> return array();<br /> }<br /><br /> public static function get_plugin_name() {<br /> return 'MyPlugin';<br /> }<br /><br /> public static function menu_items() {<br /> return array(<br /> array(<br /> 'path' =&gt; 'myportfolio/myplugin',<br /> 'url' =&gt; 'artefact/myplugin/',<br /> 'title' =&gt; get_string('MenuItemString', 'artefact.myplugin'),<br /> 'weight' =&gt; 20,<br /> ),<br /> );<br /> }<br /> }<br /><br /><br /> class ArtefactTypeMyPlugin? extends ArtefactType? {<br /> public function render_self($options) {<br /> return get_string('TestName', 'artefact.myplugin');<br /> }<br /><br /> public static function get_icon($options=null) {}<br /><br /> public static function is_singular() {<br /> return false;<br /> }<br /><br /> public static function get_links($id) {}<br /> }<br /></code>
+
<code style="background-color: #cccccc">defined('INTERNAL') || die();<br /><br /> require_once('activity.php');<br /><br /> class PluginArtefactMyPlugin extends PluginArtefact {<br /><br /> public static function get_artefact_types() {<br /> return array(<br /> 'MyPlugin',<br /> );<br /> }<br /><br /> public static function get_block_types() {<br /> return array();<br /> }<br /><br /> public static function get_plugin_name() {<br /> return 'MyPlugin';<br /> }<br /><br /> public static function menu_items() {<br /> return array(<br /> array(<br /> 'path' =&gt; 'myportfolio/myplugin',<br /> 'url' =&gt; 'artefact/myplugin/',<br /> 'title' =&gt; get_string('MenuItemString', 'artefact.myplugin'),<br /> 'weight' =&gt; 20,<br /> ),<br /> );<br /> }<br /> }<br /><br /><br /> class ArtefactTypeMyPlugin extends ArtefactType {<br /> public function render_self($options) {<br /> return get_string('TestName', 'artefact.myplugin');<br /> }<br /><br /> public static function get_icon($options=null) {}<br /><br /> public static function is_singular() {<br /> return false;<br /> }<br /><br /> public static function get_links($id) {}<br /> }<br /></code>
  
The main two methods in this class you must implement are<span><font face="Courier New"> get_artefact_types </font></span>and<span><font face="Courier New"> get_blocktypes</font></span>. Below you will find a table to be used as a cheat sheet that contains all of the abstract methods, taken from <span><font face="Courier New">lib/mahara.php</font></span> and <span><font face="Courier New">artefact/lib.php</font></span> with their phpdoc.
+
The main two methods in this class you must implement are<font face="Courier New"> get_artefact_types </font>and<font face="Courier New"> get_blocktypes</font>. Below you will find a table to be used as a cheat sheet that contains all of the abstract methods, taken from <font face="Courier New">lib/mahara.php</font> and <font face="Courier New">artefact/lib.php</font> with their phpdoc.
  
 
<div id="section_3">
 
<div id="section_3">
  
==== Artefact Types ====
+
====Artefact Types====
  
 
Artefact plugins are made up of any number of artefact types that behave slightly differently, but are related. For example, the file plugin contains three artefact types - '''file''', '''folder''', and '''image''', that have slightly different properties. The blog plugin contains '''blog''' and '''blogpost'''. As blogpost is a child of blog, file and image are children of folder as well (in a logical sense, rather than in php). <br /><br /> Artefact plugins may also contain blocktype plugins. Blocks are how artefacts get into views, and it's really just presentation information with some configuration. <br /><br /> For your plugin, you tell Mahara which blocktypes and artefact types you're implementing in the above functions, and then you must write a class for each. More on embedded blocktypes later on in this documentation. Please also see the Blocktype documentation elsewhere in the wiki.<br />
 
Artefact plugins are made up of any number of artefact types that behave slightly differently, but are related. For example, the file plugin contains three artefact types - '''file''', '''folder''', and '''image''', that have slightly different properties. The blog plugin contains '''blog''' and '''blogpost'''. As blogpost is a child of blog, file and image are children of folder as well (in a logical sense, rather than in php). <br /><br /> Artefact plugins may also contain blocktype plugins. Blocks are how artefacts get into views, and it's really just presentation information with some configuration. <br /><br /> For your plugin, you tell Mahara which blocktypes and artefact types you're implementing in the above functions, and then you must write a class for each. More on embedded blocktypes later on in this documentation. Please also see the Blocktype documentation elsewhere in the wiki.<br />
Line 37: Line 37:
 
<div id="section_4">
 
<div id="section_4">
  
===== ArtefactType subclasses =====
+
=====ArtefactType subclasses=====
  
For each artefact type that '''<span><font face="Courier New">PluginArtefactMyplugin</font></span>'''<span><font face="Courier New"><nowiki>::get_artefact_type</nowiki></font></span>s returns, you must write a class that subclasses <span><font face="Courier New">'''ArtefactType'''</font></span>. Again, the best way to understand all the methods in the class is to read the phpdocs for the parent class, in <span><font face="Courier New">artefact/lib.php</font></span>. Also, the methods you must implement are abstract again.
+
For each artefact type that '''<font face="Courier New">PluginArtefactMyplugin</font>'''<font face="Courier New">::get_artefact_type</font>s returns, you must write a class that subclasses <font face="Courier New">'''ArtefactType'''</font>. Again, the best way to understand all the methods in the class is to read the phpdocs for the parent class, in <font face="Courier New">artefact/lib.php</font>. Also, the methods you must implement are abstract again.
  
 
</div></div><div id="section_5">
 
</div></div><div id="section_5">
  
==== Abstract functions cheat sheets: ====
+
====Abstract functions cheat sheets:====
  
Listed below are the abstract functions of the parent classes that you absolutely must implement in your <span><font face="Courier New">lib.php</font></span>, if you extend said classes. Keep in mind that these are by no means the only functions you will need to override. They are listed here as a quick cheat sheet to get you going faster.
+
Listed below are the abstract functions of the parent classes that you absolutely must implement in your <font face="Courier New">lib.php</font>, if you extend said classes. Keep in mind that these are by no means the only functions you will need to override. They are listed here as a quick cheat sheet to get you going faster.
  
 
{| width="600" border="1" cellspacing="1" cellpadding="1"
 
{| width="600" border="1" cellspacing="1" cellpadding="1"
| style="background-color: #333333" | <span><font color="#FFFFFF">Abstract class '''PluginArtefact '''extends '''Plugin'''</font></span>
+
| style="background-color: #333333" | <font color="#FFFFFF">Abstract class '''PluginArtefact '''extends '''Plugin'''</font>
| style="background-color: #333333" | <span><font color="#FFFFFF"><span style="background-color: #333333">'''PHPDoc for the functions'''</span></font></span>
+
| style="background-color: #333333" | <font color="#FFFFFF"><span style="background-color: #333333">'''PHPDoc for the functions'''</span></font>
 
|-
 
|-
| <span><font face="Courier New">public static abstract function get_artefact_types()</font></span>
+
| <font face="Courier New">public static abstract function get_artefact_types()</font>
 
|
 
|
 
This function returns a list of classnames of artefact types this plugin provides.
 
This function returns a list of classnames of artefact types this plugin provides.
 +
 
* '''@return''' array
 
* '''@return''' array
 
|-
 
|-
| <span><font face="Courier New">public static abstract function get_block_types()</font></span>
+
| <font face="Courier New">public static abstract function get_block_types()</font>
 
|
 
|
This function returns a list of classnames of block types this plugin provides they must match directories inside <span><font face="Courier New">artefact/$name/blocktype</font></span>
+
This function returns a list of classnames of block types this plugin provides they must match directories inside <font face="Courier New">artefact/$name/blocktype</font>
 +
 
 
* '''@abstract'''
 
* '''@abstract'''
 
* '''@return''' array<br />
 
* '''@return''' array<br />
 
|-
 
|-
| <span><font face="Courier New">public static abstract function get_plugin_name()</font></span>
+
| <font face="Courier New">public static abstract function get_plugin_name()</font>
 
|
 
|
 
This function returns the name of the plugin.
 
This function returns the name of the plugin.
 +
 
* '''@return''' string
 
* '''@return''' string
 
|-
 
|-
| style="background-color: #333333" | <span><font color="#FFFFFF">Abstract class '''ArtefactType'''</font></span>
+
| style="background-color: #333333" | <font color="#FFFFFF">Abstract class '''ArtefactType'''</font>
| style="background-color: #333333" | <span><font color="#FFFFFF">'''PHPDoc for the functions'''</font></span>
+
| style="background-color: #333333" | <font color="#FFFFFF">'''PHPDoc for the functions'''</font>
 
|-
 
|-
| <span><font face="Courier New">public static abstract function get_icon($options=null)</font></span>
+
| <font face="Courier New">public static abstract function get_icon($options=null)</font>
 
|
 
|
 
Returns a URL for an icon for the appropriate artefact.
 
Returns a URL for an icon for the appropriate artefact.
 +
 
* '''@param''' array $options Options for the artefact. The array MUST have the 'id' key, representing the ID of the artefact for which the icon is being generated. Other keys include 'size' for a [width]x[height] version of the icon, as opposed to the default 20x20, and 'view' for the id of the view in which the icon is being displayed.
 
* '''@param''' array $options Options for the artefact. The array MUST have the 'id' key, representing the ID of the artefact for which the icon is being generated. Other keys include 'size' for a [width]x[height] version of the icon, as opposed to the default 20x20, and 'view' for the id of the view in which the icon is being displayed.
 
* '''@return''' string URL for the icon
 
* '''@return''' string URL for the icon
 
|-
 
|-
| <span><font face="Courier New">public static abstract function is_singular()</font></span>
+
| <font face="Courier New">public static abstract function is_singular()</font>
 
| Whether a user will have exactly 0 or 1 of this artefact type.
 
| Whether a user will have exactly 0 or 1 of this artefact type.
 
|-
 
|-
| <span><font face="Courier New">public static abstract function get_links($id)</font></span>
+
| <font face="Courier New">public static abstract function get_links($id)</font>
 
|
 
|
 
Returns a list of key =&gt; value pairs where the key is either '_default' or a langauge string, and value is a URL linking to that behaviour for this artefact type <br />
 
Returns a list of key =&gt; value pairs where the key is either '_default' or a langauge string, and value is a URL linking to that behaviour for this artefact type <br />
 +
 
* '''@param''' integer This is the ID of the artefact being linked to
 
* '''@param''' integer This is the ID of the artefact being linked to
 
|}
 
|}
Line 88: Line 93:
  
 
{| width="600" border="1" cellspacing="1" cellpadding="1"
 
{| width="600" border="1" cellspacing="1" cellpadding="1"
| style="background-color: #333333" | <span><font color="#FFFFFF">'''Other common functions found in '''<span><font face="Courier New">'''lib.php'''</font></span></font></span>
+
| style="background-color: #333333" | <font color="#FFFFFF">'''Other common functions found in '''<font face="Courier New">'''lib.php'''</font></font>
| style="background-color: #333333" | <span><font color="#FFFFFF">'''Description'''</font></span>
+
| style="background-color: #333333" | <font color="#FFFFFF">'''Description'''</font>
 
|-
 
|-
 
| menu_items()
 
| menu_items()
Line 107: Line 112:
 
|-
 
|-
 
| get_config(' root_name ')
 
| get_config(' root_name ')
| Used to get some folder location(for example ''''docroot'''' returns location of the mahara folder on the local disk(<span><font face="Courier New">/var/www/mahara</font></span>) and ''''wwwroot'''' returns url of the mahara folder in the www directory(<span><font face="Courier New">http://localhost/mahara</font></span>))
+
| Used to get some folder location(for example ''''docroot'''' returns location of the mahara folder on the local disk(<font face="Courier New">/var/www/mahara</font>) and ''''wwwroot'''' returns url of the mahara folder in the www directory(<font face="Courier New">http://localhost/mahara</font>))
 
|-
 
|-
 
| get_cron()
 
| get_cron()
Line 118: Line 123:
 
</div></div><div id="section_6">
 
</div></div><div id="section_6">
  
=== index.php ===
+
===index.php===
  
 
Should your artefact plugin be visible to your users, you must also include an index.php in your plug-in. This is the controller file that leads up to showing the user your views from the''' /theme''' -folder. Here is an example of an index.php:
 
Should your artefact plugin be visible to your users, you must also include an index.php in your plug-in. This is the controller file that leads up to showing the user your views from the''' /theme''' -folder. Here is an example of an index.php:
Line 126: Line 131:
 
</div><div id="section_7">
 
</div><div id="section_7">
  
=== Blocktypes ===
+
===Blocktypes===
  
For each block type that''' <span><font face="Courier New">PluginArtefactMyplugin</font></span>'''<span><font face="Courier New"><nowiki>::get_block_types</nowiki></font></span> returns, you must do the following: <br />
+
For each block type that''' <font face="Courier New">PluginArtefactMyplugin</font>'''<font face="Courier New">::get_block_types</font> returns, you must do the following: <br />
  
Create <span><font face="Courier New">artefact/myplugin/blocktype/theblockname/lib.php</font></span> and write a class in it:''' PluginBlocktypeTheblockname''' extends '''PluginBlocktype'''. Again, all required methods are abstract and the best way to learn about this is to read the parent class.<br />
+
Create <font face="Courier New">artefact/myplugin/blocktype/theblockname/lib.php</font> and write a class in it:''' PluginBlocktypeTheblockname''' extends '''PluginBlocktype'''. Again, all required methods are abstract and the best way to learn about this is to read the parent class.<br />
  
 
<div id="section_8">
 
<div id="section_8">
  
==== '''PluginBlocktype''' Abstract cheat sheet ====
+
===='''PluginBlocktype''' Abstract cheat sheet====
  
 
Listed in this cheat sheet are the abstract functions you need to implement in each class. Also listed are some other commonly found overriden functions.
 
Listed in this cheat sheet are the abstract functions you need to implement in each class. Also listed are some other commonly found overriden functions.
  
 
{| width="600" border="1" cellspacing="1" cellpadding="1"
 
{| width="600" border="1" cellspacing="1" cellpadding="1"
| style="background-color: #333333" | <span><font color="#FFFFFF">Abstract class</font></span>'''<span><font color="#FFFFFF"> PluginBlocktype</font></span>'''
+
| style="background-color: #333333" | <font color="#FFFFFF">Abstract class</font>'''<font color="#FFFFFF"> PluginBlocktype</font>'''
| style="background-color: #333333" | '''<span><font color="#FFFFFF">PHPDoc for the functions</font></span>'''
+
| style="background-color: #333333" | '''<font color="#FFFFFF">PHPDoc for the functions</font>'''
 
|-
 
|-
| <span><font face="Courier New">public static abstract function get_title();</font></span>
+
| <font face="Courier New">public static abstract function get_title();</font>
 
|
 
|
 
If this blocktype contains artefacts, and uses the artefactchooser Pieform element to choose them, this method must return the definition for the element. This is used in view/artefactchooser.json.php to build pagination for the element. The element returned MUST have the name key set to either 'artefactid' or 'artefactids', depending on whether 'selectone' is true or false. The element must also have the 'blocktype' key set to the name of the blocktype that the form is for.
 
If this blocktype contains artefacts, and uses the artefactchooser Pieform element to choose them, this method must return the definition for the element. This is used in view/artefactchooser.json.php to build pagination for the element. The element returned MUST have the name key set to either 'artefactid' or 'artefactids', depending on whether 'selectone' is true or false. The element must also have the 'blocktype' key set to the name of the blocktype that the form is for.
 +
 
* '''@param''' mixed $default The default value for the element
 
* '''@param''' mixed $default The default value for the element
 
|-
 
|-
| <span><font face="Courier New">public static abstract function get_description();</font></span>
+
| <font face="Courier New">public static abstract function get_description();</font>
 
|
 
|
 
subclasses can override this if they need to do something a bit special eg more than just what the BlockInstance??-&gt;delete function does.
 
subclasses can override this if they need to do something a bit special eg more than just what the BlockInstance??-&gt;delete function does.
 +
 
* '''@param''' BlockInstance $instance
 
* '''@param''' BlockInstance $instance
 
|-
 
|-
| <span><font face="Courier New">public static abstract function get_categories();</font></span>
+
| <font face="Courier New">public static abstract function get_categories();</font>
 
| Returns array which specifies the categories where the blocktype resides in the view creator. Possbile options: feeds, fileimagevideo, general, internal, resume
 
| Returns array which specifies the categories where the blocktype resides in the view creator. Possbile options: feeds, fileimagevideo, general, internal, resume
 
|-
 
|-
| <span><font face="Courier New">public static abstract function render_instance(BlockInstance $instance, $editing=false);</font></span>
+
| <font face="Courier New">public static abstract function render_instance(BlockInstance $instance, $editing=false);</font>
 
| Returns String with formatted html code detailing what the plugin looks like in the view
 
| Returns String with formatted html code detailing what the plugin looks like in the view
 
|-
 
|-
| <span><font face="Courier New">public static abstract function artefactchooser_element($default=null)</font></span>
+
| <font face="Courier New">public static abstract function artefactchooser_element($default=null)</font>
 
| Combines artefact to blocktype
 
| Combines artefact to blocktype
 
|-
 
|-
| <span><font face="Courier New">public static function delete_instance(BlockInstance $instance) { }</font></span>
+
| <font face="Courier New">public static function delete_instance(BlockInstance $instance) { }</font>
 
|
 
|
 
|-
 
|-
| <span><font face="Courier New">public static function instance_config_form(BlockInstance $instance) {}</font></span>
+
| <font face="Courier New">public static function instance_config_form(BlockInstance $instance) {}</font>
 
| This function must be implemented in the subclass if it has config
 
| This function must be implemented in the subclass if it has config
 
|-
 
|-
| <span><font face="Courier New">public static function instance_config_validate(Pieform $form, $values) { }</font></span>
+
| <font face="Courier New">public static function instance_config_validate(Pieform $form, $values) { }</font>
 
| Blocktype plugins can implement this to perform custom pieform validation, should they need it
 
| Blocktype plugins can implement this to perform custom pieform validation, should they need it
 
|-
 
|-
| <span><font face="Courier New">public static function get_artefacts(BlockInstance $instance) { }</font></span>
+
| <font face="Courier New">public static function get_artefacts(BlockInstance $instance) { }</font>
 
|
 
|
 
Most blocktype plugins will attach to artefacts. They should implement this function to keep a list of which ones. The result of this method is used to populate the view_artefact table, and thus decide whether an artefact is in a view for the purposes of access.See {'''@link''' artefact_in_view} for more information about this. Note that it should just handle top level artefacts. The cache rebuilder will figure out the children.
 
Most blocktype plugins will attach to artefacts. They should implement this function to keep a list of which ones. The result of this method is used to populate the view_artefact table, and thus decide whether an artefact is in a view for the purposes of access.See {'''@link''' artefact_in_view} for more information about this. Note that it should just handle top level artefacts. The cache rebuilder will figure out the children.
 +
 
* '''@return''' array ids of artefacts in this block instance
 
* '''@return''' array ids of artefacts in this block instance
 
|}
 
|}
Line 178: Line 186:
 
</div></div><div id="section_9">
 
</div></div><div id="section_9">
  
=== Database tables and XMLDB (db/ -folder) ===
+
===Database tables and XMLDB (db/ -folder)===
  
The database tables in Mahara are created and handled by XMLDB, which should be familiar to moodle developers. Each plugin gets its own<span><font face="Courier New"> install.xml </font></span>and <span><font face="Courier New">upgrade.php</font></span>, as well as their own <span><font face="Courier New">version.php</font></span>. The functions of the files are as follows: <br />
+
The database tables in Mahara are created and handled by XMLDB, which should be familiar to moodle developers. Each plugin gets its own<font face="Courier New"> install.xml </font>and <font face="Courier New">upgrade.php</font>, as well as their own <font face="Courier New">version.php</font>. The functions of the files are as follows: <br />
  
* <span><font face="Courier New">install.xml</font></span> - Mappings/Definitions for database tables and connections
+
* <font face="Courier New">install.xml</font> - Mappings/Definitions for database tables and connections
* <span><font face="Courier New">upgrade.php</font></span> - Used to make checks for changes in the version of the plugin. Needed when old versions of the plugin/blocktype must be upgraded. When upgrade.php is loaded, version.php is automatically read to get the latest version of the plugin.
+
* <font face="Courier New">upgrade.php</font> - Used to make checks for changes in the version of the plugin. Needed when old versions of the plugin/blocktype must be upgraded. When upgrade.php is loaded, version.php is automatically read to get the latest version of the plugin.
  
 
To learn more about XMLDB, please refer to the [http://docs.moodle.org/en/Development:XMLDB_Documentation moodle documentation of XMLDB] and also the[[Developer Area/Database conventions| Mahara Database Conventions]]. It might also be useful to read an existing plugins databases.
 
To learn more about XMLDB, please refer to the [http://docs.moodle.org/en/Development:XMLDB_Documentation moodle documentation of XMLDB] and also the[[Developer Area/Database conventions| Mahara Database Conventions]]. It might also be useful to read an existing plugins databases.
Line 189: Line 197:
 
</div><div id="section_10">
 
</div><div id="section_10">
  
=== Themes ===
+
===Themes===
  
Plugins often have the need to add their own Dwoo templates - this is done by having a <span><font face="Courier New">theme/default/</font></span> directory and putting templates in it. You can also do this for blocktypes within the artefact plugin. Dwoo templates are derivative of older Smarty templates. To learn more, please read [[Developer Area/Core Subsystems/Page Title|the adjacent article here]].
+
Plugins often have the need to add their own Dwoo templates - this is done by having a <font face="Courier New">theme/default/</font> directory and putting templates in it. You can also do this for blocktypes within the artefact plugin. Dwoo templates are derivative of older Smarty templates. To learn more, please read [[Developer Area/Core Subsystems/Page Title|the adjacent article here]].
  
 
</div><div id="section_11">
 
</div><div id="section_11">
  
=== Language strings ===
+
===Language strings===
  
 
For all strings in your artefact plugin, you must use:
 
For all strings in your artefact plugin, you must use:
Line 203: Line 211:
 
<code style="background-color: #cccccc">get_string('mystring', 'blocktype.myplugin/theblockname'); </code>
 
<code style="background-color: #cccccc">get_string('mystring', 'blocktype.myplugin/theblockname'); </code>
  
You can place the strings inside <span><font face="Courier New">artefact/myplugin/lang/en.utf8/artefact.myplugin.php</font></span> and <span><font face="Courier New">artefact/myplugin/blocktype/theblockname/lang/en.utf8/blocktype.theblockname.php</font></span> .To learn more about language packs and translations, please refer to this article: [[Developer Area/Language Packs/Structure|Language Packs -&gt; Structure ]]<br /><br /> An example of a string file looks like the following:<br />
+
You can place the strings inside <font face="Courier New">artefact/myplugin/lang/en.utf8/artefact.myplugin.php</font> and <font face="Courier New">artefact/myplugin/blocktype/theblockname/lang/en.utf8/blocktype.theblockname.php</font> .To learn more about language packs and translations, please refer to this article: [[Developer Area/Language Packs/Structure|Language Packs -&gt; Structure ]]<br /><br /> An example of a string file looks like the following:<br />
 
 
<code style="background-color: #cccccc">defined('INTERNAL') || die();<br /><br /> $string['TestName'] = '</code>
 
 
 
Testname works!
 
  
';<br /> $string['MenuItemString'] = 'MyPlugin!';<br /> $string['IndexPageString'] = 'This is the index page. This string is fetched from the lang file of the plugin.';<br /></div><div id="section_12">
+
<code style="background-color: #cccccc">defined('INTERNAL') || die();<br /><br /> $string['TestName'] = 'Testname works!';
 +
$string['MenuItemString'] = 'MyPlugin!';<br /> $string['IndexPageString'] = 'This is the index page. This string is fetched from the lang file of the plugin.';<br />
 +
</code>
  
=== Cron jobs ===
+
===Cron jobs===
  
If your plug-in has tasks that need to be done regularly, you can instate a cron job to achieve that. Thanks to the embedded cron system in mahara, this is achieved relatively simply by overriding the<span><font face="Courier New"> get_cron()</font></span> function and returning an array detailing the cron job. An example of this functionality would be:
+
If your plug-in has tasks that need to be done regularly, you can instate a cron job to achieve that. Thanks to the embedded cron system in mahara, this is achieved relatively simply by overriding the<font face="Courier New"> get_cron()</font> function and returning an array detailing the cron job. An example of this functionality would be:
  
 
<code style="background-color: #cccccc">public static function get_cron() {<br /> return array(<br /> (object)array(<br /> 'callfunction' =&gt; 'clean_email_validations',<br /> 'hour' =&gt; '4',<br /> 'minute' =&gt; '10',<br /> ),<br /> );<br /> }<br /><br /> public static function clean_email_validations() {<br /> //do something here<br /> }<br /></code>
 
<code style="background-color: #cccccc">public static function get_cron() {<br /> return array(<br /> (object)array(<br /> 'callfunction' =&gt; 'clean_email_validations',<br /> 'hour' =&gt; '4',<br /> 'minute' =&gt; '10',<br /> ),<br /> );<br /> }<br /><br /> public static function clean_email_validations() {<br /> //do something here<br /> }<br /></code>
Line 219: Line 225:
 
</div><div id="section_13">
 
</div><div id="section_13">
  
=== Help pages ===
+
===Help pages===
  
 
Help files can be in three differently named folders:
 
Help files can be in three differently named folders:
Line 225: Line 231:
 
<div id="section_14">
 
<div id="section_14">
  
==== Forms(Artefact plugin): ====
+
====Forms(Artefact plugin):====
  
These help files can be used from within the classes in an artefact plugins lib.php.<br /> Name format: '''''class_name.element_name.html<br />'''''Example name: <span><font face="Courier New">mytype.date.html</font></span> OR <span><font face="Courier New">mypieform.date.html</font></span><br /> Example usage:<br />
+
These help files can be used from within the classes in an artefact plugins lib.php.<br /> Name format: '''''class_name.element_name.html<br />'''''Example name: <font face="Courier New">mytype.date.html</font> OR <font face="Courier New">mypieform.date.html</font><br /> Example usage:<br />
  
 
<code style="background-color: #cccccc">class ArtefactTypeMyType extends ArtefactTypeMyPluginComposite {<br /> OR<br /> $form = pieform(array(<br /> 'name' =&gt; 'MyPieform',<br /> //...</code><code style="background-color: #cccccc">'date' =&gt; array(<br /> 'type' =&gt; 'text',<br /> 'rules' =&gt; array(<br /> 'required' =&gt; true,<br /> ),<br /> 'title' =&gt; get_string('date', 'artefact.myplugin'),<br /> 'help' =&gt; true,<br /> 'size' =&gt; 20,<br /> )<br /></code>
 
<code style="background-color: #cccccc">class ArtefactTypeMyType extends ArtefactTypeMyPluginComposite {<br /> OR<br /> $form = pieform(array(<br /> 'name' =&gt; 'MyPieform',<br /> //...</code><code style="background-color: #cccccc">'date' =&gt; array(<br /> 'type' =&gt; 'text',<br /> 'rules' =&gt; array(<br /> 'required' =&gt; true,<br /> ),<br /> 'title' =&gt; get_string('date', 'artefact.myplugin'),<br /> 'help' =&gt; true,<br /> 'size' =&gt; 20,<br /> )<br /></code>
Line 233: Line 239:
 
</div><div id="section_15">
 
</div><div id="section_15">
  
==== Forms(Blocktype plugin): ====
+
====Forms(Blocktype plugin):====
  
These help files can be used from within the<span><font face="Courier New"> instance_config_form()</font></span> function<br /> Name format: '''''instconf.element_name.html<br />'''''Example name:<span><font face="Courier New"> addbook.html<br /></font></span>Example usage:<br />
+
These help files can be used from within the<font face="Courier New"> instance_config_form()</font> function<br /> Name format: '''''instconf.element_name.html<br />'''''Example name:<font face="Courier New"> addbook.html<br /></font>Example usage:<br />
  
 
<code style="background-color: #cccccc">return array( <br /> 'width' =&gt; array( <br /> 'type' =&gt; 'text', <br /> 'title' =&gt; get_string('width','blocktype.myplugin/myblocktype'), <br /> 'size' =&gt; 3, <br /> 'rules' =&gt; array( <br /> 'required' =&gt; true, <br /> 'integer' =&gt; true, <br /> ), <br /> 'defaultvalue' =&gt; (empty($configdata['width']) ? $configdata['width'] : self::$default_width), <br /> 'help' =&gt; true, <br /> )<br /> );<br /></code>
 
<code style="background-color: #cccccc">return array( <br /> 'width' =&gt; array( <br /> 'type' =&gt; 'text', <br /> 'title' =&gt; get_string('width','blocktype.myplugin/myblocktype'), <br /> 'size' =&gt; 3, <br /> 'rules' =&gt; array( <br /> 'required' =&gt; true, <br /> 'integer' =&gt; true, <br /> ), <br /> 'defaultvalue' =&gt; (empty($configdata['width']) ? $configdata['width'] : self::$default_width), <br /> 'help' =&gt; true, <br /> )<br /> );<br /></code>
Line 241: Line 247:
 
</div><div id="section_16">
 
</div><div id="section_16">
  
==== Pages: ====
+
====Pages:====
  
These help files are just named after the page they are used in. If the page name is index, then the index page will have the help beside its heading automatically.<br /> Name format: '''''page_name.html<br />'''''Example name: <span><font face="Courier New">index.html</font></span><br />
+
These help files are just named after the page they are used in. If the page name is index, then the index page will have the help beside its heading automatically.<br /> Name format: '''''page_name.html<br />'''''Example name: <font face="Courier New">index.html</font><br />
  
 
</div><div id="section_17">
 
</div><div id="section_17">
  
==== Sections: ====
+
====Sections:====
  
These help files can be used from within the *.tpl files in theme folder. Or in some case, from a pieform.<br /> Name format: '''''section_name.html<br />'''''Example name: <span><font face="Courier New">example.html<br /></font></span>Example usage:<br />
+
These help files can be used from within the *.tpl files in theme folder. Or in some case, from a pieform.<br /> Name format: '''''section_name.html<br />'''''Example name: <font face="Courier New">example.html<br /></font>Example usage:<br />
  
 
<code style="background-color: #cccccc">{contextualhelp plugintype='artefact' pluginname='myplugin' section='example'}</code>
 
<code style="background-color: #cccccc">{contextualhelp plugintype='artefact' pluginname='myplugin' section='example'}</code>
Line 255: Line 261:
 
</div><div id="section_18">
 
</div><div id="section_18">
  
==== Usage from a pieform array: ====
+
====Usage from a pieform array:====
  
You can set a browsehelp for a file browser element(used when uploading files into Mahara) in a pieform array like this: <span><font face="Courier New">'browsehelp' =&gt; 'browsemyfiles',</font></span><br /> This way the file must be named browsemyfiles.html<br />
+
You can set a browsehelp for a file browser element(used when uploading files into Mahara) in a pieform array like this: <font face="Courier New">'browsehelp' =&gt; 'browsemyfiles',</font><br /> This way the file must be named browsemyfiles.html<br />
  
 
</div></div></div><div id="section_19">
 
</div></div></div><div id="section_19">
  
== Not yet documented ==
+
==Not yet documented==
  
 
Event handling, notifications (see Plugin class), probably more. Add more here! :)
 
Event handling, notifications (see Plugin class), probably more. Add more here! :)
  
 
</div>
 
</div>
 +
 +
===Files===
 +
 +
*[[File:Artefact_plugin_folder_structure.png]]
 +
 +
[[Category:Developer Area]][[Category:Artefact Plugins]][[Category:Plugins]]

Latest revision as of 00:52, 11 November 2015

Mahara's basic funtionality is comprised of Artefacts.

The basic unit of content in Mahara is called an artefact. All sorts of things are artefacts - blog posts & blogs, files, profile information and more. The artefact plugin type allows more to be added to the system, and as such is one of the most interesting plugin types. If you're thinking "I want to add X to the system" where X is something like wikis, calendars, polls etc, then you're probably going to be creating an artefact plugin to provide it.

Artefacts can belong to users, groups, institutions or the site itself. Some artefacts may make sense in the context of one of these but not the others - for example it might not make sense for users to have wikis (or maybe it might!), while it would make more sense for groups.

Basics of an Artefact Plugin

When Thinking about writing a new Artefact plugin, the first step is to realise that they are comprised of several different parts. There are some required items every artefact plugin must include. For the purposes of this document we're going to assume you're writing a new artefact plugin called 'Myplugin'.

The first step is to create the required file structure by making a new directory under htdocs/artefact/myplugin. This folder will contain all of your files and items, and the basic structure is as follows:

  • lib.php - Contains the class that implements the functionality of your Artefact. This is the main controller, and it must extend the abstract class PluginArtefact.
  • version.php - contains version information about the artefact.
  • index.php - should your plugin contain content that is manipulated by the user, this file contains the functions necessary to show them.
  • /theme -folder. This contains all of the Template files of your artefact, as well as all of the CSS and images needed in your plugin. You can also have multiple themes for your artefact. The default theme is always created under /theme/raw, but you can also create new themes by placing them in new folders under /theme. Read more about templates from their own article
  • /db -folder. This folder contains two files that define the database structure of your plugin.
    • install.xml - An xml-file that defines the structure of your database according to the built-in XMLDB definition.
    • upgrade.php - Used to make checks for changes in the version of the plugin/blocktype. Needed when old versions of the plugin/blocktype must be upgraded.
  • /lang -folder. Localization files for you artefact. Contains translations for strings used in the artefact under their own folder.
  • /blocktype -folder. If your artefacts make use of any blocktypes, they will go under here. Refer to the blocktype documentation to learn more about them.

Attached to this page is also an image illustrating this hierarchy

lib.php

This file is the backbone of the whole plugin, and the most logical starting point. The first thing you must do when creating this file is write a Plugin subclass -' PluginArtefactMyplugin extends PluginArtefac't. Read the phpdocs for the Plugin base class in lib/mahara.php, and PluginArtefact in artefact/lib.php to see exactly what all the methods are. Any methods you must implement will always be abstract. This it what a bare-essential class looks like:

defined('INTERNAL') || die();

require_once('activity.php');

class PluginArtefactMyPlugin extends PluginArtefact {

public static function get_artefact_types() {
return array(
'MyPlugin',
);
}

public static function get_block_types() {
return array();
}

public static function get_plugin_name() {
return 'MyPlugin';
}

public static function menu_items() {
return array(
array(
'path' => 'myportfolio/myplugin',
'url' => 'artefact/myplugin/',
'title' => get_string('MenuItemString', 'artefact.myplugin'),
'weight' => 20,
),
);
}
}


class ArtefactTypeMyPlugin extends ArtefactType {
public function render_self($options) {
return get_string('TestName', 'artefact.myplugin');
}

public static function get_icon($options=null) {}

public static function is_singular() {
return false;
}

public static function get_links($id) {}
}

The main two methods in this class you must implement are get_artefact_types and get_blocktypes. Below you will find a table to be used as a cheat sheet that contains all of the abstract methods, taken from lib/mahara.php and artefact/lib.php with their phpdoc.

Artefact Types

Artefact plugins are made up of any number of artefact types that behave slightly differently, but are related. For example, the file plugin contains three artefact types - file, folder, and image, that have slightly different properties. The blog plugin contains blog and blogpost. As blogpost is a child of blog, file and image are children of folder as well (in a logical sense, rather than in php).

Artefact plugins may also contain blocktype plugins. Blocks are how artefacts get into views, and it's really just presentation information with some configuration.

For your plugin, you tell Mahara which blocktypes and artefact types you're implementing in the above functions, and then you must write a class for each. More on embedded blocktypes later on in this documentation. Please also see the Blocktype documentation elsewhere in the wiki.

ArtefactType subclasses

For each artefact type that PluginArtefactMyplugin::get_artefact_types returns, you must write a class that subclasses ArtefactType. Again, the best way to understand all the methods in the class is to read the phpdocs for the parent class, in artefact/lib.php. Also, the methods you must implement are abstract again.

Abstract functions cheat sheets:

Listed below are the abstract functions of the parent classes that you absolutely must implement in your lib.php, if you extend said classes. Keep in mind that these are by no means the only functions you will need to override. They are listed here as a quick cheat sheet to get you going faster.

Abstract class PluginArtefact extends Plugin PHPDoc for the functions
public static abstract function get_artefact_types()

This function returns a list of classnames of artefact types this plugin provides.

  • @return array
public static abstract function get_block_types()

This function returns a list of classnames of block types this plugin provides they must match directories inside artefact/$name/blocktype

  • @abstract
  • @return array
public static abstract function get_plugin_name()

This function returns the name of the plugin.

  • @return string
Abstract class ArtefactType PHPDoc for the functions
public static abstract function get_icon($options=null)

Returns a URL for an icon for the appropriate artefact.

  • @param array $options Options for the artefact. The array MUST have the 'id' key, representing the ID of the artefact for which the icon is being generated. Other keys include 'size' for a [width]x[height] version of the icon, as opposed to the default 20x20, and 'view' for the id of the view in which the icon is being displayed.
  • @return string URL for the icon
public static abstract function is_singular() Whether a user will have exactly 0 or 1 of this artefact type.
public static abstract function get_links($id)

Returns a list of key => value pairs where the key is either '_default' or a langauge string, and value is a URL linking to that behaviour for this artefact type

  • @param integer This is the ID of the artefact being linked to

There are also some other very commonly used functions. The best way to learn what to use is of course to read the code of existing plugins, but here's a listing of some of them:

Other common functions found in lib.php Description
menu_items()
get_event_subscriptions()
get_activity_types()
postinst($prevversion)
view_export_extra_artefacts($viewids)
get_config(' root_name ') Used to get some folder location(for example 'docroot' returns location of the mahara folder on the local disk(/var/www/mahara) and 'wwwroot' returns url of the mahara folder in the www directory(http://localhost/mahara))
get_cron() Used to create new cron jobs from within the plugins (read more in cron section)
artefact_export_extra_artefacts($artefactids)

index.php

Should your artefact plugin be visible to your users, you must also include an index.php in your plug-in. This is the controller file that leads up to showing the user your views from the /theme -folder. Here is an example of an index.php:

define('INTERNAL', 1);
define('MENUITEM', 'myportfolio/myplugin');
define('SECTION_PLUGINTYPE', 'artefact');
define('SECTION_PLUGINNAME', 'myplugin');
define('SECTION_PAGE', 'index');

require(dirname(dirname(dirname(FILE))) . '/init.php');
define('TITLE', get_string('MenuItemString', 'artefact.myplugin'));

$indexstring = get_string('IndexPageString', 'artefact.myplugin');

$smarty = smarty();
$smarty->assign('indexstring', $indexstring);
$smarty->display('artefact:myplugin:index.tpl');

Blocktypes

For each block type that PluginArtefactMyplugin::get_block_types returns, you must do the following: 

Create artefact/myplugin/blocktype/theblockname/lib.php and write a class in it: PluginBlocktypeTheblockname extends PluginBlocktype. Again, all required methods are abstract and the best way to learn about this is to read the parent class.

PluginBlocktype Abstract cheat sheet

Listed in this cheat sheet are the abstract functions you need to implement in each class. Also listed are some other commonly found overriden functions.

Abstract class PluginBlocktype PHPDoc for the functions
public static abstract function get_title();

If this blocktype contains artefacts, and uses the artefactchooser Pieform element to choose them, this method must return the definition for the element. This is used in view/artefactchooser.json.php to build pagination for the element. The element returned MUST have the name key set to either 'artefactid' or 'artefactids', depending on whether 'selectone' is true or false. The element must also have the 'blocktype' key set to the name of the blocktype that the form is for.

  • @param mixed $default The default value for the element
public static abstract function get_description();

subclasses can override this if they need to do something a bit special eg more than just what the BlockInstance??->delete function does.

  • @param BlockInstance $instance
public static abstract function get_categories(); Returns array which specifies the categories where the blocktype resides in the view creator. Possbile options: feeds, fileimagevideo, general, internal, resume
public static abstract function render_instance(BlockInstance $instance, $editing=false); Returns String with formatted html code detailing what the plugin looks like in the view
public static abstract function artefactchooser_element($default=null) Combines artefact to blocktype
public static function delete_instance(BlockInstance $instance) { }
public static function instance_config_form(BlockInstance $instance) {} This function must be implemented in the subclass if it has config
public static function instance_config_validate(Pieform $form, $values) { } Blocktype plugins can implement this to perform custom pieform validation, should they need it
public static function get_artefacts(BlockInstance $instance) { }

Most blocktype plugins will attach to artefacts. They should implement this function to keep a list of which ones. The result of this method is used to populate the view_artefact table, and thus decide whether an artefact is in a view for the purposes of access.See {@link artefact_in_view} for more information about this. Note that it should just handle top level artefacts. The cache rebuilder will figure out the children.

  • @return array ids of artefacts in this block instance

Database tables and XMLDB (db/ -folder)

The database tables in Mahara are created and handled by XMLDB, which should be familiar to moodle developers. Each plugin gets its own install.xml and upgrade.php, as well as their own version.php. The functions of the files are as follows: 

  • install.xml - Mappings/Definitions for database tables and connections
  • upgrade.php - Used to make checks for changes in the version of the plugin. Needed when old versions of the plugin/blocktype must be upgraded. When upgrade.php is loaded, version.php is automatically read to get the latest version of the plugin.

To learn more about XMLDB, please refer to the moodle documentation of XMLDB and also the Mahara Database Conventions. It might also be useful to read an existing plugins databases.

Themes

Plugins often have the need to add their own Dwoo templates - this is done by having a theme/default/ directory and putting templates in it. You can also do this for blocktypes within the artefact plugin. Dwoo templates are derivative of older Smarty templates. To learn more, please read the adjacent article here.

Language strings

For all strings in your artefact plugin, you must use:

get_string('mystringkey', 'artefact_myplugin'); //or

get_string('mystring', 'blocktype.myplugin/theblockname');

You can place the strings inside artefact/myplugin/lang/en.utf8/artefact.myplugin.php and artefact/myplugin/blocktype/theblockname/lang/en.utf8/blocktype.theblockname.php .To learn more about language packs and translations, please refer to this article: Language Packs -> Structure

An example of a string file looks like the following:

defined('INTERNAL') || die();

$string['TestName'] = 'Testname works!'; $string['MenuItemString'] = 'MyPlugin!';
$string['IndexPageString'] = 'This is the index page. This string is fetched from the lang file of the plugin.';

Cron jobs

If your plug-in has tasks that need to be done regularly, you can instate a cron job to achieve that. Thanks to the embedded cron system in mahara, this is achieved relatively simply by overriding the get_cron() function and returning an array detailing the cron job. An example of this functionality would be:

public static function get_cron() {
return array(
(object)array(
'callfunction' => 'clean_email_validations',
'hour' => '4',
'minute' => '10',
),
);
}

public static function clean_email_validations() {
//do something here
}

Help pages

Help files can be in three differently named folders:

Forms(Artefact plugin):

These help files can be used from within the classes in an artefact plugins lib.php.
Name format: class_name.element_name.html
Example name: mytype.date.html OR mypieform.date.html
Example usage:

class ArtefactTypeMyType extends ArtefactTypeMyPluginComposite {
OR
$form = pieform(array(
'name' => 'MyPieform',
//...
'date' => array(
'type' => 'text',
'rules' => array(
'required' => true,
),
'title' => get_string('date', 'artefact.myplugin'),
'help' => true,
'size' => 20,
)

Forms(Blocktype plugin):

These help files can be used from within the instance_config_form() function
Name format: instconf.element_name.html
Example name: addbook.html
Example usage:

return array(
'width' => array(
'type' => 'text',
'title' => get_string('width','blocktype.myplugin/myblocktype'),
'size' => 3,
'rules' => array(
'required' => true,
'integer' => true,
),
'defaultvalue' => (empty($configdata['width']) ? $configdata['width'] : self::$default_width),
'help' => true,
)
);

Pages:

These help files are just named after the page they are used in. If the page name is index, then the index page will have the help beside its heading automatically.
Name format: page_name.html
Example name: index.html

Sections:

These help files can be used from within the *.tpl files in theme folder. Or in some case, from a pieform.
Name format: section_name.html
Example name: example.html
Example usage:

{contextualhelp plugintype='artefact' pluginname='myplugin' section='example'}

Usage from a pieform array:

You can set a browsehelp for a file browser element(used when uploading files into Mahara) in a pieform array like this: 'browsehelp' => 'browsemyfiles',
This way the file must be named browsemyfiles.html

Not yet documented

Event handling, notifications (see Plugin class), probably more. Add more here! :)

Files

  • Artefact plugin folder structure.png