<?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=Markn86</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=Markn86"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Markn86"/>
	<updated>2026-04-13T15:18:31Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=How_to_contribute_a_web_service_function_to_core&amp;diff=36841</id>
		<title>How to contribute a web service function to core</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=How_to_contribute_a_web_service_function_to_core&amp;diff=36841"/>
		<updated>2012-12-10T05:03:37Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Check the existing ==&lt;br /&gt;
Before creating a new issue, check if one of the [https://docs.moodle.org/dev/Web_services_Roadmap#Core_web_service_functions core functions] or [http://tracker.moodle.org/browse/MDL-29934 a function in the roadmap] already matches your need.&lt;br /&gt;
&lt;br /&gt;
==Create a tracker issue ==&lt;br /&gt;
Create a new feature issue in the tracker for your new web service function (it is allowed to create one issue for many function only if all functions are deeply related and that all core lib functions exist like  for MDL-32662). The issue title should be the [https://docs.moodle.org/dev/Web_services_Roadmap#Naming_convention web service function name], and the issue description should indicate the specs. The following is an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
This web service function will return assignments:&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
----------&lt;br /&gt;
&lt;br /&gt;
array of course ids - Default: empty array&lt;br /&gt;
array of capabilities - Default: empty array&lt;br /&gt;
&lt;br /&gt;
Return value:&lt;br /&gt;
-----------&lt;br /&gt;
&lt;br /&gt;
array of [&lt;br /&gt;
    struct{&lt;br /&gt;
        course struct [id, fullname, shortname, timemodified]&lt;br /&gt;
        array of assignment [id,name,timedue,grade,timemodified]&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Keep the following in mind.&lt;br /&gt;
* The web service API is designed to be a clean set of functions with very little overlap.  Each web service function should return minimal required information - sometimes ids are enough.  We expect the client/external app to manage some local storage between calls.  For example, an external app will always retrieve the courses information first. Any function down the app workflow, only needs to return course ids. The external app should already know course fullname, shortname...&lt;br /&gt;
* Avoid functions that are too specific - look for the most general possible case.  For example, we don&#039;t need a set_this_field function when a generic update_object could do it.  This is to avoid code duplication and long-term maintenance.&lt;br /&gt;
* Moodle contextids are generally internal to Moodle and are not used in the API.  (This was [http://tracker.moodle.org/browse/MDL-31681 discussed in this issue]).&lt;br /&gt;
* web service function name should be: create, update, get, and delete. Avoid as much as possible add, set, remove...&lt;br /&gt;
* description/summary/textfields are always accompanied by a format field.  On input: texts should be checked against PARAM_RAW. You must not use format_text(). On output textfields must use external_format_text(). Example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
//INPUT in xxx_parameters()&lt;br /&gt;
&#039;inputtextaera&#039; =&amp;gt; new external_value(PARAM_RAW, &#039;some html param&#039;),&lt;br /&gt;
&#039;inputtextareaformat&#039; =&amp;gt; new external_format_value(&#039;inputtextarea&#039;, VALUE_DEFAULT), // VALUE_DEFAULT has for default format FORMAT_HTML. If not mention VALUE_REQUIRED is used.&lt;br /&gt;
&lt;br /&gt;
//INPUT in xxx() &lt;br /&gt;
// no format_text() =&amp;gt; just store it in the DB&lt;br /&gt;
$params[&#039;inputtextareaformat&#039;] = external_validate_format($params[&#039;inputtextareaformat&#039;]);&lt;br /&gt;
&lt;br /&gt;
//OUTPUT in xxx()&lt;br /&gt;
list($text, $textformat) = external_format_text($text, $textformatfromDB, $contextid, $component, $filearea, $itemid);&lt;br /&gt;
               &lt;br /&gt;
//OUTPUT in xxx_returns()                &lt;br /&gt;
&#039;text&#039; =&amp;gt; new external_value(PARAM_RAW, &#039;formatted text&#039;),&lt;br /&gt;
&#039;textformat&#039; =&amp;gt; new external_format_value(&#039;text&#039;),&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Add the watchers ===&lt;br /&gt;
Add [https://docs.moodle.org/dev/Credits#Component_maintainers the module maintainer] as watcher on your issue. In most of the case, they will be the person to validate the proposal.&lt;br /&gt;
&lt;br /&gt;
=== Link the issue ===&lt;br /&gt;
Link your issue to [http://tracker.moodle.org/browse/MDL-29934 the Web service API Roadmap]. Your issue should appear in the &amp;quot;has been marked as being related by:&amp;quot; section.&lt;br /&gt;
&lt;br /&gt;
=== Agreement on the specs ===&lt;br /&gt;
Once the component leader agrees on the specs for a web service function, the web service function is placed as a subtask in the roadmap.&lt;br /&gt;
&lt;br /&gt;
== Function implementation  ==&lt;br /&gt;
Implement the function according to the specs. The implementation must follow all of the below sections.&lt;br /&gt;
&lt;br /&gt;
=== Code logic ===&lt;br /&gt;
The code logic should be matching the logic in Moodle. In the best word you will only call a core lib function in Moodle and reproduce some required capabilities/context checkings (search for the core lib function in Moodle, you&#039;ll find the required checks). &lt;br /&gt;
&lt;br /&gt;
However often a lib function doesn&#039;t exist and you need to reproduce the code logic from different scripts in Moodle. If you end up to create all this logic in your function, it&#039;s better to move all this new logic in a new lib function. Then create a tracker issue and indicates to update the scripts using your new generic lib function.&lt;br /&gt;
&lt;br /&gt;
Note that if your web service function does something different from Moodle core, it may be either a feature missing from Moodle (must be implemented at the same time), either something that the function should not be doing (review your web service function specification).&lt;br /&gt;
&lt;br /&gt;
=== File structure ===&lt;br /&gt;
The file structure is explained in the [[Web_services_API|Web services API]] and the [[External_functions_API|External function API]]. These are plugin example but they are easy to adapt to core. The easiest way to learn is to look at other functions in the Moodle code.&lt;br /&gt;
&lt;br /&gt;
=== Capabilities and context checks ===&lt;br /&gt;
The capability checking should always match the capability checks used in the front-end. You must look for the file(s) where this capibility checks are used.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/// capability and context checking of core_group_create_groups&lt;br /&gt;
$context = get_context_instance(CONTEXT_COURSE, $group-&amp;gt;courseid);&lt;br /&gt;
self::validate_context($context);&lt;br /&gt;
require_capability(&#039;moodle/course:managegroups&#039;, $context);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You also need to comment in the tracker issue about which file in core contains the permission/security checkings.  Your web service function code must correspond 100% with Moodle permissions and behaviours - it is the most difficult part of the function implementation as the code logic could be in many different files. You will save reviewers a lot of time by letting them know which file to look at.  Usually it&#039;s a form script + a page script in the UI, and sometimes in other places like admin pages.&lt;br /&gt;
&lt;br /&gt;
Note: in services.php you&#039;ll find out that you can set a &#039;requiredcapabilities&#039; settings for each web service function declaration. This is just a text help for the administrator. Moodle servers do not do any automaticcally check these capibilities. This is due to the fact that capability checks require a specific context, so you need to implement these checks in your external function.&lt;br /&gt;
&lt;br /&gt;
=== Documentation for the client developer ===&lt;br /&gt;
written complete documentation in the xxx_params() and xxx_return() external description functions. [https://docs.moodle.org/22/en/Web_services_FAQ#Where_is_the_Web_Service_API_documented.3F The generated API documentation] will only show to client developers information from these two functions and in the services.php file. Be concise about how to use the function.&lt;br /&gt;
&lt;br /&gt;
=== Web service description functions ===&lt;br /&gt;
* set top level parameters as DEFAULT (don&#039;t use OPTIONAL)&lt;br /&gt;
=== Error handling ===&lt;br /&gt;
* handled errors as described [https://docs.moodle.org/dev/Errors_handling_in_web_services in this document]&lt;br /&gt;
* DB write functions need to support transactions ($transaction = $DB-&amp;gt;start_delegated_transaction(); / $transaction-&amp;gt;allow_commit();)&lt;br /&gt;
&lt;br /&gt;
=== Proper format and coding style ===&lt;br /&gt;
* ordered the functions: 1) xxx_params() 2) xxx() 3) xxx_returns() (so the integrator is not marked as the last history committer in Git for the functions)&lt;br /&gt;
* run the [https://github.com/marinaglancy/moodle-local_moodlecheck moodlecheck]/[https://github.com/moodlehq/moodle-local_codechecker codechecker] on your modified file to check if you code match Moodle standard.&lt;br /&gt;
* follow [https://docs.moodle.org/dev/Coding_style Moodle coding style]&lt;br /&gt;
&lt;br /&gt;
=== Unit tests ===&lt;br /&gt;
You &#039;&#039;&#039;must&#039;&#039;&#039; write a [[Web Services Unit Test]]&lt;br /&gt;
&lt;br /&gt;
== Peer-review ==&lt;br /&gt;
You can now be peer-reviewed. Push your function in a Github branch named MDL-XXXX. Remember:&lt;br /&gt;
* only make one commit if you are the only contributor. &lt;br /&gt;
* do not modify lines not related to your issue. For example with Netbeans you can for example &amp;quot;Format&amp;quot; the entire file to make the code prettier.  If the file contains some existing code, It is not a good idea because you would be &amp;quot;git blame&amp;quot; for all lines in the files. For reviewer, it&#039;s also much more difficult to know what was related to the MDL issue. &lt;br /&gt;
* fill up the test instruction of the MDL issue. It should be online, the phpunit command line to run the PHPunit test. A tester will run it after the integration process is finished. Only after this final test, the function will be available in Moodle releases.&lt;br /&gt;
&lt;br /&gt;
Peer-reviews are done by the component maintainer (if you are the component maintainer, then you can pick your peer-reviewer). If there are no component maintainer (or if the component maintainer is not available) the peer-review should be assigned to moodle.com. Peer-reviewer can get help from the [[Peer reviewing checklist]].&lt;br /&gt;
&lt;br /&gt;
== Integration ==&lt;br /&gt;
Integration / Moodle HQ development priority follows these rules:&lt;br /&gt;
&lt;br /&gt;
# the web service functions required for the official Mobile app (generally very few);&lt;br /&gt;
# the web service functions for which a Git patch has been submitted;&lt;br /&gt;
# [http://tracker.moodle.org/secure/IssueNavigator.jspa?mode=hide&amp;amp;requestId=13101 the most voted issues]; and then&lt;br /&gt;
# other web service functions.&lt;br /&gt;
&lt;br /&gt;
[[Category:Web_Services]]&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=36373</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=36373"/>
		<updated>2012-11-15T09:00:30Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* upgrade.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabilities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the [[XMLDB_editor]]. Your module should always have a table with the same name as the module with the fields id, name and course as shown above.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the creator of the certificate has chosen to display the code on the certificate and another to store the actual code for each student. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the [[XMLDB_editor]] to change the install.xml file AND create the upgrade path.&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;certificate&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 16 * 16. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Update:&#039;&#039;&#039; Since 2.4 SVG files were introduced with all core Moodle activities. Please see [[Moodle_icons_2.4]] for more details on this.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;modname&amp;gt;_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The &amp;lt;modname&amp;gt;_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The &amp;lt;modname&amp;gt;_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders its page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=36372</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=36372"/>
		<updated>2012-11-15T08:59:04Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Lang Folder */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabilities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the [[XMLDB_editor]]. Your module should always have a table with the same name as the module with the fields id, name and course as shown above.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the [[XMLDB_editor]] to change the install.xml file AND create the upgrade path.&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;certificate&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 16 * 16. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Update:&#039;&#039;&#039; Since 2.4 SVG files were introduced with all core Moodle activities. Please see [[Moodle_icons_2.4]] for more details on this.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;modname&amp;gt;_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The &amp;lt;modname&amp;gt;_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The &amp;lt;modname&amp;gt;_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders its page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=36371</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=36371"/>
		<updated>2012-11-15T08:58:45Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Pix folder */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabilities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the [[XMLDB_editor]]. Your module should always have a table with the same name as the module with the fields id, name and course as shown above.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the [[XMLDB_editor]] to change the install.xml file AND create the upgrade path.&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 16 * 16. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Update:&#039;&#039;&#039; Since 2.4 SVG files were introduced with all core Moodle activities. Please see [[Moodle_icons_2.4]] for more details on this.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;modname&amp;gt;_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The &amp;lt;modname&amp;gt;_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The &amp;lt;modname&amp;gt;_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders its page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=36367</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=36367"/>
		<updated>2012-11-15T06:40:37Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* lang/en/block_simplehtml.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039; A Step-by-step Guide To Creating Blocks &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Original Author: Jon Papaioannou ([mailto:pj@moodle.org pj@moodle.org])&lt;br /&gt;
&lt;br /&gt;
Updated to Moodle 2.0 and above by: Greg J Preece ([mailto:greg.preece@blackboard.com greg.preece@blackboard.com])&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
The present document serves as a guide to developers who want to create their own blocks for use in Moodle. It applies to the 2.0 development version of Moodle (and any newer) &#039;&#039;&#039;only&#039;&#039;&#039;, as the blocks API changed significantly enough to warrant new documentation. Those wishing to read the old tutorial for Moodles 1.5 to 1.9 can find it under [[Blocks/Blocks for 1.5 to 1.9| Blocks for 1.5 to 1.9]].&lt;br /&gt;
&lt;br /&gt;
The guide is written as an interactive course which aims to develop a configurable, multi-purpose block that displays arbitrary HTML. It&#039;s targeted mainly at people with little experience with Moodle or programming in general and aims to show how easy it is to create new blocks for Moodle. A certain small amount of PHP programming knowledge is still required, though. &lt;br /&gt;
&lt;br /&gt;
Experienced developers and those who just want a &#039;&#039;&#039;programmer&#039;s reference&#039;&#039;&#039; text should refer to [[Blocks/Appendix_A| Appendix A]] because the main guide has a rather low concentration of pure information in the text.&lt;br /&gt;
&lt;br /&gt;
== Basic Concepts ==&lt;br /&gt;
&lt;br /&gt;
Through this guide, we will be following the creation of an &amp;quot;HTML&amp;quot; block from scratch in order to demonstrate most of the block features at our disposal. Our block will be named &amp;quot;SimpleHTML&amp;quot;. This does not constrain us regarding the name of the actual directory on the server where the files for our block will be stored, but for consistency we will follow the practice of using the lowercased form &amp;quot;simplehtml&amp;quot; in any case where such a name is required. &lt;br /&gt;
&lt;br /&gt;
Whenever we refer to a file or directory name which contains &amp;quot;simplehtml&amp;quot;, it&#039;s important to remember that &#039;&#039;only&#039;&#039; the &amp;quot;simplehtml&amp;quot; part is up to us to change; the rest is standardised and essential for Moodle to work correctly.&lt;br /&gt;
&lt;br /&gt;
Whenever a file&#039;s path is mentioned in this guide, it will always start with a slash. This refers to the Moodle home directory; all files and directories will be referred to with respect to that directory.&lt;br /&gt;
&lt;br /&gt;
== Ready, Set, Go! ==&lt;br /&gt;
&lt;br /&gt;
To define a &amp;quot;block&amp;quot; in Moodle, in the most basic case we need to provide just four PHP files. Remember, in this example we are creating a block called &#039;simplehtml&#039;, replace &#039;simplehtml&#039; with the name of your custom block. The four files should be located in blocks/simplehtml and are:&lt;br /&gt;
&lt;br /&gt;
=== block_simplehtml.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold the class definition for the block, and is used both to manage it as a plugin and to render it onscreen.&lt;br /&gt;
&lt;br /&gt;
We start by creating the main object file, &#039;block_simplehtml.php&#039;. We then begin coding the block:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class block_simplehtml extends block_base {&lt;br /&gt;
    public function init() {&lt;br /&gt;
        $this-&amp;gt;title = get_string(&#039;simplehtml&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    // The PHP tag and the curly bracket for the class definition &lt;br /&gt;
    // will only be closed after there is another function added in the next section.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first line is our block class definition; it must be named exactly in the manner shown. Again, only the &amp;quot;simplehtml&amp;quot; part can (and indeed must) change; everything else is standardised.&lt;br /&gt;
&lt;br /&gt;
Our class is then given a small method: [[Blocks/Appendix_A#init.28.29| init()]]. This is essential for all blocks, and its purpose is to give values to any class member variables that need instantiating. &lt;br /&gt;
&lt;br /&gt;
In this very basic example, we only want to set [[Blocks/Appendix_A#.24this-.3Etitle| $this-&amp;gt;title]], which is the title displayed in the header of our block. We can set it to whatever we like; in this case it&#039;s set to read the actual title from the language file mentioned previously, which is then distributed along with the block. I&#039;ll skip ahead a bit here and say that if you want your block to display &#039;&#039;&#039;no&#039;&#039;&#039; title at all, then you should set this to any descriptive value you want (but &#039;&#039;&#039;not&#039;&#039;&#039; make it an empty string). We will later see [[Blocks#Eye_Candy|how to disable the title&#039;s display]].&lt;br /&gt;
&lt;br /&gt;
=== db/access.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold the new capabilities created by the block.&lt;br /&gt;
&lt;br /&gt;
Moodle 2.4 onwards introduced the capabilities addinstance and myaddinstance for core blocks. They were introduced so that it was possible to control the use of individual blocks. These capabilities should also be added to your custom block, so in this case to the file blocks/simplehtml/db/access.php. If your block is not going to be used in the &#039;My Moodle page&#039; (ie, your applicable_formats function (discussed later) has &#039;my&#039; set to false.) then the myaddinstance capability is not required. The following is the capabilities array and how it should look for any new blocks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:myaddinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_SYSTEM,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;user&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/my:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_SPAM | RISK_XSS,&lt;br /&gt;
&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_BLOCK,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/site:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== lang/en/block_simplehtml.php ===&lt;br /&gt;
&lt;br /&gt;
This is the English language file for your block. If you are not an English speaker, you can replace &#039;en&#039; with your appropriate language code. All language files for blocks go under the /lang subfolder of the block&#039;s installation folder.&lt;br /&gt;
&lt;br /&gt;
Moodle 2.0 and above require a name for our plugin to show in the upgrading page. We set this value, along with the capabilities we created and any other language strings we wish to use within the block, in a language package as previously mentioned (the same file where we put our string for the plugin title).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Simple HTML block&#039;;&lt;br /&gt;
$string[&#039;simplehtml&#039;] = &#039;Simple HTML&#039;;&lt;br /&gt;
$string[&#039;simplehtml:addinstance&#039;] = &#039;Add a new simple HTML block&#039;;&lt;br /&gt;
$string[&#039;simplehtml:myaddinstance&#039;] = &#039;Add a new simple HTML block to the My Moodle page&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold version information for the plugin, along with other advanced parameters (not covered here - see [[version.php]] if you want more details).&lt;br /&gt;
&lt;br /&gt;
Prior to Moodle 2.0, version details for blocks were stored as class fields; as of Moodle 2.0 these are stored in a file called version.php, stored under &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039;. The version file is very simple indeed, containing only a few field definitions, depending on your needs. Here is an example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$plugin-&amp;gt;version = 2011062800;  // YYYYMMDDHH (year, month, day, 24-hr time)&lt;br /&gt;
$plugin-&amp;gt;requires = 2010112400; // YYYYMMDDHH (This is the release version for Moodle 2.0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file contains object field definitions that denote the version number of the block, along with the minimum version of Moodle that must be installed in order to use it. Please note that the object being used here is &#039;&#039;always&#039;&#039; called &#039;&#039;&#039;$plugin&#039;&#039;&#039;, and that you do not need to create this object yourself within the version file. Note also we don&#039;t include a closing &amp;quot;?&amp;gt;&amp;quot; tag. This is intentional, and a [[Coding_style#PHP_tags | workaround for whitespace issues]].&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== I Just Hear Static ==&lt;br /&gt;
In order to get our block to actually display something on screen, we need to add one more method to our class (before the final closing brace in our file). The new code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;  &lt;br /&gt;
  public function get_content() {&lt;br /&gt;
    if ($this-&amp;gt;content !== null) {&lt;br /&gt;
      return $this-&amp;gt;content;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;content         =  new stdClass;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text   = &#039;The content of our SimpleHTML block!&#039;;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
}   // Here&#039;s the closing bracket for the class definition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Add your block to the front page!&#039;&#039;&#039;&lt;br /&gt;
Don&#039;t forget (especially if you&#039;re a new Moodle user) to add your block to the front page. Turn Editing On, and add your block to the page.&lt;br /&gt;
&lt;br /&gt;
It can&#039;t get any simpler than that, can it? Let&#039;s dissect this method to see what&#039;s going on...&lt;br /&gt;
&lt;br /&gt;
First of all, there is a check that returns the current value of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] if it&#039;s not NULL; otherwise we proceed with &amp;quot;computing&amp;quot; it. Since the computation is potentially a time-consuming operation and it &#039;&#039;&#039;will&#039;&#039;&#039; be called several times for each block (Moodle works that way internally), we take a precaution and include this time-saver.&lt;br /&gt;
Supposing the content had not been computed before (it was NULL), we then define it from scratch. The code speaks for itself there, so there isn&#039;t much to say. Just keep in mind that we can use HTML both in the text &#039;&#039;&#039;and&#039;&#039;&#039; in the footer, if we want to.&lt;br /&gt;
&lt;br /&gt;
It&#039;s worth mentioning that this is not the only type of content a block can output. You can also create lists and hierarchical trees, which are better suited for certain types of output, such as menus. These different content types have an impact on the content object and how it is constructed. For more information, see [[Blocks/Appendix A#.24this-.3Econtent_type|Appendix A]]&lt;br /&gt;
&lt;br /&gt;
At this point our block should be capable of being automatically installed in Moodle and added to courses; visit your administration page to install it (Click &amp;quot;Notifications&amp;quot; under the Site Administration Block) and after seeing it in action come back to continue our tutorial.&lt;br /&gt;
&lt;br /&gt;
== Configure That Out ==&lt;br /&gt;
&lt;br /&gt;
The current version of our block doesn&#039;t really do much; it just displays a fixed message, which is not very useful. What we&#039;d really like to do is allow the teachers to customize what goes into the block. This, in block-speak, is called &amp;quot;instance configuration&amp;quot;. Basic instance configuration is automatic in Moodle 2.0; if you put any page with blocks on it into &amp;quot;editing mode&amp;quot;, you will notice that each block has an edit button in its title bar. Clicking on this will take you to the block configuration form. The settings that Moodle adds to this form by default relate to the block&#039;s appearance and position on Moodle pages. &lt;br /&gt;
&lt;br /&gt;
We can extend this configuration form, and add custom preferences fields, so that users can better tailor our block to a given task or page. To extend the configuration form, create the file &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&amp;lt;/span&amp;gt;, and fill it with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class block_simplehtml_edit_form extends block_edit_form {&lt;br /&gt;
        &lt;br /&gt;
    protected function specific_definition($mform) {&lt;br /&gt;
        &lt;br /&gt;
        // Section header title according to language file.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;configheader&#039;, get_string(&#039;blocksettings&#039;, &#039;block&#039;));&lt;br /&gt;
&lt;br /&gt;
        // A sample string variable with a default value.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_text&#039;, get_string(&#039;blockstring&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;config_text&#039;, &#039;default value&#039;);&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;config_text&#039;, PARAM_MULTILANG);        &lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The first line declares a class that inherits &#039;&#039;&#039;from block_edit_form&#039;&#039;&#039;, and this allows Moodle to identify the code to execute in the configuration page. The &#039;&#039;&#039;specific_definition()&#039;&#039;&#039; method is where your form elements are defined, and these take the same format as with the standard [[lib/formslib.php_Form_Definition|Moodle form library]].  Within our specific_definition method, we have created a header, and an input field which will accept text to be used within the block.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; All your field names need to start with &amp;quot;config_&amp;quot;, otherwise they will not be saved and will not be available within the block via [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]]. &lt;br /&gt;
&lt;br /&gt;
So once our instance configuration form has been saved, we can use the inputted text within the block like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (! empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text = $this-&amp;gt;config-&amp;gt;text;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] is available in all block methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]. This is because [[Blocks/Appendix_A#init.28.29|init()]] is called immediately as the block is being created, with the purpose of setting things up, so [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] has not yet been instantiated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note about Checkbox:&#039;&#039;&#039; You cannot use the &#039;checkbox&#039; element in the form (once set it will stay set). You must use advcheckbox instead. &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Specialists ==&lt;br /&gt;
&lt;br /&gt;
Implementing instance configuration for the block&#039;s contents was good enough to whet our appetite, but who wants to stop there? Why not customize the block&#039;s title, too?&lt;br /&gt;
&lt;br /&gt;
Why not, indeed. Well, our first attempt to achieve this is natural enough: let&#039;s add another field to &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&#039;&#039;. Here goes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // A sample string variable with a default value.&lt;br /&gt;
    $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_title&#039;, get_string(&#039;blocktitle&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
    $mform-&amp;gt;setDefault(&#039;config_title&#039;, &#039;default value&#039;);&lt;br /&gt;
    $mform-&amp;gt;setType(&#039;config_title&#039;, PARAM_MULTILANG);        &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We save the edited file, go to a course, edit the title of the block and... nothing happens! The instance configuration is saved correctly, all right (editing it once more proves that) but it&#039;s not being displayed. All we get is just the simple &amp;quot;SimpleHTML&amp;quot; title.&lt;br /&gt;
&lt;br /&gt;
That&#039;s not too weird, if we think back a bit. Do you remember that [[Blocks/Appendix_A#init.28.29|init()]] method, where we set [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]]? We didn&#039;t actually change its value from then, and [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] is definitely not the same as &#039;&#039;&#039;$this-&amp;gt;config-&amp;gt;title&#039;&#039;&#039; (to Moodle, at least). What we need is a way to update [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] with the value in the instance configuration. But as we said a bit earlier, we can use [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] in all methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]! So what can we do?&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pull out another ace from our sleeve, and add this small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function specialization() {&lt;br /&gt;
  if (!empty($this-&amp;gt;config-&amp;gt;title)) {&lt;br /&gt;
    $this-&amp;gt;title = $this-&amp;gt;config-&amp;gt;title;&lt;br /&gt;
  } else {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;title = &#039;Default title ...&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;text = &#039;Default text ...&#039;;&lt;br /&gt;
  }    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aha, here&#039;s what we wanted to do all along! But what&#039;s going on with the [[Blocks/Appendix_A#specialization.28.29| specialization()]] method?&lt;br /&gt;
&lt;br /&gt;
This &amp;quot;magic&amp;quot; method has actually a very nice property: it&#039;s &#039;&#039;guaranteed&#039;&#039; to be automatically called by Moodle as soon as our instance configuration is loaded and available (that is, immediately after [[Blocks/Appendix_A#init.28.29|init()]] is called). That means before the block&#039;s content is computed for the first time, and indeed before &#039;&#039;anything&#039;&#039; else is done with the block. Thus, providing a [[Blocks/Appendix_A#specialization.28.29| specialization()]] method is the natural choice for any configuration data that needs to be acted upon or made available &amp;quot;as soon as possible&amp;quot;, as in this case.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Now You See Me, Now You Don&#039;t ==&lt;br /&gt;
&lt;br /&gt;
Now would be a good time to mention another nifty technique that can be used in blocks, and which comes in handy quite often. Specifically, it may be the case that our block will have something interesting to display some of the time; but in some other cases, it won&#039;t have anything useful to say. An example here would be the &amp;quot;Recent Activity&amp;quot; block, in the case where no recent activity in fact exists. &lt;br /&gt;
&lt;br /&gt;
However in that case the block chooses to explicitly inform you of the lack of said activity, which is arguably useful. It would be nice, then, to be able to have our block &amp;quot;disappear&amp;quot; if it&#039;s not needed to display it.&lt;br /&gt;
&lt;br /&gt;
This is indeed possible, and the way to do it is to make sure that after the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called, the block has no content to display. This means that all fields in $this-&amp;gt;content should be equal to the empty string (&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;). In the case of our HTML-based block, these fields are $this-&amp;gt;content-&amp;gt;text and $this-&amp;gt;content-&amp;gt;footer. Moodle performs this check by calling the block&#039;s [[Blocks/Appendix_A#is_empty.28.29| is_empty()]] method, and if the block is indeed empty then it is not displayed at all.&lt;br /&gt;
&lt;br /&gt;
Note that the exact value of the block&#039;s title and the presence or absence of a [[Blocks/Appendix_A#hide_header.28.29| hide_header()]] method do &#039;&#039;not&#039;&#039; affect this behavior. A block is considered empty if it has no content, irrespective of anything else.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== We Are Legion ==&lt;br /&gt;
&lt;br /&gt;
Right now our block is fully configurable, both in title and content. It&#039;s so versatile, in fact, that we could make pretty much anything out of it. It would be really nice to be able to add multiple blocks of this type to a single course. And, as you might have guessed, doing that is as simple as adding another small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_allow_multiple() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells Moodle that it should allow any number of instances of the SimpleHTML block in any course. After saving the changes to our file, Moodle immediately allows us to add multiple copies of the block without further ado!&lt;br /&gt;
&lt;br /&gt;
Please note that even if a block itself allows multiple instances in the same page, the administrator still has the option of disallowing such behavior. This setting can be set separately for each block from the Administration / Configuration / Blocks page.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Effects of Globalization ==&lt;br /&gt;
&lt;br /&gt;
Configuring each block instance with its own personal data is cool enough, but sometimes administrators need some way to &amp;quot;touch&amp;quot; all instances of a specific block at the same time. In the case of our SimpleHTML block, a few settings that would make sense to apply to all instances aren&#039;t that hard to come up with. &lt;br /&gt;
&lt;br /&gt;
For example, we might want to limit the contents of each block to only so many characters, or we might have a setting that filters HTML out of the block&#039;s contents, only allowing pure text in. Granted, such a feature wouldn&#039;t win us any awards for naming our block &amp;quot;SimpleHTML&amp;quot; but some tormented administrator somewhere might actually find it useful.&lt;br /&gt;
&lt;br /&gt;
This kind of configuration is called &amp;quot;global configuration&amp;quot; and applies only to a specific block type (all instances of that block type are affected, however).  Implementing such configuration for our block is quite similar to implementing the instance configuration. We will now see how to implement the second example, having a setting that only allows text and not HTML in the block&#039;s contents. To enable global configuration for the block, we create a new file, &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;settings.php&#039;&#039;&#039;&#039;&#039;, and populate it with form field definitions for each setting, which Moodle will use to generate and handle a global settings form.  This is quite similar in concept to how we generated the instance configuration form earlier, but the actual code used to generate the form and fields is somewhat different.&lt;br /&gt;
&lt;br /&gt;
Place the following in your settings.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_heading(&lt;br /&gt;
            &#039;headerconfig&#039;,&lt;br /&gt;
            get_string(&#039;headerconfig&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descconfig&#039;, &#039;block_simplehtml&#039;)&lt;br /&gt;
        ));&lt;br /&gt;
&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_configcheckbox(&lt;br /&gt;
            &#039;simplehtml/Allow_HTML&#039;,&lt;br /&gt;
            get_string(&#039;labelallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            &#039;0&#039;&lt;br /&gt;
        ));    &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, to generate a global configuration form, we simply create admin setting objects and add them to an array. This array is then stepped over to create the settings form, and the inputted data is automatically saved to the database. Full details of the setting types available and how to add them can be found under [[Admin_settings#Individual_settings]].&lt;br /&gt;
&lt;br /&gt;
We&#039;ve now created a header and checkbox form element to accept configuration details from the site admin. You should pay extra attention to the name of our checkbox element, &#039;&#039;&#039; &#039;simplehtml/Allow_HTML&#039; &#039;&#039;&#039;, as it specifies not only the name of the configuration option, but also how it should be stored. If you simply specify a name for the config option, it will be stored in the global $CFG object, and in the &#039;&#039;&amp;lt;prefix&amp;gt;_config&#039;&#039; database table. This will make your config variable available immediately via $CFG without requiring an additional database call, but will also increase the size of the $CFG object. In addition, we must prefix the variable with the name of our block, otherwise we run the risk of our config variable sharing its name with a similar variable in another plugin, or within Moodle itself.&lt;br /&gt;
&lt;br /&gt;
The preferred method of storing your block&#039;s configuration data is to prefix each config variable name in your settings.php file with your block&#039;s name, followed by a slash ( / ), and the name of the configuration variable, as we have done above. If you write your settings.php file in this way, then your variables will be stored in the &#039;&#039;&amp;lt;prefix&amp;gt;_config_plugin&#039;&#039; table, under your block&#039;s name. Your config data will still be available via a &#039;&#039;&#039;get_config()&#039;&#039;&#039; call, and name collision will be impossible between plugins.&lt;br /&gt;
&lt;br /&gt;
Finally, if you&#039;re wondering why there are two language tags specified for each element, the first tag is for the element&#039;s label or primary text, and the second tag is for its description. And that&#039;s it. Pretty easy, huh?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE FOR UPGRADERS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You&#039;ll notice that the settings.php file and parsed element names replaces Moodle&#039;s old storage method, wherein it would send all the configuration data to your block&#039;s [[Blocks/Appendix_A#config_save.28.29|config_save()]] method, and allow you to override how the data is saved. The [[Blocks/Appendix_A#config_save.28.29|config_save()]] method is no longer used in Moodle 2.x; however the [[Blocks/Appendix_A#instance_config_save.28.29|instance_config_save()]] method is very much alive and well, as you will see shortly.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Global Config Data  ===&lt;br /&gt;
&lt;br /&gt;
Now that we have global data defined for the plugin, we need to know how to access it within our code.  If you saved your config variables in the global namespace, you can access them from the global $CFG object, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = $CFG-&amp;gt;Allow_HTML;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If, as recommended, you saved your config variables in a custom namespace for your block, then you can access them via a call to &#039;&#039;&#039;get_config()&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Rolling It All Together ===&lt;br /&gt;
&lt;br /&gt;
OK, so we now have an instance configuration form that allows users to enter custom content text for a block, and a global configuration option that dictates whether or not that user should be allowed to enter HTML tags as part of the content. Now we just need to tie the two together. But if Moodle takes care of the form processing for our instance configuration in edit_form.php, how can we capture it and remove the HTML tags where required?&lt;br /&gt;
&lt;br /&gt;
Well, fortunately, there is a way this can be done.  By overriding the [[Blocks/Appendix_A#instance_config_save.28.29| instance_config_save()]] method in our block class, we can modify the way in which instance configuration data is stored after input. The default implementation is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data) {&lt;br /&gt;
  $data = stripslashes_recursive($data);&lt;br /&gt;
  $this-&amp;gt;config = $data;&lt;br /&gt;
  return set_field(&#039;block_instance&#039;, &lt;br /&gt;
                   &#039;configdata&#039;,&lt;br /&gt;
                    base64_encode(serialize($data)),&lt;br /&gt;
                   &#039;id&#039;, &lt;br /&gt;
                   $this-&amp;gt;instance-&amp;gt;id);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may look intimidating at first (what&#039;s all this stripslashes_recursive() and base64_encode() and serialize() stuff?) but do not despair; we won&#039;t have to touch any of it. We will only add some extra validation code in the beginning and then instruct Moodle to additionally call this default implementation to do the actual storing of the data. Specifically, we will add a method to our class which goes like this:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data) {&lt;br /&gt;
  if(get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;) == &#039;1&#039;) {&lt;br /&gt;
    $data-&amp;gt;text = strip_tags($data-&amp;gt;text);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // And now forward to the default implementation defined in the parent class&lt;br /&gt;
  return parent::instance_config_save($data);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(This example assumes you are using a custom namespace for the block.)&lt;br /&gt;
&lt;br /&gt;
At last! Now the administrator has absolute power of life and death over what type of content is allowed in our &amp;quot;SimpleHTML&amp;quot; block! Absolute? Well... not exactly. In fact, if we think about it for a while, it will become apparent that if at some point in time HTML is allowed and some blocks have saved their content with HTML included, and afterwards the administrator changes the setting to &amp;quot;off&amp;quot;, this will only prevent subsequent content changes from including HTML. Blocks which already had HTML in their content would continue to display it!&lt;br /&gt;
&lt;br /&gt;
Following that train of thought, the next stop is realizing that we wouldn&#039;t have this problem if we had chosen the lazy approach a while back, because in that case we would &amp;quot;sanitize&amp;quot; each block&#039;s content just before it was displayed. &lt;br /&gt;
&lt;br /&gt;
The only thing we can do with the eager approach is strip all the tags from the content of all SimpleHTML instances as soon as the admin setting is changed to &amp;quot;HTML off&amp;quot;; but even then, turning the setting back to &amp;quot;HTML on&amp;quot; won&#039;t bring back the tags we stripped away. On the other hand, the lazy approach might be slower, but it&#039;s more versatile; we can choose whether to strip or keep the HTML before displaying the content, and we won&#039;t lose it at all if the admin toggles the setting off and on again. Isn&#039;t the life of a developer simple and wonderful?&lt;br /&gt;
&lt;br /&gt;
=== Exercise === &lt;br /&gt;
We will let this part of the tutorial come to a close with the obligatory exercise for the reader: &lt;br /&gt;
In order to have the SimpleHTML block work &amp;quot;correctly&amp;quot;, find out how to strengthen the eager approach to strip out all tags from the existing configuration of all instances of our block, &#039;&#039;&#039;or&#039;&#039;&#039; go back and implement the lazy approach instead. &lt;br /&gt;
(Hint: Do that in the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Eye Candy ==&lt;br /&gt;
&lt;br /&gt;
Our block is just about complete functionally, so now let&#039;s take a look at some of the tricks we can use to make its behavior customized in a few more useful ways.&lt;br /&gt;
&lt;br /&gt;
First of all, there are a couple of ways we can adjust the visual aspects of our block. For starters, it might be useful to create a block that doesn&#039;t display a header (title) at all. You can see this effect in action in the Course Description block that comes with Moodle. This behavior is achieved by, you guessed it, adding one more method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function hide_header() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One more note here: we cannot just set an empty title inside the block&#039;s [[Blocks/Appendix_A#init.28.29| init()]] method; it&#039;s necessary for each block to have a unique, non-empty title after [[Blocks/Appendix_A#init.28.29| init()]] is called so that Moodle can use those titles to differentiate between all of the installed blocks.&lt;br /&gt;
&lt;br /&gt;
Next, we can affect some properties of the actual HTML that will be used to print our block. Each block is fully contained within a &amp;amp;lt;div&amp;amp;gt; or &amp;amp;lt;table&amp;amp;gt; elements, inside which all the HTML for that block is printed. We can instruct Moodle to add HTML attributes with specific values to that container. This is generally done to give us freedom to customize the end result using CSS (this is in fact done by default as we&#039;ll see below).&lt;br /&gt;
&lt;br /&gt;
The default behavior of this feature in our case will modify our block&#039;s &amp;quot;class&amp;quot; HTML attribute by appending the value &amp;quot;block_simplehtml&amp;quot; (the prefix &amp;quot;block_&amp;quot; followed by the name of our block, lowercased). We can then use that class to make CSS selectors in our theme to alter this block&#039;s visual style (for example, &amp;quot;.block_simplehtml { border: 1px black solid}&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To change the default behavior, we will need to define a method which returns an associative array of attribute names and values. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function html_attributes() {&lt;br /&gt;
    $attributes = parent::html_attributes(); // Get default values&lt;br /&gt;
    $attributes[&#039;class&#039;] .= &#039; block_&#039;. $this-&amp;gt;name(); // Append our class to class attribute&lt;br /&gt;
    return $attributes;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This results in the block having all its normal HTML attributes, as inherited from the base block class, plus our additional class name. We can now use this class name to change the style of the block, add JavaScript events to it via YUI, and so on. And for one final elegant touch,  we have not set the class to the hard-coded value &amp;quot;block_simplehtml&amp;quot;, but instead used the [[Blocks/Appendix_A#name.28.29| name()]] method to make it dynamically match our block&#039;s name.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Authorized Personnel Only ==&lt;br /&gt;
&lt;br /&gt;
Some blocks are useful in some circumstances, but not in others. An example of this would be the &amp;quot;Social Activities&amp;quot; block, which is useful in courses with the &amp;quot;social&amp;quot; course format, but not courses with the &amp;quot;weeks&amp;quot; format. What we need to be able to do is limit our block&#039;s availability, so that it can only be selected on pages where its content or abilities are appropriate.&lt;br /&gt;
&lt;br /&gt;
Moodle allows us to declare which page formats a block is available on, and enforces these restrictions as set by the block&#039;s developer at all times. The information is given to Moodle as a standard associative array, with each key corresponding to a page format and defining a boolean value (true/false) that declares whether the block should be allowed to appear in that page format.&lt;br /&gt;
&lt;br /&gt;
Notice the deliberate use of the term &#039;&#039;page&#039;&#039; instead of &#039;&#039;course&#039;&#039; in the above paragraph. This is because in Moodle 1.5 and onwards, blocks can be displayed in any page that supports them. The best example of such pages are the course pages, but we are not restricted to them. For instance, the quiz view page (the first one we see when we click on the name of the quiz) also supports blocks.&lt;br /&gt;
&lt;br /&gt;
The format names we can use for the pages derive from the name of the script which is actually used to display that page. For example, when we are looking at a course, the script is &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/course/view.php&amp;lt;/span&amp;gt; (this is evident from the browser&#039;s address line). Thus, the format name of that page is &#039;&#039;&#039;course-view&#039;&#039;&#039;. It follows easily that the format name for a quiz view page is &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039;. This rule of thumb does have a few exceptions, however:&lt;br /&gt;
&lt;br /&gt;
# The format name for the front page of Moodle is &#039;&#039;&#039;site-index&#039;&#039;&#039;.&lt;br /&gt;
# The format name for courses is actually not just &#039;&#039;&#039;course-view&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;; it is &amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;course-view-weeks&#039;&#039;&#039;, &#039;&#039;&#039;course-view-topics&#039;&#039;&#039;, etc.&lt;br /&gt;
# Even though there is no such page, the format name &#039;&#039;&#039;all&#039;&#039;&#039; can be used as a catch-all option.&lt;br /&gt;
&lt;br /&gt;
We can include as many format names as we want in our definition of the applicable formats. Each format can be allowed or disallowed, and there are also three more rules that help resolve the question &amp;quot;is this block allowed into this page or not?&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
# Prefixes of a format name will match that format name; for example, &#039;&#039;&#039;mod&#039;&#039;&#039; will match all the activity modules. &#039;&#039;&#039;course-view&#039;&#039;&#039; will match any course, regardless of the course format. And finally, &#039;&#039;&#039;site&#039;&#039;&#039; will also match the front page (remember that its full format name is &#039;&#039;&#039;site-index&#039;&#039;&#039;).&lt;br /&gt;
# The more specialized a format name that matches our page is, the higher precedence it has when deciding if the block will be allowed. For example, &#039;&#039;&#039;mod&#039;&#039;&#039;, &#039;&#039;&#039;mod-quiz&#039;&#039;&#039; and &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; all match the quiz view page. But if all three are present, &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; will take precedence over the other two because it is a better match.&lt;br /&gt;
# The character &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; can be used in place of any word. For example, &#039;&#039;&#039;mod&#039;&#039;&#039; and &#039;&#039;&#039;mod-*&#039;&#039;&#039; are equivalent. At the time of this document&#039;s writing, there is no actual reason to utilize this &amp;quot;wildcard matching&amp;quot; feature, but it exists for future usage.&lt;br /&gt;
# The order that the format names appear does not make any difference.&lt;br /&gt;
All of the above are enough to make the situation sound complex, so let&#039;s look at some specific examples. First of all, to have our block appear &#039;&#039;&#039;only&#039;&#039;&#039; in the site front page, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&#039;site&#039; =&amp;gt; true);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Since &#039;&#039;&#039;all&#039;&#039;&#039; is missing, the block is disallowed from appearing in &#039;&#039;any&#039;&#039; course format; but then &#039;&#039;&#039;site&#039;&#039;&#039; is set to TRUE, so it&#039;s explicitly allowed to appear in the site front page (remember that &#039;&#039;&#039;site&#039;&#039;&#039; matches &#039;&#039;&#039;site-index&#039;&#039;&#039; because it&#039;s a prefix).&lt;br /&gt;
&lt;br /&gt;
For another example, if we wanted to allow the block to appear in all course formats &#039;&#039;except&#039;&#039; social, and also to &#039;&#039;not&#039;&#039; be allowed anywhere but in courses, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
    &#039;course-view-social&#039; =&amp;gt; false);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This time, we first allow the block to appear in all courses and then we explicitly disallow the social format.&lt;br /&gt;
For our final, most complicated example, suppose that a block can be displayed in the site front page, in courses (but not social courses) and also when we are viewing any activity module, &#039;&#039;except&#039;&#039; quiz. This would be:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;site-index&#039; =&amp;gt; true,&lt;br /&gt;
          &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
   &#039;course-view-social&#039; =&amp;gt; false,&lt;br /&gt;
                  &#039;mod&#039; =&amp;gt; true, &lt;br /&gt;
             &#039;mod-quiz&#039; =&amp;gt; false&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is not difficult to realize that the above accomplishes the objective if we remember that there is a &amp;quot;best match&amp;quot; policy to determine the end result.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Responding to Cron ==&lt;br /&gt;
&lt;br /&gt;
It is possible to have our block respond to the global Moodle cron process; we can have a method that is run at regular intervals regardless of user interaction. There are two parts to this. Firstly we need to define a new function within our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function cron() {&lt;br /&gt;
    mtrace( &amp;quot;Hey, my cron script is running&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
    // do something&lt;br /&gt;
&lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we will need to set the (minimum) execution interval for our cron function. Prior to Moodle 2.0, this was achieved by setting the value of a block&#039;s $this-&amp;gt;cron field, via the init() method. This is now achieved by adding an additional line to our &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039; file. Open it up and add the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $plugin-&amp;gt;cron = 300;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cron intervals are set in seconds, so the above line will set our minimum execution interval to 5 minutes. However, the function can only be called as frequently as cron has been set to run in the Moodle installation. So if our block is set to wait at least 5 minutes between runs, as in this example, but Moodle&#039;s cron system is only set to run every 24 hours, then our block is going to be waiting a lot longer between runs than we expected!&lt;br /&gt;
&lt;br /&gt;
Remember that if we change any values in the version file or block file we &#039;&#039;&#039;must&#039;&#039;&#039; bump the version number and visit the Notifications page to upgrade the block, otherwise they will be ignored.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039;&lt;br /&gt;
The block cron is designed to call the cron script for that block &#039;&#039;&#039;type&#039;&#039;&#039; only. That is, cron does not care about individual instances of blocks. Inside your cron function &#039;&#039;$this&#039;&#039; is defined, but it has almost nothing in it (only title and content fields are populated). If you need to execute cron for individual instances it is your own responsibility to iterate over them in the block&#039;s cron function. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function cron() {&lt;br /&gt;
&lt;br /&gt;
    global $DB; // Global database object&lt;br /&gt;
&lt;br /&gt;
    // Get the instances of the block&lt;br /&gt;
    $instances = $DB-&amp;gt;get_records( &#039;block_instance&#039;, array(&#039;blockid&#039;=&amp;gt;&#039;simplehtml&#039;) );&lt;br /&gt;
&lt;br /&gt;
    // Iterate over the instances&lt;br /&gt;
    foreach ($instances as $instance) {&lt;br /&gt;
&lt;br /&gt;
        // Recreate block object&lt;br /&gt;
        $block = block_instance(&#039;simplehtml&#039;, $instance);&lt;br /&gt;
&lt;br /&gt;
        // $block is now the equivalent of $this in &#039;normal&#039; block&lt;br /&gt;
        // usage, e.g.&lt;br /&gt;
        $someconfigitem = $block-&amp;gt;config-&amp;gt;item2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TIP: This also means that creating a block is a possible way to create code that can respond to cron with a reasonably low overhead. No actual instances of the block are required.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Additional Content Types == &lt;br /&gt;
&lt;br /&gt;
=== Lists ===&lt;br /&gt;
&lt;br /&gt;
In this final part of the guide we will briefly discuss several additional capabilities of Moodle&#039;s block system, namely the ability to create blocks that display different kinds of content to the user. The first of these creates a list of options and displays them to the user.  This list is displayed with one item per line, and an optional image (icon) next to the item. An example of such a &#039;&#039;list block&#039;&#039; is the standard Moodle &amp;quot;admin&amp;quot; block, which illustrates all the points discussed in this section.&lt;br /&gt;
&lt;br /&gt;
As we have seen so far, blocks use two properties of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]]: &amp;quot;text&amp;quot; and &amp;quot;footer&amp;quot;. The text is displayed as-is as the block content, and the footer is displayed below the content in a smaller font size. List blocks use $this-&amp;gt;content-&amp;gt;footer in the exact same way, but they ignore $this-&amp;gt;content-&amp;gt;text.&lt;br /&gt;
&lt;br /&gt;
Instead, Moodle expects such blocks to set two other properties when the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called: $this-&amp;gt;content-&amp;gt;items and $this-&amp;gt;content-&amp;gt;icons. $this-&amp;gt;content-&amp;gt;items should be a numerically indexed array containing elements that represent the HTML for each item in the list that is going to be displayed. Usually these items will be HTML anchor tags which provide links to some page. $this-&amp;gt;content-&amp;gt;icons should also be a numerically indexed array, with exactly as many items as $this-&amp;gt;content-&amp;gt;items has. Each of these items should be a fully qualified HTML &amp;lt;img&amp;gt; tag, with &amp;quot;src&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;width&amp;quot; and &amp;quot;alt&amp;quot; attributes. Obviously, it makes sense to keep the images small and of a uniform size. We would recommend standard 16x16 images for this purpose.&lt;br /&gt;
&lt;br /&gt;
In order to tell Moodle that we want to have a list block instead of the standard text block, we need to make a small change to our block class declaration. Instead of extending class &#039;&#039;&#039;block_base&#039;&#039;&#039;, our block will extend class &#039;&#039;&#039;block_list&#039;&#039;&#039;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
class block_my_menu extends block_list {&lt;br /&gt;
     // The init() method does not need to change at all&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition to making this change, we must of course also modify the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method to construct the [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] variable as discussed above:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function get_content() {&lt;br /&gt;
  if ($this-&amp;gt;content !== null) {&lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content         = new stdClass;&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items[] = html_writer::tag(&#039;a&#039;, &#039;Menu Option 1&#039;, array(&#039;href&#039; =&amp;gt; &#039;some_file.php&#039;));&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons[] = html_writer::empty_tag(&#039;img&#039;, array(&#039;src&#039; =&amp;gt; &#039;images/icons/1.gif&#039;, &#039;class&#039; =&amp;gt; &#039;icon&#039;));&lt;br /&gt;
&lt;br /&gt;
  // Add more list items here&lt;br /&gt;
 &lt;br /&gt;
  return $this-&amp;gt;content;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To summarise, if we want to create a list block instead of a text block, we just need to change the block class declaration and the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method. Adding the mandatory [[Blocks/Appendix_A#init.28.29| init()]] method as discussed earlier will then give us our first list block in no time!&lt;br /&gt;
&lt;br /&gt;
=== Trees ===&lt;br /&gt;
&lt;br /&gt;
As of 23rd December 2011, this functionality remains inoperable in all Moodle 2.x versions. It appears that classes are missing from the code base. This has been added to the tracker at the URL below. Please upvote this issue if you require this functionality.&lt;br /&gt;
&lt;br /&gt;
[http://tracker.moodle.org/browse/MDL-28289 Visit this issue on the tracker @ MDL28289]&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Database support ==&lt;br /&gt;
In case we need to have a database table that holds some specific information used within our block, we will need to create the file &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;install.xml&#039;&#039;&#039;&#039;&#039; with the table schema contained within it.&lt;br /&gt;
&lt;br /&gt;
To create the install.xml file, use the [[XMLDB editor]]. See [[Database_FAQ#XMLDB|Database FAQ &amp;gt; XMLDB]] for further details.&lt;br /&gt;
&lt;br /&gt;
Up-to-date documentation on upgrading our block, as well as providing new capabilities and events to the system, can be found under [https://docs.moodle.org/dev/Installing_and_upgrading_plugin_database_tables#install.php Installing and Upgrading Plugin Database Tables]&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Blocks Advanced]] A continuation of this tutorial.&lt;br /&gt;
* [http://dev.moodle.org/mod/resource/view.php?id=48 Unit 7 of the Introduction to Moodle Programming course] is a follow up to this course. (But you should follow the forum discussions of that course closely as there are still some bugs and inconsistencies.)&lt;br /&gt;
* A [http://cvs.moodle.org/contrib/plugins/blocks/NEWBLOCK/ NEWBLOCK template] you can all use to start you own block.&lt;br /&gt;
&lt;br /&gt;
== Appendices ==&lt;br /&gt;
&lt;br /&gt;
The appendices have been moved to separate pages:&lt;br /&gt;
&lt;br /&gt;
* Appendix A: [[Blocks/Appendix A|&#039;&#039;block_base&#039;&#039; Reference]] &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;br /&gt;
[[ja:開発:ブロック]]&lt;br /&gt;
[[:en:Blocks|Blocks]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=36366</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=36366"/>
		<updated>2012-11-15T06:32:08Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* db/access.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039; A Step-by-step Guide To Creating Blocks &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Original Author: Jon Papaioannou ([mailto:pj@moodle.org pj@moodle.org])&lt;br /&gt;
&lt;br /&gt;
Updated to Moodle 2.0 and above by: Greg J Preece ([mailto:greg.preece@blackboard.com greg.preece@blackboard.com])&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
The present document serves as a guide to developers who want to create their own blocks for use in Moodle. It applies to the 2.0 development version of Moodle (and any newer) &#039;&#039;&#039;only&#039;&#039;&#039;, as the blocks API changed significantly enough to warrant new documentation. Those wishing to read the old tutorial for Moodles 1.5 to 1.9 can find it under [[Blocks/Blocks for 1.5 to 1.9| Blocks for 1.5 to 1.9]].&lt;br /&gt;
&lt;br /&gt;
The guide is written as an interactive course which aims to develop a configurable, multi-purpose block that displays arbitrary HTML. It&#039;s targeted mainly at people with little experience with Moodle or programming in general and aims to show how easy it is to create new blocks for Moodle. A certain small amount of PHP programming knowledge is still required, though. &lt;br /&gt;
&lt;br /&gt;
Experienced developers and those who just want a &#039;&#039;&#039;programmer&#039;s reference&#039;&#039;&#039; text should refer to [[Blocks/Appendix_A| Appendix A]] because the main guide has a rather low concentration of pure information in the text.&lt;br /&gt;
&lt;br /&gt;
== Basic Concepts ==&lt;br /&gt;
&lt;br /&gt;
Through this guide, we will be following the creation of an &amp;quot;HTML&amp;quot; block from scratch in order to demonstrate most of the block features at our disposal. Our block will be named &amp;quot;SimpleHTML&amp;quot;. This does not constrain us regarding the name of the actual directory on the server where the files for our block will be stored, but for consistency we will follow the practice of using the lowercased form &amp;quot;simplehtml&amp;quot; in any case where such a name is required. &lt;br /&gt;
&lt;br /&gt;
Whenever we refer to a file or directory name which contains &amp;quot;simplehtml&amp;quot;, it&#039;s important to remember that &#039;&#039;only&#039;&#039; the &amp;quot;simplehtml&amp;quot; part is up to us to change; the rest is standardised and essential for Moodle to work correctly.&lt;br /&gt;
&lt;br /&gt;
Whenever a file&#039;s path is mentioned in this guide, it will always start with a slash. This refers to the Moodle home directory; all files and directories will be referred to with respect to that directory.&lt;br /&gt;
&lt;br /&gt;
== Ready, Set, Go! ==&lt;br /&gt;
&lt;br /&gt;
To define a &amp;quot;block&amp;quot; in Moodle, in the most basic case we need to provide just four PHP files. Remember, in this example we are creating a block called &#039;simplehtml&#039;, replace &#039;simplehtml&#039; with the name of your custom block. The four files should be located in blocks/simplehtml and are:&lt;br /&gt;
&lt;br /&gt;
=== block_simplehtml.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold the class definition for the block, and is used both to manage it as a plugin and to render it onscreen.&lt;br /&gt;
&lt;br /&gt;
We start by creating the main object file, &#039;block_simplehtml.php&#039;. We then begin coding the block:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class block_simplehtml extends block_base {&lt;br /&gt;
    public function init() {&lt;br /&gt;
        $this-&amp;gt;title = get_string(&#039;simplehtml&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    // The PHP tag and the curly bracket for the class definition &lt;br /&gt;
    // will only be closed after there is another function added in the next section.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first line is our block class definition; it must be named exactly in the manner shown. Again, only the &amp;quot;simplehtml&amp;quot; part can (and indeed must) change; everything else is standardised.&lt;br /&gt;
&lt;br /&gt;
Our class is then given a small method: [[Blocks/Appendix_A#init.28.29| init()]]. This is essential for all blocks, and its purpose is to give values to any class member variables that need instantiating. &lt;br /&gt;
&lt;br /&gt;
In this very basic example, we only want to set [[Blocks/Appendix_A#.24this-.3Etitle| $this-&amp;gt;title]], which is the title displayed in the header of our block. We can set it to whatever we like; in this case it&#039;s set to read the actual title from the language file mentioned previously, which is then distributed along with the block. I&#039;ll skip ahead a bit here and say that if you want your block to display &#039;&#039;&#039;no&#039;&#039;&#039; title at all, then you should set this to any descriptive value you want (but &#039;&#039;&#039;not&#039;&#039;&#039; make it an empty string). We will later see [[Blocks#Eye_Candy|how to disable the title&#039;s display]].&lt;br /&gt;
&lt;br /&gt;
=== db/access.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold the new capabilities created by the block.&lt;br /&gt;
&lt;br /&gt;
Moodle 2.4 onwards introduced the capabilities addinstance and myaddinstance for core blocks. They were introduced so that it was possible to control the use of individual blocks. These capabilities should also be added to your custom block, so in this case to the file blocks/simplehtml/db/access.php. If your block is not going to be used in the &#039;My Moodle page&#039; (ie, your applicable_formats function (discussed later) has &#039;my&#039; set to false.) then the myaddinstance capability is not required. The following is the capabilities array and how it should look for any new blocks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:myaddinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_SYSTEM,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;user&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/my:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_SPAM | RISK_XSS,&lt;br /&gt;
&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_BLOCK,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/site:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== lang/en/block_simplehtml.php ===&lt;br /&gt;
&lt;br /&gt;
This is the English language file for your block. If you are not an English speaker, you can replace &#039;en&#039; with your appropriate language code. All language files for blocks go under the /lang subfolder of the block&#039;s installation folder.&lt;br /&gt;
&lt;br /&gt;
Moodle 2.0 and above require a name for our plugin to show in the upgrading page. We set this value, along with any other language strings we wish to use within the block, in a language package as previously mentioned (the same file where we put our string for the plugin title).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Simple html block&#039;;&lt;br /&gt;
$string[&#039;simplehtml&#039;] = &#039;Simple html&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold version information for the plugin, along with other advanced parameters (not covered here - see [[version.php]] if you want more details).&lt;br /&gt;
&lt;br /&gt;
Prior to Moodle 2.0, version details for blocks were stored as class fields; as of Moodle 2.0 these are stored in a file called version.php, stored under &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039;. The version file is very simple indeed, containing only a few field definitions, depending on your needs. Here is an example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$plugin-&amp;gt;version = 2011062800;  // YYYYMMDDHH (year, month, day, 24-hr time)&lt;br /&gt;
$plugin-&amp;gt;requires = 2010112400; // YYYYMMDDHH (This is the release version for Moodle 2.0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file contains object field definitions that denote the version number of the block, along with the minimum version of Moodle that must be installed in order to use it. Please note that the object being used here is &#039;&#039;always&#039;&#039; called &#039;&#039;&#039;$plugin&#039;&#039;&#039;, and that you do not need to create this object yourself within the version file. Note also we don&#039;t include a closing &amp;quot;?&amp;gt;&amp;quot; tag. This is intentional, and a [[Coding_style#PHP_tags | workaround for whitespace issues]].&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== I Just Hear Static ==&lt;br /&gt;
In order to get our block to actually display something on screen, we need to add one more method to our class (before the final closing brace in our file). The new code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;  &lt;br /&gt;
  public function get_content() {&lt;br /&gt;
    if ($this-&amp;gt;content !== null) {&lt;br /&gt;
      return $this-&amp;gt;content;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;content         =  new stdClass;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text   = &#039;The content of our SimpleHTML block!&#039;;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
}   // Here&#039;s the closing bracket for the class definition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Add your block to the front page!&#039;&#039;&#039;&lt;br /&gt;
Don&#039;t forget (especially if you&#039;re a new Moodle user) to add your block to the front page. Turn Editing On, and add your block to the page.&lt;br /&gt;
&lt;br /&gt;
It can&#039;t get any simpler than that, can it? Let&#039;s dissect this method to see what&#039;s going on...&lt;br /&gt;
&lt;br /&gt;
First of all, there is a check that returns the current value of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] if it&#039;s not NULL; otherwise we proceed with &amp;quot;computing&amp;quot; it. Since the computation is potentially a time-consuming operation and it &#039;&#039;&#039;will&#039;&#039;&#039; be called several times for each block (Moodle works that way internally), we take a precaution and include this time-saver.&lt;br /&gt;
Supposing the content had not been computed before (it was NULL), we then define it from scratch. The code speaks for itself there, so there isn&#039;t much to say. Just keep in mind that we can use HTML both in the text &#039;&#039;&#039;and&#039;&#039;&#039; in the footer, if we want to.&lt;br /&gt;
&lt;br /&gt;
It&#039;s worth mentioning that this is not the only type of content a block can output. You can also create lists and hierarchical trees, which are better suited for certain types of output, such as menus. These different content types have an impact on the content object and how it is constructed. For more information, see [[Blocks/Appendix A#.24this-.3Econtent_type|Appendix A]]&lt;br /&gt;
&lt;br /&gt;
At this point our block should be capable of being automatically installed in Moodle and added to courses; visit your administration page to install it (Click &amp;quot;Notifications&amp;quot; under the Site Administration Block) and after seeing it in action come back to continue our tutorial.&lt;br /&gt;
&lt;br /&gt;
== Configure That Out ==&lt;br /&gt;
&lt;br /&gt;
The current version of our block doesn&#039;t really do much; it just displays a fixed message, which is not very useful. What we&#039;d really like to do is allow the teachers to customize what goes into the block. This, in block-speak, is called &amp;quot;instance configuration&amp;quot;. Basic instance configuration is automatic in Moodle 2.0; if you put any page with blocks on it into &amp;quot;editing mode&amp;quot;, you will notice that each block has an edit button in its title bar. Clicking on this will take you to the block configuration form. The settings that Moodle adds to this form by default relate to the block&#039;s appearance and position on Moodle pages. &lt;br /&gt;
&lt;br /&gt;
We can extend this configuration form, and add custom preferences fields, so that users can better tailor our block to a given task or page. To extend the configuration form, create the file &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&amp;lt;/span&amp;gt;, and fill it with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class block_simplehtml_edit_form extends block_edit_form {&lt;br /&gt;
        &lt;br /&gt;
    protected function specific_definition($mform) {&lt;br /&gt;
        &lt;br /&gt;
        // Section header title according to language file.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;configheader&#039;, get_string(&#039;blocksettings&#039;, &#039;block&#039;));&lt;br /&gt;
&lt;br /&gt;
        // A sample string variable with a default value.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_text&#039;, get_string(&#039;blockstring&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;config_text&#039;, &#039;default value&#039;);&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;config_text&#039;, PARAM_MULTILANG);        &lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The first line declares a class that inherits &#039;&#039;&#039;from block_edit_form&#039;&#039;&#039;, and this allows Moodle to identify the code to execute in the configuration page. The &#039;&#039;&#039;specific_definition()&#039;&#039;&#039; method is where your form elements are defined, and these take the same format as with the standard [[lib/formslib.php_Form_Definition|Moodle form library]].  Within our specific_definition method, we have created a header, and an input field which will accept text to be used within the block.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; All your field names need to start with &amp;quot;config_&amp;quot;, otherwise they will not be saved and will not be available within the block via [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]]. &lt;br /&gt;
&lt;br /&gt;
So once our instance configuration form has been saved, we can use the inputted text within the block like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (! empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text = $this-&amp;gt;config-&amp;gt;text;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] is available in all block methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]. This is because [[Blocks/Appendix_A#init.28.29|init()]] is called immediately as the block is being created, with the purpose of setting things up, so [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] has not yet been instantiated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note about Checkbox:&#039;&#039;&#039; You cannot use the &#039;checkbox&#039; element in the form (once set it will stay set). You must use advcheckbox instead. &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Specialists ==&lt;br /&gt;
&lt;br /&gt;
Implementing instance configuration for the block&#039;s contents was good enough to whet our appetite, but who wants to stop there? Why not customize the block&#039;s title, too?&lt;br /&gt;
&lt;br /&gt;
Why not, indeed. Well, our first attempt to achieve this is natural enough: let&#039;s add another field to &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&#039;&#039;. Here goes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // A sample string variable with a default value.&lt;br /&gt;
    $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_title&#039;, get_string(&#039;blocktitle&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
    $mform-&amp;gt;setDefault(&#039;config_title&#039;, &#039;default value&#039;);&lt;br /&gt;
    $mform-&amp;gt;setType(&#039;config_title&#039;, PARAM_MULTILANG);        &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We save the edited file, go to a course, edit the title of the block and... nothing happens! The instance configuration is saved correctly, all right (editing it once more proves that) but it&#039;s not being displayed. All we get is just the simple &amp;quot;SimpleHTML&amp;quot; title.&lt;br /&gt;
&lt;br /&gt;
That&#039;s not too weird, if we think back a bit. Do you remember that [[Blocks/Appendix_A#init.28.29|init()]] method, where we set [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]]? We didn&#039;t actually change its value from then, and [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] is definitely not the same as &#039;&#039;&#039;$this-&amp;gt;config-&amp;gt;title&#039;&#039;&#039; (to Moodle, at least). What we need is a way to update [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] with the value in the instance configuration. But as we said a bit earlier, we can use [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] in all methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]! So what can we do?&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pull out another ace from our sleeve, and add this small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function specialization() {&lt;br /&gt;
  if (!empty($this-&amp;gt;config-&amp;gt;title)) {&lt;br /&gt;
    $this-&amp;gt;title = $this-&amp;gt;config-&amp;gt;title;&lt;br /&gt;
  } else {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;title = &#039;Default title ...&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;text = &#039;Default text ...&#039;;&lt;br /&gt;
  }    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aha, here&#039;s what we wanted to do all along! But what&#039;s going on with the [[Blocks/Appendix_A#specialization.28.29| specialization()]] method?&lt;br /&gt;
&lt;br /&gt;
This &amp;quot;magic&amp;quot; method has actually a very nice property: it&#039;s &#039;&#039;guaranteed&#039;&#039; to be automatically called by Moodle as soon as our instance configuration is loaded and available (that is, immediately after [[Blocks/Appendix_A#init.28.29|init()]] is called). That means before the block&#039;s content is computed for the first time, and indeed before &#039;&#039;anything&#039;&#039; else is done with the block. Thus, providing a [[Blocks/Appendix_A#specialization.28.29| specialization()]] method is the natural choice for any configuration data that needs to be acted upon or made available &amp;quot;as soon as possible&amp;quot;, as in this case.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Now You See Me, Now You Don&#039;t ==&lt;br /&gt;
&lt;br /&gt;
Now would be a good time to mention another nifty technique that can be used in blocks, and which comes in handy quite often. Specifically, it may be the case that our block will have something interesting to display some of the time; but in some other cases, it won&#039;t have anything useful to say. An example here would be the &amp;quot;Recent Activity&amp;quot; block, in the case where no recent activity in fact exists. &lt;br /&gt;
&lt;br /&gt;
However in that case the block chooses to explicitly inform you of the lack of said activity, which is arguably useful. It would be nice, then, to be able to have our block &amp;quot;disappear&amp;quot; if it&#039;s not needed to display it.&lt;br /&gt;
&lt;br /&gt;
This is indeed possible, and the way to do it is to make sure that after the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called, the block has no content to display. This means that all fields in $this-&amp;gt;content should be equal to the empty string (&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;). In the case of our HTML-based block, these fields are $this-&amp;gt;content-&amp;gt;text and $this-&amp;gt;content-&amp;gt;footer. Moodle performs this check by calling the block&#039;s [[Blocks/Appendix_A#is_empty.28.29| is_empty()]] method, and if the block is indeed empty then it is not displayed at all.&lt;br /&gt;
&lt;br /&gt;
Note that the exact value of the block&#039;s title and the presence or absence of a [[Blocks/Appendix_A#hide_header.28.29| hide_header()]] method do &#039;&#039;not&#039;&#039; affect this behavior. A block is considered empty if it has no content, irrespective of anything else.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== We Are Legion ==&lt;br /&gt;
&lt;br /&gt;
Right now our block is fully configurable, both in title and content. It&#039;s so versatile, in fact, that we could make pretty much anything out of it. It would be really nice to be able to add multiple blocks of this type to a single course. And, as you might have guessed, doing that is as simple as adding another small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_allow_multiple() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells Moodle that it should allow any number of instances of the SimpleHTML block in any course. After saving the changes to our file, Moodle immediately allows us to add multiple copies of the block without further ado!&lt;br /&gt;
&lt;br /&gt;
Please note that even if a block itself allows multiple instances in the same page, the administrator still has the option of disallowing such behavior. This setting can be set separately for each block from the Administration / Configuration / Blocks page.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Effects of Globalization ==&lt;br /&gt;
&lt;br /&gt;
Configuring each block instance with its own personal data is cool enough, but sometimes administrators need some way to &amp;quot;touch&amp;quot; all instances of a specific block at the same time. In the case of our SimpleHTML block, a few settings that would make sense to apply to all instances aren&#039;t that hard to come up with. &lt;br /&gt;
&lt;br /&gt;
For example, we might want to limit the contents of each block to only so many characters, or we might have a setting that filters HTML out of the block&#039;s contents, only allowing pure text in. Granted, such a feature wouldn&#039;t win us any awards for naming our block &amp;quot;SimpleHTML&amp;quot; but some tormented administrator somewhere might actually find it useful.&lt;br /&gt;
&lt;br /&gt;
This kind of configuration is called &amp;quot;global configuration&amp;quot; and applies only to a specific block type (all instances of that block type are affected, however).  Implementing such configuration for our block is quite similar to implementing the instance configuration. We will now see how to implement the second example, having a setting that only allows text and not HTML in the block&#039;s contents. To enable global configuration for the block, we create a new file, &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;settings.php&#039;&#039;&#039;&#039;&#039;, and populate it with form field definitions for each setting, which Moodle will use to generate and handle a global settings form.  This is quite similar in concept to how we generated the instance configuration form earlier, but the actual code used to generate the form and fields is somewhat different.&lt;br /&gt;
&lt;br /&gt;
Place the following in your settings.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_heading(&lt;br /&gt;
            &#039;headerconfig&#039;,&lt;br /&gt;
            get_string(&#039;headerconfig&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descconfig&#039;, &#039;block_simplehtml&#039;)&lt;br /&gt;
        ));&lt;br /&gt;
&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_configcheckbox(&lt;br /&gt;
            &#039;simplehtml/Allow_HTML&#039;,&lt;br /&gt;
            get_string(&#039;labelallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            &#039;0&#039;&lt;br /&gt;
        ));    &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, to generate a global configuration form, we simply create admin setting objects and add them to an array. This array is then stepped over to create the settings form, and the inputted data is automatically saved to the database. Full details of the setting types available and how to add them can be found under [[Admin_settings#Individual_settings]].&lt;br /&gt;
&lt;br /&gt;
We&#039;ve now created a header and checkbox form element to accept configuration details from the site admin. You should pay extra attention to the name of our checkbox element, &#039;&#039;&#039; &#039;simplehtml/Allow_HTML&#039; &#039;&#039;&#039;, as it specifies not only the name of the configuration option, but also how it should be stored. If you simply specify a name for the config option, it will be stored in the global $CFG object, and in the &#039;&#039;&amp;lt;prefix&amp;gt;_config&#039;&#039; database table. This will make your config variable available immediately via $CFG without requiring an additional database call, but will also increase the size of the $CFG object. In addition, we must prefix the variable with the name of our block, otherwise we run the risk of our config variable sharing its name with a similar variable in another plugin, or within Moodle itself.&lt;br /&gt;
&lt;br /&gt;
The preferred method of storing your block&#039;s configuration data is to prefix each config variable name in your settings.php file with your block&#039;s name, followed by a slash ( / ), and the name of the configuration variable, as we have done above. If you write your settings.php file in this way, then your variables will be stored in the &#039;&#039;&amp;lt;prefix&amp;gt;_config_plugin&#039;&#039; table, under your block&#039;s name. Your config data will still be available via a &#039;&#039;&#039;get_config()&#039;&#039;&#039; call, and name collision will be impossible between plugins.&lt;br /&gt;
&lt;br /&gt;
Finally, if you&#039;re wondering why there are two language tags specified for each element, the first tag is for the element&#039;s label or primary text, and the second tag is for its description. And that&#039;s it. Pretty easy, huh?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE FOR UPGRADERS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You&#039;ll notice that the settings.php file and parsed element names replaces Moodle&#039;s old storage method, wherein it would send all the configuration data to your block&#039;s [[Blocks/Appendix_A#config_save.28.29|config_save()]] method, and allow you to override how the data is saved. The [[Blocks/Appendix_A#config_save.28.29|config_save()]] method is no longer used in Moodle 2.x; however the [[Blocks/Appendix_A#instance_config_save.28.29|instance_config_save()]] method is very much alive and well, as you will see shortly.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Global Config Data  ===&lt;br /&gt;
&lt;br /&gt;
Now that we have global data defined for the plugin, we need to know how to access it within our code.  If you saved your config variables in the global namespace, you can access them from the global $CFG object, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = $CFG-&amp;gt;Allow_HTML;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If, as recommended, you saved your config variables in a custom namespace for your block, then you can access them via a call to &#039;&#039;&#039;get_config()&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Rolling It All Together ===&lt;br /&gt;
&lt;br /&gt;
OK, so we now have an instance configuration form that allows users to enter custom content text for a block, and a global configuration option that dictates whether or not that user should be allowed to enter HTML tags as part of the content. Now we just need to tie the two together. But if Moodle takes care of the form processing for our instance configuration in edit_form.php, how can we capture it and remove the HTML tags where required?&lt;br /&gt;
&lt;br /&gt;
Well, fortunately, there is a way this can be done.  By overriding the [[Blocks/Appendix_A#instance_config_save.28.29| instance_config_save()]] method in our block class, we can modify the way in which instance configuration data is stored after input. The default implementation is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data) {&lt;br /&gt;
  $data = stripslashes_recursive($data);&lt;br /&gt;
  $this-&amp;gt;config = $data;&lt;br /&gt;
  return set_field(&#039;block_instance&#039;, &lt;br /&gt;
                   &#039;configdata&#039;,&lt;br /&gt;
                    base64_encode(serialize($data)),&lt;br /&gt;
                   &#039;id&#039;, &lt;br /&gt;
                   $this-&amp;gt;instance-&amp;gt;id);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may look intimidating at first (what&#039;s all this stripslashes_recursive() and base64_encode() and serialize() stuff?) but do not despair; we won&#039;t have to touch any of it. We will only add some extra validation code in the beginning and then instruct Moodle to additionally call this default implementation to do the actual storing of the data. Specifically, we will add a method to our class which goes like this:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data) {&lt;br /&gt;
  if(get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;) == &#039;1&#039;) {&lt;br /&gt;
    $data-&amp;gt;text = strip_tags($data-&amp;gt;text);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // And now forward to the default implementation defined in the parent class&lt;br /&gt;
  return parent::instance_config_save($data);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(This example assumes you are using a custom namespace for the block.)&lt;br /&gt;
&lt;br /&gt;
At last! Now the administrator has absolute power of life and death over what type of content is allowed in our &amp;quot;SimpleHTML&amp;quot; block! Absolute? Well... not exactly. In fact, if we think about it for a while, it will become apparent that if at some point in time HTML is allowed and some blocks have saved their content with HTML included, and afterwards the administrator changes the setting to &amp;quot;off&amp;quot;, this will only prevent subsequent content changes from including HTML. Blocks which already had HTML in their content would continue to display it!&lt;br /&gt;
&lt;br /&gt;
Following that train of thought, the next stop is realizing that we wouldn&#039;t have this problem if we had chosen the lazy approach a while back, because in that case we would &amp;quot;sanitize&amp;quot; each block&#039;s content just before it was displayed. &lt;br /&gt;
&lt;br /&gt;
The only thing we can do with the eager approach is strip all the tags from the content of all SimpleHTML instances as soon as the admin setting is changed to &amp;quot;HTML off&amp;quot;; but even then, turning the setting back to &amp;quot;HTML on&amp;quot; won&#039;t bring back the tags we stripped away. On the other hand, the lazy approach might be slower, but it&#039;s more versatile; we can choose whether to strip or keep the HTML before displaying the content, and we won&#039;t lose it at all if the admin toggles the setting off and on again. Isn&#039;t the life of a developer simple and wonderful?&lt;br /&gt;
&lt;br /&gt;
=== Exercise === &lt;br /&gt;
We will let this part of the tutorial come to a close with the obligatory exercise for the reader: &lt;br /&gt;
In order to have the SimpleHTML block work &amp;quot;correctly&amp;quot;, find out how to strengthen the eager approach to strip out all tags from the existing configuration of all instances of our block, &#039;&#039;&#039;or&#039;&#039;&#039; go back and implement the lazy approach instead. &lt;br /&gt;
(Hint: Do that in the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Eye Candy ==&lt;br /&gt;
&lt;br /&gt;
Our block is just about complete functionally, so now let&#039;s take a look at some of the tricks we can use to make its behavior customized in a few more useful ways.&lt;br /&gt;
&lt;br /&gt;
First of all, there are a couple of ways we can adjust the visual aspects of our block. For starters, it might be useful to create a block that doesn&#039;t display a header (title) at all. You can see this effect in action in the Course Description block that comes with Moodle. This behavior is achieved by, you guessed it, adding one more method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function hide_header() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One more note here: we cannot just set an empty title inside the block&#039;s [[Blocks/Appendix_A#init.28.29| init()]] method; it&#039;s necessary for each block to have a unique, non-empty title after [[Blocks/Appendix_A#init.28.29| init()]] is called so that Moodle can use those titles to differentiate between all of the installed blocks.&lt;br /&gt;
&lt;br /&gt;
Next, we can affect some properties of the actual HTML that will be used to print our block. Each block is fully contained within a &amp;amp;lt;div&amp;amp;gt; or &amp;amp;lt;table&amp;amp;gt; elements, inside which all the HTML for that block is printed. We can instruct Moodle to add HTML attributes with specific values to that container. This is generally done to give us freedom to customize the end result using CSS (this is in fact done by default as we&#039;ll see below).&lt;br /&gt;
&lt;br /&gt;
The default behavior of this feature in our case will modify our block&#039;s &amp;quot;class&amp;quot; HTML attribute by appending the value &amp;quot;block_simplehtml&amp;quot; (the prefix &amp;quot;block_&amp;quot; followed by the name of our block, lowercased). We can then use that class to make CSS selectors in our theme to alter this block&#039;s visual style (for example, &amp;quot;.block_simplehtml { border: 1px black solid}&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To change the default behavior, we will need to define a method which returns an associative array of attribute names and values. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function html_attributes() {&lt;br /&gt;
    $attributes = parent::html_attributes(); // Get default values&lt;br /&gt;
    $attributes[&#039;class&#039;] .= &#039; block_&#039;. $this-&amp;gt;name(); // Append our class to class attribute&lt;br /&gt;
    return $attributes;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This results in the block having all its normal HTML attributes, as inherited from the base block class, plus our additional class name. We can now use this class name to change the style of the block, add JavaScript events to it via YUI, and so on. And for one final elegant touch,  we have not set the class to the hard-coded value &amp;quot;block_simplehtml&amp;quot;, but instead used the [[Blocks/Appendix_A#name.28.29| name()]] method to make it dynamically match our block&#039;s name.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Authorized Personnel Only ==&lt;br /&gt;
&lt;br /&gt;
Some blocks are useful in some circumstances, but not in others. An example of this would be the &amp;quot;Social Activities&amp;quot; block, which is useful in courses with the &amp;quot;social&amp;quot; course format, but not courses with the &amp;quot;weeks&amp;quot; format. What we need to be able to do is limit our block&#039;s availability, so that it can only be selected on pages where its content or abilities are appropriate.&lt;br /&gt;
&lt;br /&gt;
Moodle allows us to declare which page formats a block is available on, and enforces these restrictions as set by the block&#039;s developer at all times. The information is given to Moodle as a standard associative array, with each key corresponding to a page format and defining a boolean value (true/false) that declares whether the block should be allowed to appear in that page format.&lt;br /&gt;
&lt;br /&gt;
Notice the deliberate use of the term &#039;&#039;page&#039;&#039; instead of &#039;&#039;course&#039;&#039; in the above paragraph. This is because in Moodle 1.5 and onwards, blocks can be displayed in any page that supports them. The best example of such pages are the course pages, but we are not restricted to them. For instance, the quiz view page (the first one we see when we click on the name of the quiz) also supports blocks.&lt;br /&gt;
&lt;br /&gt;
The format names we can use for the pages derive from the name of the script which is actually used to display that page. For example, when we are looking at a course, the script is &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/course/view.php&amp;lt;/span&amp;gt; (this is evident from the browser&#039;s address line). Thus, the format name of that page is &#039;&#039;&#039;course-view&#039;&#039;&#039;. It follows easily that the format name for a quiz view page is &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039;. This rule of thumb does have a few exceptions, however:&lt;br /&gt;
&lt;br /&gt;
# The format name for the front page of Moodle is &#039;&#039;&#039;site-index&#039;&#039;&#039;.&lt;br /&gt;
# The format name for courses is actually not just &#039;&#039;&#039;course-view&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;; it is &amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;course-view-weeks&#039;&#039;&#039;, &#039;&#039;&#039;course-view-topics&#039;&#039;&#039;, etc.&lt;br /&gt;
# Even though there is no such page, the format name &#039;&#039;&#039;all&#039;&#039;&#039; can be used as a catch-all option.&lt;br /&gt;
&lt;br /&gt;
We can include as many format names as we want in our definition of the applicable formats. Each format can be allowed or disallowed, and there are also three more rules that help resolve the question &amp;quot;is this block allowed into this page or not?&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
# Prefixes of a format name will match that format name; for example, &#039;&#039;&#039;mod&#039;&#039;&#039; will match all the activity modules. &#039;&#039;&#039;course-view&#039;&#039;&#039; will match any course, regardless of the course format. And finally, &#039;&#039;&#039;site&#039;&#039;&#039; will also match the front page (remember that its full format name is &#039;&#039;&#039;site-index&#039;&#039;&#039;).&lt;br /&gt;
# The more specialized a format name that matches our page is, the higher precedence it has when deciding if the block will be allowed. For example, &#039;&#039;&#039;mod&#039;&#039;&#039;, &#039;&#039;&#039;mod-quiz&#039;&#039;&#039; and &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; all match the quiz view page. But if all three are present, &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; will take precedence over the other two because it is a better match.&lt;br /&gt;
# The character &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; can be used in place of any word. For example, &#039;&#039;&#039;mod&#039;&#039;&#039; and &#039;&#039;&#039;mod-*&#039;&#039;&#039; are equivalent. At the time of this document&#039;s writing, there is no actual reason to utilize this &amp;quot;wildcard matching&amp;quot; feature, but it exists for future usage.&lt;br /&gt;
# The order that the format names appear does not make any difference.&lt;br /&gt;
All of the above are enough to make the situation sound complex, so let&#039;s look at some specific examples. First of all, to have our block appear &#039;&#039;&#039;only&#039;&#039;&#039; in the site front page, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&#039;site&#039; =&amp;gt; true);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Since &#039;&#039;&#039;all&#039;&#039;&#039; is missing, the block is disallowed from appearing in &#039;&#039;any&#039;&#039; course format; but then &#039;&#039;&#039;site&#039;&#039;&#039; is set to TRUE, so it&#039;s explicitly allowed to appear in the site front page (remember that &#039;&#039;&#039;site&#039;&#039;&#039; matches &#039;&#039;&#039;site-index&#039;&#039;&#039; because it&#039;s a prefix).&lt;br /&gt;
&lt;br /&gt;
For another example, if we wanted to allow the block to appear in all course formats &#039;&#039;except&#039;&#039; social, and also to &#039;&#039;not&#039;&#039; be allowed anywhere but in courses, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
    &#039;course-view-social&#039; =&amp;gt; false);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This time, we first allow the block to appear in all courses and then we explicitly disallow the social format.&lt;br /&gt;
For our final, most complicated example, suppose that a block can be displayed in the site front page, in courses (but not social courses) and also when we are viewing any activity module, &#039;&#039;except&#039;&#039; quiz. This would be:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;site-index&#039; =&amp;gt; true,&lt;br /&gt;
          &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
   &#039;course-view-social&#039; =&amp;gt; false,&lt;br /&gt;
                  &#039;mod&#039; =&amp;gt; true, &lt;br /&gt;
             &#039;mod-quiz&#039; =&amp;gt; false&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is not difficult to realize that the above accomplishes the objective if we remember that there is a &amp;quot;best match&amp;quot; policy to determine the end result.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Responding to Cron ==&lt;br /&gt;
&lt;br /&gt;
It is possible to have our block respond to the global Moodle cron process; we can have a method that is run at regular intervals regardless of user interaction. There are two parts to this. Firstly we need to define a new function within our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function cron() {&lt;br /&gt;
    mtrace( &amp;quot;Hey, my cron script is running&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
    // do something&lt;br /&gt;
&lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we will need to set the (minimum) execution interval for our cron function. Prior to Moodle 2.0, this was achieved by setting the value of a block&#039;s $this-&amp;gt;cron field, via the init() method. This is now achieved by adding an additional line to our &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039; file. Open it up and add the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $plugin-&amp;gt;cron = 300;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cron intervals are set in seconds, so the above line will set our minimum execution interval to 5 minutes. However, the function can only be called as frequently as cron has been set to run in the Moodle installation. So if our block is set to wait at least 5 minutes between runs, as in this example, but Moodle&#039;s cron system is only set to run every 24 hours, then our block is going to be waiting a lot longer between runs than we expected!&lt;br /&gt;
&lt;br /&gt;
Remember that if we change any values in the version file or block file we &#039;&#039;&#039;must&#039;&#039;&#039; bump the version number and visit the Notifications page to upgrade the block, otherwise they will be ignored.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039;&lt;br /&gt;
The block cron is designed to call the cron script for that block &#039;&#039;&#039;type&#039;&#039;&#039; only. That is, cron does not care about individual instances of blocks. Inside your cron function &#039;&#039;$this&#039;&#039; is defined, but it has almost nothing in it (only title and content fields are populated). If you need to execute cron for individual instances it is your own responsibility to iterate over them in the block&#039;s cron function. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function cron() {&lt;br /&gt;
&lt;br /&gt;
    global $DB; // Global database object&lt;br /&gt;
&lt;br /&gt;
    // Get the instances of the block&lt;br /&gt;
    $instances = $DB-&amp;gt;get_records( &#039;block_instance&#039;, array(&#039;blockid&#039;=&amp;gt;&#039;simplehtml&#039;) );&lt;br /&gt;
&lt;br /&gt;
    // Iterate over the instances&lt;br /&gt;
    foreach ($instances as $instance) {&lt;br /&gt;
&lt;br /&gt;
        // Recreate block object&lt;br /&gt;
        $block = block_instance(&#039;simplehtml&#039;, $instance);&lt;br /&gt;
&lt;br /&gt;
        // $block is now the equivalent of $this in &#039;normal&#039; block&lt;br /&gt;
        // usage, e.g.&lt;br /&gt;
        $someconfigitem = $block-&amp;gt;config-&amp;gt;item2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TIP: This also means that creating a block is a possible way to create code that can respond to cron with a reasonably low overhead. No actual instances of the block are required.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Additional Content Types == &lt;br /&gt;
&lt;br /&gt;
=== Lists ===&lt;br /&gt;
&lt;br /&gt;
In this final part of the guide we will briefly discuss several additional capabilities of Moodle&#039;s block system, namely the ability to create blocks that display different kinds of content to the user. The first of these creates a list of options and displays them to the user.  This list is displayed with one item per line, and an optional image (icon) next to the item. An example of such a &#039;&#039;list block&#039;&#039; is the standard Moodle &amp;quot;admin&amp;quot; block, which illustrates all the points discussed in this section.&lt;br /&gt;
&lt;br /&gt;
As we have seen so far, blocks use two properties of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]]: &amp;quot;text&amp;quot; and &amp;quot;footer&amp;quot;. The text is displayed as-is as the block content, and the footer is displayed below the content in a smaller font size. List blocks use $this-&amp;gt;content-&amp;gt;footer in the exact same way, but they ignore $this-&amp;gt;content-&amp;gt;text.&lt;br /&gt;
&lt;br /&gt;
Instead, Moodle expects such blocks to set two other properties when the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called: $this-&amp;gt;content-&amp;gt;items and $this-&amp;gt;content-&amp;gt;icons. $this-&amp;gt;content-&amp;gt;items should be a numerically indexed array containing elements that represent the HTML for each item in the list that is going to be displayed. Usually these items will be HTML anchor tags which provide links to some page. $this-&amp;gt;content-&amp;gt;icons should also be a numerically indexed array, with exactly as many items as $this-&amp;gt;content-&amp;gt;items has. Each of these items should be a fully qualified HTML &amp;lt;img&amp;gt; tag, with &amp;quot;src&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;width&amp;quot; and &amp;quot;alt&amp;quot; attributes. Obviously, it makes sense to keep the images small and of a uniform size. We would recommend standard 16x16 images for this purpose.&lt;br /&gt;
&lt;br /&gt;
In order to tell Moodle that we want to have a list block instead of the standard text block, we need to make a small change to our block class declaration. Instead of extending class &#039;&#039;&#039;block_base&#039;&#039;&#039;, our block will extend class &#039;&#039;&#039;block_list&#039;&#039;&#039;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
class block_my_menu extends block_list {&lt;br /&gt;
     // The init() method does not need to change at all&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition to making this change, we must of course also modify the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method to construct the [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] variable as discussed above:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function get_content() {&lt;br /&gt;
  if ($this-&amp;gt;content !== null) {&lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content         = new stdClass;&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items[] = html_writer::tag(&#039;a&#039;, &#039;Menu Option 1&#039;, array(&#039;href&#039; =&amp;gt; &#039;some_file.php&#039;));&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons[] = html_writer::empty_tag(&#039;img&#039;, array(&#039;src&#039; =&amp;gt; &#039;images/icons/1.gif&#039;, &#039;class&#039; =&amp;gt; &#039;icon&#039;));&lt;br /&gt;
&lt;br /&gt;
  // Add more list items here&lt;br /&gt;
 &lt;br /&gt;
  return $this-&amp;gt;content;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To summarise, if we want to create a list block instead of a text block, we just need to change the block class declaration and the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method. Adding the mandatory [[Blocks/Appendix_A#init.28.29| init()]] method as discussed earlier will then give us our first list block in no time!&lt;br /&gt;
&lt;br /&gt;
=== Trees ===&lt;br /&gt;
&lt;br /&gt;
As of 23rd December 2011, this functionality remains inoperable in all Moodle 2.x versions. It appears that classes are missing from the code base. This has been added to the tracker at the URL below. Please upvote this issue if you require this functionality.&lt;br /&gt;
&lt;br /&gt;
[http://tracker.moodle.org/browse/MDL-28289 Visit this issue on the tracker @ MDL28289]&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Database support ==&lt;br /&gt;
In case we need to have a database table that holds some specific information used within our block, we will need to create the file &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;install.xml&#039;&#039;&#039;&#039;&#039; with the table schema contained within it.&lt;br /&gt;
&lt;br /&gt;
To create the install.xml file, use the [[XMLDB editor]]. See [[Database_FAQ#XMLDB|Database FAQ &amp;gt; XMLDB]] for further details.&lt;br /&gt;
&lt;br /&gt;
Up-to-date documentation on upgrading our block, as well as providing new capabilities and events to the system, can be found under [https://docs.moodle.org/dev/Installing_and_upgrading_plugin_database_tables#install.php Installing and Upgrading Plugin Database Tables]&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Blocks Advanced]] A continuation of this tutorial.&lt;br /&gt;
* [http://dev.moodle.org/mod/resource/view.php?id=48 Unit 7 of the Introduction to Moodle Programming course] is a follow up to this course. (But you should follow the forum discussions of that course closely as there are still some bugs and inconsistencies.)&lt;br /&gt;
* A [http://cvs.moodle.org/contrib/plugins/blocks/NEWBLOCK/ NEWBLOCK template] you can all use to start you own block.&lt;br /&gt;
&lt;br /&gt;
== Appendices ==&lt;br /&gt;
&lt;br /&gt;
The appendices have been moved to separate pages:&lt;br /&gt;
&lt;br /&gt;
* Appendix A: [[Blocks/Appendix A|&#039;&#039;block_base&#039;&#039; Reference]] &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;br /&gt;
[[ja:開発:ブロック]]&lt;br /&gt;
[[:en:Blocks|Blocks]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Finding_your_way_into_the_Moodle_code&amp;diff=36331</id>
		<title>Finding your way into the Moodle code</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Finding_your_way_into_the_Moodle_code&amp;diff=36331"/>
		<updated>2012-11-13T10:10:37Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Tools that can help */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This article is aimed at people totally new to Moodle development and have some PHP experience, if you don&#039;t have that experience please visit [[PHP for novices|PHP for novices]]. It is a few tips to help you get started with the mass of Moodle code.&lt;br /&gt;
&lt;br /&gt;
Please feel free to add more tips here, but I think it is also good if we can keep this article quite short.&lt;br /&gt;
&lt;br /&gt;
==Developer documentation==&lt;br /&gt;
&lt;br /&gt;
If you have not already found it, the main source of developer documentation is [[Developer_documentation]].&lt;br /&gt;
&lt;br /&gt;
==Finding a way in==&lt;br /&gt;
&lt;br /&gt;
For finding where to start, you need to know that when you are looking at, for example, http://moodle.org/mod/forum/discuss.php?d=82799, then the code for that is in /mod/forum/discuss.php, and you just need to follow through what it does.&lt;br /&gt;
&lt;br /&gt;
It calls functions in the main Moodle libraries, and the three most important are:&lt;br /&gt;
&lt;br /&gt;
*lib/moodlelib.php - general stuff.&lt;br /&gt;
*lib/weblib.php - things to do with output of HTML&lt;br /&gt;
*lib/dmllib.php - things to do with getting data in and out of the database.&lt;br /&gt;
&lt;br /&gt;
==Understanding what you find==&lt;br /&gt;
&lt;br /&gt;
As you look at the code, it is often a good idea, to insert statements like&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 debugging(&#039;In function require_login&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
which will print the message above if it gets far enough so you know the code has not stalled before there, or&lt;br /&gt;
 print_object($course);&lt;br /&gt;
which will print out a variable, showing you what it contains. &lt;br /&gt;
&lt;br /&gt;
Variable like $course are often objects with lots of fields. Seeing what they contain will help you understand what is going on. The first of these prints out whatever text you give it, and information about the sequence of function calls that the code took to get there. (It only works if you go to &#039;&#039;Administration &amp;gt; Server &amp;gt; [[:en:Debugging|Debugging]]&#039;&#039;, and turn the debug level to ALL or DEVELOPER.)&lt;br /&gt;
&lt;br /&gt;
==Tools that can help==&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Eclipse&#039;&#039;&#039;, for instance helps finding function definitions. You can hold down CTRL and click on the name of a function, it immediately jumps you to where that function is defined. ([[Setting_up_Eclipse]])&lt;br /&gt;
*&#039;&#039;&#039;Netbeans&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Sublime 2&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Emacs&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Vim&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;TextMate&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See also [[Developer documentation#Tools]] and [[:Category:Developer tools]].&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [http://dev.moodle.org/course/view.php?id=2 Introduction to Moodle Programming] a course at dev.moodle.org&lt;br /&gt;
* [[Development FAQ]]&lt;br /&gt;
* [[Developer_documentation]]&lt;br /&gt;
* [[Overview]]&lt;br /&gt;
* [[ctags]]&lt;br /&gt;
* [http://blog.danpoltawski.co.uk/archives/2009-05-Secrets-of-Learning-Moodle-Development!.html &amp;quot;Secrets of Learning Moodle Development!&amp;quot;] by Moodle core developer [[User:Dan Poltawski| Dan Poltawski]]&lt;br /&gt;
* [http://www.slideshare.net/tjh1000/a-basic-introduciton-to-the-moodle-architecture-5442122 A basic introduction to the Moodle architecture] by Moodle core developer Tim Hunt&lt;br /&gt;
* [http://www.aosabook.org/en/moodle.html The Architecture of Open Source Applications: Moodle] by Tim Hunt&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Database_collation_issue&amp;diff=36330</id>
		<title>Database collation issue</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Database_collation_issue&amp;diff=36330"/>
		<updated>2012-11-13T10:07:31Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Transitional period (minor) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Database collation issue&lt;br /&gt;
|state = Specification in progress&lt;br /&gt;
|tracker = MDL-36208&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=214564&lt;br /&gt;
|assignee = &#039;&#039;Hero required&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
&lt;br /&gt;
Database store text data using a particular &#039;&#039;&#039;character set&#039;&#039;&#039;. Moodle uses UTF-8, which is a good thing, since UTF-8 can represent almost any character ever.&lt;br /&gt;
&lt;br /&gt;
Text data is also stored with an associated &#039;&#039;&#039;collation&#039;&#039;&#039;. This affects how the values are sorted and compared. For example, different languages have different sort-orders, which depend on which alphabet they use. For example in German the &#039;&#039;&#039;ß&#039;&#039;&#039; character should come just after &#039;&#039;&#039;S&#039;&#039;&#039; (and &#039;&#039;&#039;s&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Collations typically come in two forms, case sensitive, and case-insensitive. If you are using a case-insensitive collation, then not only do &#039;x&#039; and &#039;X&#039; get sorted the same, but actually, the database thinks that &#039;x&#039; = &#039;X&#039;.&lt;br /&gt;
&lt;br /&gt;
Operations like JOINs are typically much faster if both tables (columns) use the same collation.&lt;br /&gt;
&lt;br /&gt;
== The problems ==&lt;br /&gt;
&lt;br /&gt;
=== Collation should depend on current language ===&lt;br /&gt;
&lt;br /&gt;
On multi-lingual sites like [https://moodle.org/ moodle.org], different users will all expect reports to be sorted according to their language&#039;s collation rules. If we just specify the collation in database table definition, then all queries for all users have to use the same collation.&lt;br /&gt;
&lt;br /&gt;
Typical bugs:&lt;br /&gt;
* MDL-30446 Glossary order issues for some collation settings (Postgres)&lt;br /&gt;
&lt;br /&gt;
=== Machine-readable identifiers ===&lt;br /&gt;
&lt;br /&gt;
Moodle stores two sorts for text data:&lt;br /&gt;
* user-visible strings like user.firstname, user.lastname or course.fullname&lt;br /&gt;
* machine-readable identifiers like user.username, course.idnumber or file.filepath&lt;br /&gt;
&lt;br /&gt;
For machine-readable identifiers, the &#039;x&#039; == &#039;X&#039;, or worse &#039;e&#039; == &#039;é&#039; behaviour is really bad, particularly if you want to put a unique index on the column in question. It has lead to bugs like:&lt;br /&gt;
* MDL-29332 Calculated Questions Require Case Sensitive Data Tables (MySQL)&lt;br /&gt;
* MDL-33655 MySQL case insensitivity breaks get_directory_files (MySQL)&lt;br /&gt;
* MDL-34271 improve mysql collation handling&lt;br /&gt;
&lt;br /&gt;
=== MySQL only has localised collations that are case-insensitive ===&lt;br /&gt;
&lt;br /&gt;
If you look at the list of [https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-sets.html MySQL collations], you will see that the only collations that give correctly locale-aware ordering are case-insensitive (the ci bit in utf8_czech_ci), and so suffer from the &#039;x&#039; == &#039;X&#039; and &#039;e&#039; == &#039;é&#039; problem. The only collation that does not have this problem is utf8_bin, which is not the order people want to see.&lt;br /&gt;
&lt;br /&gt;
== Outline solution ==&lt;br /&gt;
&lt;br /&gt;
The proposed solution is simple in outline:&lt;br /&gt;
# Store all data in database tables that use a case-sentistive collation (e.g. utf8_bin).&lt;br /&gt;
# Change all ORDER BY clauses in all SQL that sort text, to specify the correct sort collation, based on the current language.&lt;br /&gt;
&lt;br /&gt;
To support that second part, we will need some helper code, for example, each language pack must specify the right collation to use, for each supported database, for example using new strings in langconfig.php. We will also need an $DB-&amp;gt;sql_order_by_text($column) helper function to return the right SQL fragment like &amp;quot;columnname COLLATE utf8_czech_ci&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Difficulties with the proposed solution ==&lt;br /&gt;
&lt;br /&gt;
=== Transitional period (minor) ===&lt;br /&gt;
&lt;br /&gt;
In the transitional period, when the table definitions have been updated to use a collation like utf8_bin, but before we have found and fixed all SQL queries in Moodle core (and in all third-party plugins) to use sql_order_by_text, then the worst that can happen is that the results of some reports appear in a slightly odd order for some users. The reports will still basically work.&lt;br /&gt;
&lt;br /&gt;
Whenever a problem like this is detected, it will be easy to add the necessary sql_order_by_text call to the code to fix it.&lt;br /&gt;
&lt;br /&gt;
=== Time to do the upgrade (moderate) ===&lt;br /&gt;
&lt;br /&gt;
The amount of time required to upgrade all tables to a new collation is going to be comparable to the time required for the change that changed all unsigned int columns to signed. This was an issue for some large sites.&lt;br /&gt;
&lt;br /&gt;
Like dropping unsigned columns, this is probably a necessary evil that we can live with.&lt;br /&gt;
&lt;br /&gt;
=== Backwards compatibility of identifiers (severe) ===&lt;br /&gt;
&lt;br /&gt;
This is the most serious problem. It affects areas like:&lt;br /&gt;
* What are valid user names? Are user names case-sensitive.&lt;br /&gt;
* For people using integrations like the database authentication and enrolment plugins, or CVS import, it may be that at the moment, the identifiers currently match using case-insensitive collation, but if we changed the database collation to utf8_bin, then things would not longer match. This could cause a real mess.&lt;br /&gt;
&lt;br /&gt;
So, we may have to add an admin option for these areas, where admins can choose if they want case-sensitive or case-insenstivive collations. Then, if they choose case-insensitive collation for backwards compatibility, we will have to add explicit LOWER(...) or COLLATE calls to the code, to maintain the current behaviour.&lt;br /&gt;
&lt;br /&gt;
Here the risk is not just wrong sorting of reports, but it could badly break sites data integration. Hence, the risks if we get this wrong is very severe.&lt;br /&gt;
&lt;br /&gt;
We do not yet have a good solution to this problem.&lt;br /&gt;
&lt;br /&gt;
[[Category:Project]]&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=36121</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=36121"/>
		<updated>2012-11-08T08:42:59Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039; A Step-by-step Guide To Creating Blocks &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Original Author: Jon Papaioannou ([mailto:pj@moodle.org pj@moodle.org])&lt;br /&gt;
&lt;br /&gt;
Updated to Moodle 2.0 and above by: Greg J Preece ([mailto:greg.preece@blackboard.com greg.preece@blackboard.com])&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
The present document serves as a guide to developers who want to create their own blocks for use in Moodle. It applies to the 2.0 development version of Moodle (and any newer) &#039;&#039;&#039;only&#039;&#039;&#039;, as the blocks API changed significantly enough to warrant new documentation. Those wishing to read the old tutorial for Moodles 1.5 to 1.9 can find it under [[Blocks/Blocks for 1.5 to 1.9| Blocks for 1.5 to 1.9]].&lt;br /&gt;
&lt;br /&gt;
The guide is written as an interactive course which aims to develop a configurable, multi-purpose block that displays arbitrary HTML. It&#039;s targeted mainly at people with little experience with Moodle or programming in general and aims to show how easy it is to create new blocks for Moodle. A certain small amount of PHP programming knowledge is still required, though. &lt;br /&gt;
&lt;br /&gt;
Experienced developers and those who just want a &#039;&#039;&#039;programmer&#039;s reference&#039;&#039;&#039; text should refer to [[Blocks/Appendix_A| Appendix A]] because the main guide has a rather low concentration of pure information in the text.&lt;br /&gt;
&lt;br /&gt;
== Basic Concepts ==&lt;br /&gt;
&lt;br /&gt;
Through this guide, we will be following the creation of an &amp;quot;HTML&amp;quot; block from scratch in order to demonstrate most of the block features at our disposal. Our block will be named &amp;quot;SimpleHTML&amp;quot;. This does not constrain us regarding the name of the actual directory on the server where the files for our block will be stored, but for consistency we will follow the practice of using the lowercased form &amp;quot;simplehtml&amp;quot; in any case where such a name is required. &lt;br /&gt;
&lt;br /&gt;
Whenever we refer to a file or directory name which contains &amp;quot;simplehtml&amp;quot;, it&#039;s important to remember that &#039;&#039;only&#039;&#039; the &amp;quot;simplehtml&amp;quot; part is up to us to change; the rest is standardised and essential for Moodle to work correctly.&lt;br /&gt;
&lt;br /&gt;
Whenever a file&#039;s path is mentioned in this guide, it will always start with a slash. This refers to the Moodle home directory; all files and directories will be referred to with respect to that directory.&lt;br /&gt;
&lt;br /&gt;
== Ready, Set, Go! ==&lt;br /&gt;
&lt;br /&gt;
To define a &amp;quot;block&amp;quot; in Moodle, in the most basic case we need to provide just four PHP files. Remember, in this example we are creating a block called &#039;simplehtml&#039;, replace &#039;simplehtml&#039; with the name of your custom block. The four files should be located in blocks/simplehtml and are:&lt;br /&gt;
&lt;br /&gt;
=== block_simplehtml.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold the class definition for the block, and is used both to manage it as a plugin and to render it onscreen.&lt;br /&gt;
&lt;br /&gt;
We start by creating the main object file, &#039;block_simplehtml.php&#039;. We then begin coding the block:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class block_simplehtml extends block_base {&lt;br /&gt;
    public function init() {&lt;br /&gt;
        $this-&amp;gt;title = get_string(&#039;simplehtml&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    // The PHP tag and the curly bracket for the class definition &lt;br /&gt;
    // will only be closed after there is another function added in the next section.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first line is our block class definition; it must be named exactly in the manner shown. Again, only the &amp;quot;simplehtml&amp;quot; part can (and indeed must) change; everything else is standardised.&lt;br /&gt;
&lt;br /&gt;
Our class is then given a small method: [[Blocks/Appendix_A#init.28.29| init()]]. This is essential for all blocks, and its purpose is to give values to any class member variables that need instantiating. &lt;br /&gt;
&lt;br /&gt;
In this very basic example, we only want to set [[Blocks/Appendix_A#.24this-.3Etitle| $this-&amp;gt;title]], which is the title displayed in the header of our block. We can set it to whatever we like; in this case it&#039;s set to read the actual title from the language file mentioned previously, which is then distributed along with the block. I&#039;ll skip ahead a bit here and say that if you want your block to display &#039;&#039;&#039;no&#039;&#039;&#039; title at all, then you should set this to any descriptive value you want (but &#039;&#039;&#039;not&#039;&#039;&#039; make it an empty string). We will later see [[Blocks#Eye_Candy|how to disable the title&#039;s display]].&lt;br /&gt;
&lt;br /&gt;
=== db/access.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold the new capabilities created by the block.&lt;br /&gt;
&lt;br /&gt;
Moodle 2.4 onwards introduced the capabilities addinstance and myaddinstance for each core block. They were introduced so that it was possible to control the use of individual blocks. These capabilities should also be added to your custom block, so in this case to the file blocks/simplehtml/db/access.php. If your block is not going to be used in the &#039;My Moodle page&#039; (ie, your applicable_formats function (discussed later) has &#039;my&#039; set to false.) then the myaddinstance capability is not required. The following is the capabilities array and how it should look for any new blocks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:myaddinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_SYSTEM,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;user&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/my:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_SPAM | RISK_XSS,&lt;br /&gt;
&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_BLOCK,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/site:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== lang/en/block_simplehtml.php ===&lt;br /&gt;
&lt;br /&gt;
This is the English language file for your block. If you are not an English speaker, you can replace &#039;en&#039; with your appropriate language code. All language files for blocks go under the /lang subfolder of the block&#039;s installation folder.&lt;br /&gt;
&lt;br /&gt;
Moodle 2.0 and above require a name for our plugin to show in the upgrading page. We set this value, along with any other language strings we wish to use within the block, in a language package as previously mentioned (the same file where we put our string for the plugin title).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Simple html block&#039;;&lt;br /&gt;
$string[&#039;simplehtml&#039;] = &#039;Simple html&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold version information for the plugin, along with other advanced parameters (not covered here - see [[version.php]] if you want more details).&lt;br /&gt;
&lt;br /&gt;
Prior to Moodle 2.0, version details for blocks were stored as class fields; as of Moodle 2.0 these are stored in a file called version.php, stored under &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039;. The version file is very simple indeed, containing only a few field definitions, depending on your needs. Here is an example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$plugin-&amp;gt;version = 2011062800;  // YYYYMMDDHH (year, month, day, 24-hr time)&lt;br /&gt;
$plugin-&amp;gt;requires = 2010112400; // YYYYMMDDHH (This is the release version for Moodle 2.0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file contains object field definitions that denote the version number of the block, along with the minimum version of Moodle that must be installed in order to use it. Please note that the object being used here is &#039;&#039;always&#039;&#039; called &#039;&#039;&#039;$plugin&#039;&#039;&#039;, and that you do not need to create this object yourself within the version file. Note also we don&#039;t include a closing &amp;quot;?&amp;gt;&amp;quot; tag. This is intentional, and a [[Coding_style#PHP_tags | workaround for whitespace issues]].&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== I Just Hear Static ==&lt;br /&gt;
In order to get our block to actually display something on screen, we need to add one more method to our class (before the final closing brace in our file). The new code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;  &lt;br /&gt;
  public function get_content() {&lt;br /&gt;
    if ($this-&amp;gt;content !== null) {&lt;br /&gt;
      return $this-&amp;gt;content;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;content         =  new stdClass;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text   = &#039;The content of our SimpleHTML block!&#039;;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
}   // Here&#039;s the closing bracket for the class definition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Add your block to the front page!&#039;&#039;&#039;&lt;br /&gt;
Don&#039;t forget (especially if you&#039;re a new Moodle user) to add your block to the front page. Turn Editing On, and add your block to the page.&lt;br /&gt;
&lt;br /&gt;
It can&#039;t get any simpler than that, can it? Let&#039;s dissect this method to see what&#039;s going on...&lt;br /&gt;
&lt;br /&gt;
First of all, there is a check that returns the current value of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] if it&#039;s not NULL; otherwise we proceed with &amp;quot;computing&amp;quot; it. Since the computation is potentially a time-consuming operation and it &#039;&#039;&#039;will&#039;&#039;&#039; be called several times for each block (Moodle works that way internally), we take a precaution and include this time-saver.&lt;br /&gt;
Supposing the content had not been computed before (it was NULL), we then define it from scratch. The code speaks for itself there, so there isn&#039;t much to say. Just keep in mind that we can use HTML both in the text &#039;&#039;&#039;and&#039;&#039;&#039; in the footer, if we want to.&lt;br /&gt;
&lt;br /&gt;
It&#039;s worth mentioning that this is not the only type of content a block can output. You can also create lists and hierarchical trees, which are better suited for certain types of output, such as menus. These different content types have an impact on the content object and how it is constructed. For more information, see [[Blocks/Appendix A#.24this-.3Econtent_type|Appendix A]]&lt;br /&gt;
&lt;br /&gt;
At this point our block should be capable of being automatically installed in Moodle and added to courses; visit your administration page to install it (Click &amp;quot;Notifications&amp;quot; under the Site Administration Block) and after seeing it in action come back to continue our tutorial.&lt;br /&gt;
&lt;br /&gt;
== Configure That Out ==&lt;br /&gt;
&lt;br /&gt;
The current version of our block doesn&#039;t really do much; it just displays a fixed message, which is not very useful. What we&#039;d really like to do is allow the teachers to customize what goes into the block. This, in block-speak, is called &amp;quot;instance configuration&amp;quot;. Basic instance configuration is automatic in Moodle 2.0; if you put any page with blocks on it into &amp;quot;editing mode&amp;quot;, you will notice that each block has an edit button in its title bar. Clicking on this will take you to the block configuration form. The settings that Moodle adds to this form by default relate to the block&#039;s appearance and position on Moodle pages. &lt;br /&gt;
&lt;br /&gt;
We can extend this configuration form, and add custom preferences fields, so that users can better tailor our block to a given task or page. To extend the configuration form, create the file &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&amp;lt;/span&amp;gt;, and fill it with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class block_simplehtml_edit_form extends block_edit_form {&lt;br /&gt;
        &lt;br /&gt;
    protected function specific_definition($mform) {&lt;br /&gt;
        &lt;br /&gt;
        // Section header title according to language file.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;configheader&#039;, get_string(&#039;blocksettings&#039;, &#039;block&#039;));&lt;br /&gt;
&lt;br /&gt;
        // A sample string variable with a default value.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_text&#039;, get_string(&#039;blockstring&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;config_text&#039;, &#039;default value&#039;);&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;config_text&#039;, PARAM_MULTILANG);        &lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The first line declares a class that inherits &#039;&#039;&#039;from block_edit_form&#039;&#039;&#039;, and this allows Moodle to identify the code to execute in the configuration page. The &#039;&#039;&#039;specific_definition()&#039;&#039;&#039; method is where your form elements are defined, and these take the same format as with the standard [[lib/formslib.php_Form_Definition|Moodle form library]].  Within our specific_definition method, we have created a header, and an input field which will accept text to be used within the block.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; All your field names need to start with &amp;quot;config_&amp;quot;, otherwise they will not be saved and will not be available within the block via [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]]. &lt;br /&gt;
&lt;br /&gt;
So once our instance configuration form has been saved, we can use the inputted text within the block like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (! empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text = $this-&amp;gt;config-&amp;gt;text;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] is available in all block methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]. This is because [[Blocks/Appendix_A#init.28.29|init()]] is called immediately as the block is being created, with the purpose of setting things up, so [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] has not yet been instantiated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note about Checkbox:&#039;&#039;&#039; You cannot use the &#039;checkbox&#039; element in the form (once set it will stay set). You must use advcheckbox instead. &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Specialists ==&lt;br /&gt;
&lt;br /&gt;
Implementing instance configuration for the block&#039;s contents was good enough to whet our appetite, but who wants to stop there? Why not customize the block&#039;s title, too?&lt;br /&gt;
&lt;br /&gt;
Why not, indeed. Well, our first attempt to achieve this is natural enough: let&#039;s add another field to &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&#039;&#039;. Here goes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // A sample string variable with a default value.&lt;br /&gt;
    $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_title&#039;, get_string(&#039;blocktitle&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
    $mform-&amp;gt;setDefault(&#039;config_title&#039;, &#039;default value&#039;);&lt;br /&gt;
    $mform-&amp;gt;setType(&#039;config_title&#039;, PARAM_MULTILANG);        &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We save the edited file, go to a course, edit the title of the block and... nothing happens! The instance configuration is saved correctly, all right (editing it once more proves that) but it&#039;s not being displayed. All we get is just the simple &amp;quot;SimpleHTML&amp;quot; title.&lt;br /&gt;
&lt;br /&gt;
That&#039;s not too weird, if we think back a bit. Do you remember that [[Blocks/Appendix_A#init.28.29|init()]] method, where we set [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]]? We didn&#039;t actually change its value from then, and [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] is definitely not the same as &#039;&#039;&#039;$this-&amp;gt;config-&amp;gt;title&#039;&#039;&#039; (to Moodle, at least). What we need is a way to update [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] with the value in the instance configuration. But as we said a bit earlier, we can use [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] in all methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]! So what can we do?&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pull out another ace from our sleeve, and add this small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function specialization() {&lt;br /&gt;
  if (!empty($this-&amp;gt;config-&amp;gt;title)) {&lt;br /&gt;
    $this-&amp;gt;title = $this-&amp;gt;config-&amp;gt;title;&lt;br /&gt;
  } else {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;title = &#039;Default title ...&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;text = &#039;Default text ...&#039;;&lt;br /&gt;
  }    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aha, here&#039;s what we wanted to do all along! But what&#039;s going on with the [[Blocks/Appendix_A#specialization.28.29| specialization()]] method?&lt;br /&gt;
&lt;br /&gt;
This &amp;quot;magic&amp;quot; method has actually a very nice property: it&#039;s &#039;&#039;guaranteed&#039;&#039; to be automatically called by Moodle as soon as our instance configuration is loaded and available (that is, immediately after [[Blocks/Appendix_A#init.28.29|init()]] is called). That means before the block&#039;s content is computed for the first time, and indeed before &#039;&#039;anything&#039;&#039; else is done with the block. Thus, providing a [[Blocks/Appendix_A#specialization.28.29| specialization()]] method is the natural choice for any configuration data that needs to be acted upon or made available &amp;quot;as soon as possible&amp;quot;, as in this case.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Now You See Me, Now You Don&#039;t ==&lt;br /&gt;
&lt;br /&gt;
Now would be a good time to mention another nifty technique that can be used in blocks, and which comes in handy quite often. Specifically, it may be the case that our block will have something interesting to display some of the time; but in some other cases, it won&#039;t have anything useful to say. An example here would be the &amp;quot;Recent Activity&amp;quot; block, in the case where no recent activity in fact exists. &lt;br /&gt;
&lt;br /&gt;
However in that case the block chooses to explicitly inform you of the lack of said activity, which is arguably useful. It would be nice, then, to be able to have our block &amp;quot;disappear&amp;quot; if it&#039;s not needed to display it.&lt;br /&gt;
&lt;br /&gt;
This is indeed possible, and the way to do it is to make sure that after the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called, the block has no content to display. This means that all fields in $this-&amp;gt;content should be equal to the empty string (&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;). In the case of our HTML-based block, these fields are $this-&amp;gt;content-&amp;gt;text and $this-&amp;gt;content-&amp;gt;footer. Moodle performs this check by calling the block&#039;s [[Blocks/Appendix_A#is_empty.28.29| is_empty()]] method, and if the block is indeed empty then it is not displayed at all.&lt;br /&gt;
&lt;br /&gt;
Note that the exact value of the block&#039;s title and the presence or absence of a [[Blocks/Appendix_A#hide_header.28.29| hide_header()]] method do &#039;&#039;not&#039;&#039; affect this behavior. A block is considered empty if it has no content, irrespective of anything else.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== We Are Legion ==&lt;br /&gt;
&lt;br /&gt;
Right now our block is fully configurable, both in title and content. It&#039;s so versatile, in fact, that we could make pretty much anything out of it. It would be really nice to be able to add multiple blocks of this type to a single course. And, as you might have guessed, doing that is as simple as adding another small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_allow_multiple() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells Moodle that it should allow any number of instances of the SimpleHTML block in any course. After saving the changes to our file, Moodle immediately allows us to add multiple copies of the block without further ado!&lt;br /&gt;
&lt;br /&gt;
Please note that even if a block itself allows multiple instances in the same page, the administrator still has the option of disallowing such behavior. This setting can be set separately for each block from the Administration / Configuration / Blocks page.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Effects of Globalization ==&lt;br /&gt;
&lt;br /&gt;
Configuring each block instance with its own personal data is cool enough, but sometimes administrators need some way to &amp;quot;touch&amp;quot; all instances of a specific block at the same time. In the case of our SimpleHTML block, a few settings that would make sense to apply to all instances aren&#039;t that hard to come up with. &lt;br /&gt;
&lt;br /&gt;
For example, we might want to limit the contents of each block to only so many characters, or we might have a setting that filters HTML out of the block&#039;s contents, only allowing pure text in. Granted, such a feature wouldn&#039;t win us any awards for naming our block &amp;quot;SimpleHTML&amp;quot; but some tormented administrator somewhere might actually find it useful.&lt;br /&gt;
&lt;br /&gt;
This kind of configuration is called &amp;quot;global configuration&amp;quot; and applies only to a specific block type (all instances of that block type are affected, however).  Implementing such configuration for our block is quite similar to implementing the instance configuration. We will now see how to implement the second example, having a setting that only allows text and not HTML in the block&#039;s contents. To enable global configuration for the block, we create a new file, &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;settings.php&#039;&#039;&#039;&#039;&#039;, and populate it with form field definitions for each setting, which Moodle will use to generate and handle a global settings form.  This is quite similar in concept to how we generated the instance configuration form earlier, but the actual code used to generate the form and fields is somewhat different.&lt;br /&gt;
&lt;br /&gt;
Place the following in your settings.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_heading(&lt;br /&gt;
            &#039;headerconfig&#039;,&lt;br /&gt;
            get_string(&#039;headerconfig&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descconfig&#039;, &#039;block_simplehtml&#039;)&lt;br /&gt;
        ));&lt;br /&gt;
&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_configcheckbox(&lt;br /&gt;
            &#039;simplehtml/Allow_HTML&#039;,&lt;br /&gt;
            get_string(&#039;labelallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            &#039;0&#039;&lt;br /&gt;
        ));    &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, to generate a global configuration form, we simply create admin setting objects and add them to an array. This array is then stepped over to create the settings form, and the inputted data is automatically saved to the database. Full details of the setting types available and how to add them can be found under [[Admin_settings#Individual_settings]].&lt;br /&gt;
&lt;br /&gt;
We&#039;ve now created a header and checkbox form element to accept configuration details from the site admin. You should pay extra attention to the name of our checkbox element, &#039;&#039;&#039; &#039;simplehtml/Allow_HTML&#039; &#039;&#039;&#039;, as it specifies not only the name of the configuration option, but also how it should be stored. If you simply specify a name for the config option, it will be stored in the global $CFG object, and in the &#039;&#039;&amp;lt;prefix&amp;gt;_config&#039;&#039; database table. This will make your config variable available immediately via $CFG without requiring an additional database call, but will also increase the size of the $CFG object. In addition, we must prefix the variable with the name of our block, otherwise we run the risk of our config variable sharing its name with a similar variable in another plugin, or within Moodle itself.&lt;br /&gt;
&lt;br /&gt;
The preferred method of storing your block&#039;s configuration data is to prefix each config variable name in your settings.php file with your block&#039;s name, followed by a slash ( / ), and the name of the configuration variable, as we have done above. If you write your settings.php file in this way, then your variables will be stored in the &#039;&#039;&amp;lt;prefix&amp;gt;_config_plugin&#039;&#039; table, under your block&#039;s name. Your config data will still be available via a &#039;&#039;&#039;get_config()&#039;&#039;&#039; call, and name collision will be impossible between plugins.&lt;br /&gt;
&lt;br /&gt;
Finally, if you&#039;re wondering why there are two language tags specified for each element, the first tag is for the element&#039;s label or primary text, and the second tag is for its description. And that&#039;s it. Pretty easy, huh?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE FOR UPGRADERS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You&#039;ll notice that the settings.php file and parsed element names replaces Moodle&#039;s old storage method, wherein it would send all the configuration data to your block&#039;s [[Blocks/Appendix_A#config_save.28.29|config_save()]] method, and allow you to override how the data is saved. The [[Blocks/Appendix_A#config_save.28.29|config_save()]] method is no longer used in Moodle 2.x; however the [[Blocks/Appendix_A#instance_config_save.28.29|instance_config_save()]] method is very much alive and well, as you will see shortly.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Global Config Data  ===&lt;br /&gt;
&lt;br /&gt;
Now that we have global data defined for the plugin, we need to know how to access it within our code.  If you saved your config variables in the global namespace, you can access them from the global $CFG object, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = $CFG-&amp;gt;Allow_HTML;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If, as recommended, you saved your config variables in a custom namespace for your block, then you can access them via a call to &#039;&#039;&#039;get_config()&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Rolling It All Together ===&lt;br /&gt;
&lt;br /&gt;
OK, so we now have an instance configuration form that allows users to enter custom content text for a block, and a global configuration option that dictates whether or not that user should be allowed to enter HTML tags as part of the content. Now we just need to tie the two together. But if Moodle takes care of the form processing for our instance configuration in edit_form.php, how can we capture it and remove the HTML tags where required?&lt;br /&gt;
&lt;br /&gt;
Well, fortunately, there is a way this can be done.  By overriding the [[Blocks/Appendix_A#instance_config_save.28.29| instance_config_save()]] method in our block class, we can modify the way in which instance configuration data is stored after input. The default implementation is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data) {&lt;br /&gt;
  $data = stripslashes_recursive($data);&lt;br /&gt;
  $this-&amp;gt;config = $data;&lt;br /&gt;
  return set_field(&#039;block_instance&#039;, &lt;br /&gt;
                   &#039;configdata&#039;,&lt;br /&gt;
                    base64_encode(serialize($data)),&lt;br /&gt;
                   &#039;id&#039;, &lt;br /&gt;
                   $this-&amp;gt;instance-&amp;gt;id);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may look intimidating at first (what&#039;s all this stripslashes_recursive() and base64_encode() and serialize() stuff?) but do not despair; we won&#039;t have to touch any of it. We will only add some extra validation code in the beginning and then instruct Moodle to additionally call this default implementation to do the actual storing of the data. Specifically, we will add a method to our class which goes like this:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data) {&lt;br /&gt;
  if(get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;) == &#039;1&#039;) {&lt;br /&gt;
    $data-&amp;gt;text = strip_tags($data-&amp;gt;text);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // And now forward to the default implementation defined in the parent class&lt;br /&gt;
  return parent::instance_config_save($data);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(This example assumes you are using a custom namespace for the block.)&lt;br /&gt;
&lt;br /&gt;
At last! Now the administrator has absolute power of life and death over what type of content is allowed in our &amp;quot;SimpleHTML&amp;quot; block! Absolute? Well... not exactly. In fact, if we think about it for a while, it will become apparent that if at some point in time HTML is allowed and some blocks have saved their content with HTML included, and afterwards the administrator changes the setting to &amp;quot;off&amp;quot;, this will only prevent subsequent content changes from including HTML. Blocks which already had HTML in their content would continue to display it!&lt;br /&gt;
&lt;br /&gt;
Following that train of thought, the next stop is realizing that we wouldn&#039;t have this problem if we had chosen the lazy approach a while back, because in that case we would &amp;quot;sanitize&amp;quot; each block&#039;s content just before it was displayed. &lt;br /&gt;
&lt;br /&gt;
The only thing we can do with the eager approach is strip all the tags from the content of all SimpleHTML instances as soon as the admin setting is changed to &amp;quot;HTML off&amp;quot;; but even then, turning the setting back to &amp;quot;HTML on&amp;quot; won&#039;t bring back the tags we stripped away. On the other hand, the lazy approach might be slower, but it&#039;s more versatile; we can choose whether to strip or keep the HTML before displaying the content, and we won&#039;t lose it at all if the admin toggles the setting off and on again. Isn&#039;t the life of a developer simple and wonderful?&lt;br /&gt;
&lt;br /&gt;
=== Exercise === &lt;br /&gt;
We will let this part of the tutorial come to a close with the obligatory exercise for the reader: &lt;br /&gt;
In order to have the SimpleHTML block work &amp;quot;correctly&amp;quot;, find out how to strengthen the eager approach to strip out all tags from the existing configuration of all instances of our block, &#039;&#039;&#039;or&#039;&#039;&#039; go back and implement the lazy approach instead. &lt;br /&gt;
(Hint: Do that in the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Eye Candy ==&lt;br /&gt;
&lt;br /&gt;
Our block is just about complete functionally, so now let&#039;s take a look at some of the tricks we can use to make its behavior customized in a few more useful ways.&lt;br /&gt;
&lt;br /&gt;
First of all, there are a couple of ways we can adjust the visual aspects of our block. For starters, it might be useful to create a block that doesn&#039;t display a header (title) at all. You can see this effect in action in the Course Description block that comes with Moodle. This behavior is achieved by, you guessed it, adding one more method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function hide_header() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One more note here: we cannot just set an empty title inside the block&#039;s [[Blocks/Appendix_A#init.28.29| init()]] method; it&#039;s necessary for each block to have a unique, non-empty title after [[Blocks/Appendix_A#init.28.29| init()]] is called so that Moodle can use those titles to differentiate between all of the installed blocks.&lt;br /&gt;
&lt;br /&gt;
Next, we can affect some properties of the actual HTML that will be used to print our block. Each block is fully contained within a &amp;amp;lt;div&amp;amp;gt; or &amp;amp;lt;table&amp;amp;gt; elements, inside which all the HTML for that block is printed. We can instruct Moodle to add HTML attributes with specific values to that container. This is generally done to give us freedom to customize the end result using CSS (this is in fact done by default as we&#039;ll see below).&lt;br /&gt;
&lt;br /&gt;
The default behavior of this feature in our case will modify our block&#039;s &amp;quot;class&amp;quot; HTML attribute by appending the value &amp;quot;block_simplehtml&amp;quot; (the prefix &amp;quot;block_&amp;quot; followed by the name of our block, lowercased). We can then use that class to make CSS selectors in our theme to alter this block&#039;s visual style (for example, &amp;quot;.block_simplehtml { border: 1px black solid}&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To change the default behavior, we will need to define a method which returns an associative array of attribute names and values. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function html_attributes() {&lt;br /&gt;
    $attributes = parent::html_attributes(); // Get default values&lt;br /&gt;
    $attributes[&#039;class&#039;] .= &#039; block_&#039;. $this-&amp;gt;name(); // Append our class to class attribute&lt;br /&gt;
    return $attributes;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This results in the block having all its normal HTML attributes, as inherited from the base block class, plus our additional class name. We can now use this class name to change the style of the block, add JavaScript events to it via YUI, and so on. And for one final elegant touch,  we have not set the class to the hard-coded value &amp;quot;block_simplehtml&amp;quot;, but instead used the [[Blocks/Appendix_A#name.28.29| name()]] method to make it dynamically match our block&#039;s name.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Authorized Personnel Only ==&lt;br /&gt;
&lt;br /&gt;
Some blocks are useful in some circumstances, but not in others. An example of this would be the &amp;quot;Social Activities&amp;quot; block, which is useful in courses with the &amp;quot;social&amp;quot; course format, but not courses with the &amp;quot;weeks&amp;quot; format. What we need to be able to do is limit our block&#039;s availability, so that it can only be selected on pages where its content or abilities are appropriate.&lt;br /&gt;
&lt;br /&gt;
Moodle allows us to declare which page formats a block is available on, and enforces these restrictions as set by the block&#039;s developer at all times. The information is given to Moodle as a standard associative array, with each key corresponding to a page format and defining a boolean value (true/false) that declares whether the block should be allowed to appear in that page format.&lt;br /&gt;
&lt;br /&gt;
Notice the deliberate use of the term &#039;&#039;page&#039;&#039; instead of &#039;&#039;course&#039;&#039; in the above paragraph. This is because in Moodle 1.5 and onwards, blocks can be displayed in any page that supports them. The best example of such pages are the course pages, but we are not restricted to them. For instance, the quiz view page (the first one we see when we click on the name of the quiz) also supports blocks.&lt;br /&gt;
&lt;br /&gt;
The format names we can use for the pages derive from the name of the script which is actually used to display that page. For example, when we are looking at a course, the script is &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/course/view.php&amp;lt;/span&amp;gt; (this is evident from the browser&#039;s address line). Thus, the format name of that page is &#039;&#039;&#039;course-view&#039;&#039;&#039;. It follows easily that the format name for a quiz view page is &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039;. This rule of thumb does have a few exceptions, however:&lt;br /&gt;
&lt;br /&gt;
# The format name for the front page of Moodle is &#039;&#039;&#039;site-index&#039;&#039;&#039;.&lt;br /&gt;
# The format name for courses is actually not just &#039;&#039;&#039;course-view&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;; it is &amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;course-view-weeks&#039;&#039;&#039;, &#039;&#039;&#039;course-view-topics&#039;&#039;&#039;, etc.&lt;br /&gt;
# Even though there is no such page, the format name &#039;&#039;&#039;all&#039;&#039;&#039; can be used as a catch-all option.&lt;br /&gt;
&lt;br /&gt;
We can include as many format names as we want in our definition of the applicable formats. Each format can be allowed or disallowed, and there are also three more rules that help resolve the question &amp;quot;is this block allowed into this page or not?&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
# Prefixes of a format name will match that format name; for example, &#039;&#039;&#039;mod&#039;&#039;&#039; will match all the activity modules. &#039;&#039;&#039;course-view&#039;&#039;&#039; will match any course, regardless of the course format. And finally, &#039;&#039;&#039;site&#039;&#039;&#039; will also match the front page (remember that its full format name is &#039;&#039;&#039;site-index&#039;&#039;&#039;).&lt;br /&gt;
# The more specialized a format name that matches our page is, the higher precedence it has when deciding if the block will be allowed. For example, &#039;&#039;&#039;mod&#039;&#039;&#039;, &#039;&#039;&#039;mod-quiz&#039;&#039;&#039; and &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; all match the quiz view page. But if all three are present, &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; will take precedence over the other two because it is a better match.&lt;br /&gt;
# The character &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; can be used in place of any word. For example, &#039;&#039;&#039;mod&#039;&#039;&#039; and &#039;&#039;&#039;mod-*&#039;&#039;&#039; are equivalent. At the time of this document&#039;s writing, there is no actual reason to utilize this &amp;quot;wildcard matching&amp;quot; feature, but it exists for future usage.&lt;br /&gt;
# The order that the format names appear does not make any difference.&lt;br /&gt;
All of the above are enough to make the situation sound complex, so let&#039;s look at some specific examples. First of all, to have our block appear &#039;&#039;&#039;only&#039;&#039;&#039; in the site front page, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&#039;site&#039; =&amp;gt; true);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Since &#039;&#039;&#039;all&#039;&#039;&#039; is missing, the block is disallowed from appearing in &#039;&#039;any&#039;&#039; course format; but then &#039;&#039;&#039;site&#039;&#039;&#039; is set to TRUE, so it&#039;s explicitly allowed to appear in the site front page (remember that &#039;&#039;&#039;site&#039;&#039;&#039; matches &#039;&#039;&#039;site-index&#039;&#039;&#039; because it&#039;s a prefix).&lt;br /&gt;
&lt;br /&gt;
For another example, if we wanted to allow the block to appear in all course formats &#039;&#039;except&#039;&#039; social, and also to &#039;&#039;not&#039;&#039; be allowed anywhere but in courses, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
    &#039;course-view-social&#039; =&amp;gt; false);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This time, we first allow the block to appear in all courses and then we explicitly disallow the social format.&lt;br /&gt;
For our final, most complicated example, suppose that a block can be displayed in the site front page, in courses (but not social courses) and also when we are viewing any activity module, &#039;&#039;except&#039;&#039; quiz. This would be:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;site-index&#039; =&amp;gt; true,&lt;br /&gt;
          &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
   &#039;course-view-social&#039; =&amp;gt; false,&lt;br /&gt;
                  &#039;mod&#039; =&amp;gt; true, &lt;br /&gt;
             &#039;mod-quiz&#039; =&amp;gt; false&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is not difficult to realize that the above accomplishes the objective if we remember that there is a &amp;quot;best match&amp;quot; policy to determine the end result.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Responding to Cron ==&lt;br /&gt;
&lt;br /&gt;
It is possible to have our block respond to the global Moodle cron process; we can have a method that is run at regular intervals regardless of user interaction. There are two parts to this. Firstly we need to define a new function within our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function cron() {&lt;br /&gt;
    mtrace( &amp;quot;Hey, my cron script is running&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
    // do something&lt;br /&gt;
&lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we will need to set the (minimum) execution interval for our cron function. Prior to Moodle 2.0, this was achieved by setting the value of a block&#039;s $this-&amp;gt;cron field, via the init() method. This is now achieved by adding an additional line to our &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039; file. Open it up and add the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $plugin-&amp;gt;cron = 300;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cron intervals are set in seconds, so the above line will set our minimum execution interval to 5 minutes. However, the function can only be called as frequently as cron has been set to run in the Moodle installation. So if our block is set to wait at least 5 minutes between runs, as in this example, but Moodle&#039;s cron system is only set to run every 24 hours, then our block is going to be waiting a lot longer between runs than we expected!&lt;br /&gt;
&lt;br /&gt;
Remember that if we change any values in the version file or block file we &#039;&#039;&#039;must&#039;&#039;&#039; bump the version number and visit the Notifications page to upgrade the block, otherwise they will be ignored.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039;&lt;br /&gt;
The block cron is designed to call the cron script for that block &#039;&#039;&#039;type&#039;&#039;&#039; only. That is, cron does not care about individual instances of blocks. Inside your cron function &#039;&#039;$this&#039;&#039; is defined, but it has almost nothing in it (only title and content fields are populated). If you need to execute cron for individual instances it is your own responsibility to iterate over them in the block&#039;s cron function. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function cron() {&lt;br /&gt;
&lt;br /&gt;
    global $DB; // Global database object&lt;br /&gt;
&lt;br /&gt;
    // Get the instances of the block&lt;br /&gt;
    $instances = $DB-&amp;gt;get_records( &#039;block_instance&#039;, array(&#039;blockid&#039;=&amp;gt;&#039;simplehtml&#039;) );&lt;br /&gt;
&lt;br /&gt;
    // Iterate over the instances&lt;br /&gt;
    foreach ($instances as $instance) {&lt;br /&gt;
&lt;br /&gt;
        // Recreate block object&lt;br /&gt;
        $block = block_instance(&#039;simplehtml&#039;, $instance);&lt;br /&gt;
&lt;br /&gt;
        // $block is now the equivalent of $this in &#039;normal&#039; block&lt;br /&gt;
        // usage, e.g.&lt;br /&gt;
        $someconfigitem = $block-&amp;gt;config-&amp;gt;item2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TIP: This also means that creating a block is a possible way to create code that can respond to cron with a reasonably low overhead. No actual instances of the block are required.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Additional Content Types == &lt;br /&gt;
&lt;br /&gt;
=== Lists ===&lt;br /&gt;
&lt;br /&gt;
In this final part of the guide we will briefly discuss several additional capabilities of Moodle&#039;s block system, namely the ability to create blocks that display different kinds of content to the user. The first of these creates a list of options and displays them to the user.  This list is displayed with one item per line, and an optional image (icon) next to the item. An example of such a &#039;&#039;list block&#039;&#039; is the standard Moodle &amp;quot;admin&amp;quot; block, which illustrates all the points discussed in this section.&lt;br /&gt;
&lt;br /&gt;
As we have seen so far, blocks use two properties of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]]: &amp;quot;text&amp;quot; and &amp;quot;footer&amp;quot;. The text is displayed as-is as the block content, and the footer is displayed below the content in a smaller font size. List blocks use $this-&amp;gt;content-&amp;gt;footer in the exact same way, but they ignore $this-&amp;gt;content-&amp;gt;text.&lt;br /&gt;
&lt;br /&gt;
Instead, Moodle expects such blocks to set two other properties when the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called: $this-&amp;gt;content-&amp;gt;items and $this-&amp;gt;content-&amp;gt;icons. $this-&amp;gt;content-&amp;gt;items should be a numerically indexed array containing elements that represent the HTML for each item in the list that is going to be displayed. Usually these items will be HTML anchor tags which provide links to some page. $this-&amp;gt;content-&amp;gt;icons should also be a numerically indexed array, with exactly as many items as $this-&amp;gt;content-&amp;gt;items has. Each of these items should be a fully qualified HTML &amp;lt;img&amp;gt; tag, with &amp;quot;src&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;width&amp;quot; and &amp;quot;alt&amp;quot; attributes. Obviously, it makes sense to keep the images small and of a uniform size. We would recommend standard 16x16 images for this purpose.&lt;br /&gt;
&lt;br /&gt;
In order to tell Moodle that we want to have a list block instead of the standard text block, we need to make a small change to our block class declaration. Instead of extending class &#039;&#039;&#039;block_base&#039;&#039;&#039;, our block will extend class &#039;&#039;&#039;block_list&#039;&#039;&#039;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
class block_my_menu extends block_list {&lt;br /&gt;
     // The init() method does not need to change at all&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition to making this change, we must of course also modify the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method to construct the [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] variable as discussed above:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function get_content() {&lt;br /&gt;
  if ($this-&amp;gt;content !== null) {&lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content         = new stdClass;&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items[] = html_writer::tag(&#039;a&#039;, &#039;Menu Option 1&#039;, array(&#039;href&#039; =&amp;gt; &#039;some_file.php&#039;));&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons[] = html_writer::empty_tag(&#039;img&#039;, array(&#039;src&#039; =&amp;gt; &#039;images/icons/1.gif&#039;, &#039;class&#039; =&amp;gt; &#039;icon&#039;));&lt;br /&gt;
&lt;br /&gt;
  // Add more list items here&lt;br /&gt;
 &lt;br /&gt;
  return $this-&amp;gt;content;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To summarise, if we want to create a list block instead of a text block, we just need to change the block class declaration and the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method. Adding the mandatory [[Blocks/Appendix_A#init.28.29| init()]] method as discussed earlier will then give us our first list block in no time!&lt;br /&gt;
&lt;br /&gt;
=== Trees ===&lt;br /&gt;
&lt;br /&gt;
As of 23rd December 2011, this functionality remains inoperable in all Moodle 2.x versions. It appears that classes are missing from the code base. This has been added to the tracker at the URL below. Please upvote this issue if you require this functionality.&lt;br /&gt;
&lt;br /&gt;
[http://tracker.moodle.org/browse/MDL-28289 Visit this issue on the tracker @ MDL28289]&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Database support ==&lt;br /&gt;
In case we need to have a database table that holds some specific information used within our block, we will need to create the file &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;install.xml&#039;&#039;&#039;&#039;&#039; with the table schema contained within it.&lt;br /&gt;
&lt;br /&gt;
To create the install.xml file, use the [[XMLDB editor]]. See [[Database_FAQ#XMLDB|Database FAQ &amp;gt; XMLDB]] for further details.&lt;br /&gt;
&lt;br /&gt;
Up-to-date documentation on upgrading our block, as well as providing new capabilities and events to the system, can be found under [https://docs.moodle.org/dev/Installing_and_upgrading_plugin_database_tables#install.php Installing and Upgrading Plugin Database Tables]&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Blocks Advanced]] A continuation of this tutorial.&lt;br /&gt;
* [http://dev.moodle.org/mod/resource/view.php?id=48 Unit 7 of the Introduction to Moodle Programming course] is a follow up to this course. (But you should follow the forum discussions of that course closely as there are still some bugs and inconsistencies.)&lt;br /&gt;
* A [http://cvs.moodle.org/contrib/plugins/blocks/NEWBLOCK/ NEWBLOCK template] you can all use to start you own block.&lt;br /&gt;
&lt;br /&gt;
== Appendices ==&lt;br /&gt;
&lt;br /&gt;
The appendices have been moved to separate pages:&lt;br /&gt;
&lt;br /&gt;
* Appendix A: [[Blocks/Appendix A|&#039;&#039;block_base&#039;&#039; Reference]] &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;br /&gt;
[[ja:開発:ブロック]]&lt;br /&gt;
[[:en:Blocks|Blocks]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=36120</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=36120"/>
		<updated>2012-11-08T08:40:46Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039; A Step-by-step Guide To Creating Blocks &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Original Author: Jon Papaioannou ([mailto:pj@moodle.org pj@moodle.org])&lt;br /&gt;
&lt;br /&gt;
Updated to Moodle 2.0 and above by: Greg J Preece ([mailto:greg.preece@blackboard.com greg.preece@blackboard.com])&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
The present document serves as a guide to developers who want to create their own blocks for use in Moodle. It applies to the 2.0 development version of Moodle (and any newer) &#039;&#039;&#039;only&#039;&#039;&#039;, as the blocks API changed significantly enough to warrant new documentation. Those wishing to read the old tutorial for Moodles 1.5 to 1.9 can find it under [[Blocks/Blocks for 1.5 to 1.9| Blocks for 1.5 to 1.9]].&lt;br /&gt;
&lt;br /&gt;
The guide is written as an interactive course which aims to develop a configurable, multi-purpose block that displays arbitrary HTML. It&#039;s targeted mainly at people with little experience with Moodle or programming in general and aims to show how easy it is to create new blocks for Moodle. A certain small amount of PHP programming knowledge is still required, though. &lt;br /&gt;
&lt;br /&gt;
Experienced developers and those who just want a &#039;&#039;&#039;programmer&#039;s reference&#039;&#039;&#039; text should refer to [[Blocks/Appendix_A| Appendix A]] because the main guide has a rather low concentration of pure information in the text.&lt;br /&gt;
&lt;br /&gt;
== Basic Concepts ==&lt;br /&gt;
&lt;br /&gt;
Through this guide, we will be following the creation of an &amp;quot;HTML&amp;quot; block from scratch in order to demonstrate most of the block features at our disposal. Our block will be named &amp;quot;SimpleHTML&amp;quot;. This does not constrain us regarding the name of the actual directory on the server where the files for our block will be stored, but for consistency we will follow the practice of using the lowercased form &amp;quot;simplehtml&amp;quot; in any case where such a name is required. &lt;br /&gt;
&lt;br /&gt;
Whenever we refer to a file or directory name which contains &amp;quot;simplehtml&amp;quot;, it&#039;s important to remember that &#039;&#039;only&#039;&#039; the &amp;quot;simplehtml&amp;quot; part is up to us to change; the rest is standardised and essential for Moodle to work correctly.&lt;br /&gt;
&lt;br /&gt;
Whenever a file&#039;s path is mentioned in this guide, it will always start with a slash. This refers to the Moodle home directory; all files and directories will be referred to with respect to that directory.&lt;br /&gt;
&lt;br /&gt;
== Ready, Set, Go! ==&lt;br /&gt;
&lt;br /&gt;
To define a &amp;quot;block&amp;quot; in Moodle, in the most basic case we need to provide just four PHP files. Remember, in this example we are creating a block called &#039;simplehtml&#039;, replace &#039;simplehtml&#039; with the name of your custom block. The four files should be located in blocks/simplehtml and are:&lt;br /&gt;
&lt;br /&gt;
=== block_simplehtml.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold the class definition for the block, and is used both to manage it as a plugin and to render it onscreen.&lt;br /&gt;
&lt;br /&gt;
We start by creating the main object file, &#039;block_simplehtml.php&#039;. We then begin coding the block:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class block_simplehtml extends block_base {&lt;br /&gt;
    public function init() {&lt;br /&gt;
        $this-&amp;gt;title = get_string(&#039;simplehtml&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    // The PHP tag and the curly bracket for the class definition &lt;br /&gt;
    // will only be closed after there is another function added in the next section.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first line is our block class definition; it must be named exactly in the manner shown. Again, only the &amp;quot;simplehtml&amp;quot; part can (and indeed must) change; everything else is standardised.&lt;br /&gt;
&lt;br /&gt;
Our class is then given a small method: [[Blocks/Appendix_A#init.28.29| init()]]. This is essential for all blocks, and its purpose is to give values to any class member variables that need instantiating. &lt;br /&gt;
&lt;br /&gt;
In this very basic example, we only want to set [[Blocks/Appendix_A#.24this-.3Etitle| $this-&amp;gt;title]], which is the title displayed in the header of our block. We can set it to whatever we like; in this case it&#039;s set to read the actual title from the language file mentioned previously, which is then distributed along with the block. I&#039;ll skip ahead a bit here and say that if you want your block to display &#039;&#039;&#039;no&#039;&#039;&#039; title at all, then you should set this to any descriptive value you want (but &#039;&#039;&#039;not&#039;&#039;&#039; make it an empty string). We will later see [[Blocks#Eye_Candy|how to disable the title&#039;s display]].&lt;br /&gt;
&lt;br /&gt;
=== db/access.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold the new capabilities created by the block.&lt;br /&gt;
&lt;br /&gt;
Moodle 2.4 onwards introduced the capabilities addinstance and myaddinstance for each core block. They were introduced so that it was possible to control the use of individual blocks. These capabilities should also be added to your custom block, so in this case to the file blocks/simplehtml/db/access.php. If your block is not going to be used in the &#039;My Moodle page&#039; (ie, your applicable_formats function (discussed later) has &#039;my&#039; set to false.) then the myaddinstance capability is not required. The following is the capabilities array and how it should look for any new blocks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:myaddinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_SYSTEM,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;user&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/my:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_SPAM | RISK_XSS,&lt;br /&gt;
&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_BLOCK,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/site:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== lang/en/block_simplehtml.php ===&lt;br /&gt;
&lt;br /&gt;
This is the English language file for your block. If you are not an English speaker, you can replace &#039;en&#039; with your appropriate language code. All language files for blocks go under the /lang subfolder of the block&#039;s installation folder.&lt;br /&gt;
&lt;br /&gt;
Moodle 2.0 and above require a name for our plugin to show in the upgrading page. We set this value, along with any other language strings we wish to use within the block, in a language package as previously mentioned (the same file where we put our string for the plugin title). Now we will create this language package. Create the file &#039;&#039;/blocks/simplehtml/lang/en/&#039;&#039;&#039;&#039;&#039;block_simplehtml.php&#039;&#039;&#039; and paste the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Simple html block&#039;;&lt;br /&gt;
$string[&#039;simplehtml&#039;] = &#039;Simple html&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
This file will hold version information for the plugin, along with other advanced parameters (not covered here - see [[version.php]] if you want more details).&lt;br /&gt;
&lt;br /&gt;
Prior to Moodle 2.0, version details for blocks were stored as class fields; as of Moodle 2.0 these are stored in a file called version.php, stored under &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039;. The version file is very simple indeed, containing only a few field definitions, depending on your needs. Here is an example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$plugin-&amp;gt;version = 2011062800;  // YYYYMMDDHH (year, month, day, 24-hr time)&lt;br /&gt;
$plugin-&amp;gt;requires = 2010112400; // YYYYMMDDHH (This is the release version for Moodle 2.0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file contains object field definitions that denote the version number of the block, along with the minimum version of Moodle that must be installed in order to use it. Please note that the object being used here is &#039;&#039;always&#039;&#039; called &#039;&#039;&#039;$plugin&#039;&#039;&#039;, and that you do not need to create this object yourself within the version file. Note also that we didnt include the closing &amp;quot;?&amp;gt;&amp;quot; tag for PHP. This is intentional, and a [[Coding_style#PHP_tags | workaround for whitespace issues]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== I Just Hear Static ==&lt;br /&gt;
In order to get our block to actually display something on screen, we need to add one more method to our class (before the final closing brace in our file). The new code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;  &lt;br /&gt;
  public function get_content() {&lt;br /&gt;
    if ($this-&amp;gt;content !== null) {&lt;br /&gt;
      return $this-&amp;gt;content;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;content         =  new stdClass;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text   = &#039;The content of our SimpleHTML block!&#039;;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
}   // Here&#039;s the closing bracket for the class definition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Add your block to the front page!&#039;&#039;&#039;&lt;br /&gt;
Don&#039;t forget (especially if you&#039;re a new Moodle user) to add your block to the front page. Turn Editing On, and add your block to the page.&lt;br /&gt;
&lt;br /&gt;
It can&#039;t get any simpler than that, can it? Let&#039;s dissect this method to see what&#039;s going on...&lt;br /&gt;
&lt;br /&gt;
First of all, there is a check that returns the current value of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] if it&#039;s not NULL; otherwise we proceed with &amp;quot;computing&amp;quot; it. Since the computation is potentially a time-consuming operation and it &#039;&#039;&#039;will&#039;&#039;&#039; be called several times for each block (Moodle works that way internally), we take a precaution and include this time-saver.&lt;br /&gt;
Supposing the content had not been computed before (it was NULL), we then define it from scratch. The code speaks for itself there, so there isn&#039;t much to say. Just keep in mind that we can use HTML both in the text &#039;&#039;&#039;and&#039;&#039;&#039; in the footer, if we want to.&lt;br /&gt;
&lt;br /&gt;
It&#039;s worth mentioning that this is not the only type of content a block can output. You can also create lists and hierarchical trees, which are better suited for certain types of output, such as menus. These different content types have an impact on the content object and how it is constructed. For more information, see [[Blocks/Appendix A#.24this-.3Econtent_type|Appendix A]]&lt;br /&gt;
&lt;br /&gt;
At this point our block should be capable of being automatically installed in Moodle and added to courses; visit your administration page to install it (Click &amp;quot;Notifications&amp;quot; under the Site Administration Block) and after seeing it in action come back to continue our tutorial.&lt;br /&gt;
&lt;br /&gt;
== Configure That Out ==&lt;br /&gt;
&lt;br /&gt;
The current version of our block doesn&#039;t really do much; it just displays a fixed message, which is not very useful. What we&#039;d really like to do is allow the teachers to customize what goes into the block. This, in block-speak, is called &amp;quot;instance configuration&amp;quot;. Basic instance configuration is automatic in Moodle 2.0; if you put any page with blocks on it into &amp;quot;editing mode&amp;quot;, you will notice that each block has an edit button in its title bar. Clicking on this will take you to the block configuration form. The settings that Moodle adds to this form by default relate to the block&#039;s appearance and position on Moodle pages. &lt;br /&gt;
&lt;br /&gt;
We can extend this configuration form, and add custom preferences fields, so that users can better tailor our block to a given task or page. To extend the configuration form, create the file &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&amp;lt;/span&amp;gt;, and fill it with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class block_simplehtml_edit_form extends block_edit_form {&lt;br /&gt;
        &lt;br /&gt;
    protected function specific_definition($mform) {&lt;br /&gt;
        &lt;br /&gt;
        // Section header title according to language file.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;configheader&#039;, get_string(&#039;blocksettings&#039;, &#039;block&#039;));&lt;br /&gt;
&lt;br /&gt;
        // A sample string variable with a default value.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_text&#039;, get_string(&#039;blockstring&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;config_text&#039;, &#039;default value&#039;);&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;config_text&#039;, PARAM_MULTILANG);        &lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The first line declares a class that inherits &#039;&#039;&#039;from block_edit_form&#039;&#039;&#039;, and this allows Moodle to identify the code to execute in the configuration page. The &#039;&#039;&#039;specific_definition()&#039;&#039;&#039; method is where your form elements are defined, and these take the same format as with the standard [[lib/formslib.php_Form_Definition|Moodle form library]].  Within our specific_definition method, we have created a header, and an input field which will accept text to be used within the block.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; All your field names need to start with &amp;quot;config_&amp;quot;, otherwise they will not be saved and will not be available within the block via [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]]. &lt;br /&gt;
&lt;br /&gt;
So once our instance configuration form has been saved, we can use the inputted text within the block like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (! empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text = $this-&amp;gt;config-&amp;gt;text;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] is available in all block methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]. This is because [[Blocks/Appendix_A#init.28.29|init()]] is called immediately as the block is being created, with the purpose of setting things up, so [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] has not yet been instantiated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note about Checkbox:&#039;&#039;&#039; You cannot use the &#039;checkbox&#039; element in the form (once set it will stay set). You must use advcheckbox instead. &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Specialists ==&lt;br /&gt;
&lt;br /&gt;
Implementing instance configuration for the block&#039;s contents was good enough to whet our appetite, but who wants to stop there? Why not customize the block&#039;s title, too?&lt;br /&gt;
&lt;br /&gt;
Why not, indeed. Well, our first attempt to achieve this is natural enough: let&#039;s add another field to &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&#039;&#039;. Here goes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // A sample string variable with a default value.&lt;br /&gt;
    $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_title&#039;, get_string(&#039;blocktitle&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
    $mform-&amp;gt;setDefault(&#039;config_title&#039;, &#039;default value&#039;);&lt;br /&gt;
    $mform-&amp;gt;setType(&#039;config_title&#039;, PARAM_MULTILANG);        &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We save the edited file, go to a course, edit the title of the block and... nothing happens! The instance configuration is saved correctly, all right (editing it once more proves that) but it&#039;s not being displayed. All we get is just the simple &amp;quot;SimpleHTML&amp;quot; title.&lt;br /&gt;
&lt;br /&gt;
That&#039;s not too weird, if we think back a bit. Do you remember that [[Blocks/Appendix_A#init.28.29|init()]] method, where we set [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]]? We didn&#039;t actually change its value from then, and [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] is definitely not the same as &#039;&#039;&#039;$this-&amp;gt;config-&amp;gt;title&#039;&#039;&#039; (to Moodle, at least). What we need is a way to update [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] with the value in the instance configuration. But as we said a bit earlier, we can use [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] in all methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]! So what can we do?&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pull out another ace from our sleeve, and add this small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function specialization() {&lt;br /&gt;
  if (!empty($this-&amp;gt;config-&amp;gt;title)) {&lt;br /&gt;
    $this-&amp;gt;title = $this-&amp;gt;config-&amp;gt;title;&lt;br /&gt;
  } else {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;title = &#039;Default title ...&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;text = &#039;Default text ...&#039;;&lt;br /&gt;
  }    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aha, here&#039;s what we wanted to do all along! But what&#039;s going on with the [[Blocks/Appendix_A#specialization.28.29| specialization()]] method?&lt;br /&gt;
&lt;br /&gt;
This &amp;quot;magic&amp;quot; method has actually a very nice property: it&#039;s &#039;&#039;guaranteed&#039;&#039; to be automatically called by Moodle as soon as our instance configuration is loaded and available (that is, immediately after [[Blocks/Appendix_A#init.28.29|init()]] is called). That means before the block&#039;s content is computed for the first time, and indeed before &#039;&#039;anything&#039;&#039; else is done with the block. Thus, providing a [[Blocks/Appendix_A#specialization.28.29| specialization()]] method is the natural choice for any configuration data that needs to be acted upon or made available &amp;quot;as soon as possible&amp;quot;, as in this case.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Now You See Me, Now You Don&#039;t ==&lt;br /&gt;
&lt;br /&gt;
Now would be a good time to mention another nifty technique that can be used in blocks, and which comes in handy quite often. Specifically, it may be the case that our block will have something interesting to display some of the time; but in some other cases, it won&#039;t have anything useful to say. An example here would be the &amp;quot;Recent Activity&amp;quot; block, in the case where no recent activity in fact exists. &lt;br /&gt;
&lt;br /&gt;
However in that case the block chooses to explicitly inform you of the lack of said activity, which is arguably useful. It would be nice, then, to be able to have our block &amp;quot;disappear&amp;quot; if it&#039;s not needed to display it.&lt;br /&gt;
&lt;br /&gt;
This is indeed possible, and the way to do it is to make sure that after the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called, the block has no content to display. This means that all fields in $this-&amp;gt;content should be equal to the empty string (&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;). In the case of our HTML-based block, these fields are $this-&amp;gt;content-&amp;gt;text and $this-&amp;gt;content-&amp;gt;footer. Moodle performs this check by calling the block&#039;s [[Blocks/Appendix_A#is_empty.28.29| is_empty()]] method, and if the block is indeed empty then it is not displayed at all.&lt;br /&gt;
&lt;br /&gt;
Note that the exact value of the block&#039;s title and the presence or absence of a [[Blocks/Appendix_A#hide_header.28.29| hide_header()]] method do &#039;&#039;not&#039;&#039; affect this behavior. A block is considered empty if it has no content, irrespective of anything else.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== We Are Legion ==&lt;br /&gt;
&lt;br /&gt;
Right now our block is fully configurable, both in title and content. It&#039;s so versatile, in fact, that we could make pretty much anything out of it. It would be really nice to be able to add multiple blocks of this type to a single course. And, as you might have guessed, doing that is as simple as adding another small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_allow_multiple() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells Moodle that it should allow any number of instances of the SimpleHTML block in any course. After saving the changes to our file, Moodle immediately allows us to add multiple copies of the block without further ado!&lt;br /&gt;
&lt;br /&gt;
Please note that even if a block itself allows multiple instances in the same page, the administrator still has the option of disallowing such behavior. This setting can be set separately for each block from the Administration / Configuration / Blocks page.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Effects of Globalization ==&lt;br /&gt;
&lt;br /&gt;
Configuring each block instance with its own personal data is cool enough, but sometimes administrators need some way to &amp;quot;touch&amp;quot; all instances of a specific block at the same time. In the case of our SimpleHTML block, a few settings that would make sense to apply to all instances aren&#039;t that hard to come up with. &lt;br /&gt;
&lt;br /&gt;
For example, we might want to limit the contents of each block to only so many characters, or we might have a setting that filters HTML out of the block&#039;s contents, only allowing pure text in. Granted, such a feature wouldn&#039;t win us any awards for naming our block &amp;quot;SimpleHTML&amp;quot; but some tormented administrator somewhere might actually find it useful.&lt;br /&gt;
&lt;br /&gt;
This kind of configuration is called &amp;quot;global configuration&amp;quot; and applies only to a specific block type (all instances of that block type are affected, however).  Implementing such configuration for our block is quite similar to implementing the instance configuration. We will now see how to implement the second example, having a setting that only allows text and not HTML in the block&#039;s contents. To enable global configuration for the block, we create a new file, &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;settings.php&#039;&#039;&#039;&#039;&#039;, and populate it with form field definitions for each setting, which Moodle will use to generate and handle a global settings form.  This is quite similar in concept to how we generated the instance configuration form earlier, but the actual code used to generate the form and fields is somewhat different.&lt;br /&gt;
&lt;br /&gt;
Place the following in your settings.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_heading(&lt;br /&gt;
            &#039;headerconfig&#039;,&lt;br /&gt;
            get_string(&#039;headerconfig&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descconfig&#039;, &#039;block_simplehtml&#039;)&lt;br /&gt;
        ));&lt;br /&gt;
&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_configcheckbox(&lt;br /&gt;
            &#039;simplehtml/Allow_HTML&#039;,&lt;br /&gt;
            get_string(&#039;labelallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            &#039;0&#039;&lt;br /&gt;
        ));    &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, to generate a global configuration form, we simply create admin setting objects and add them to an array. This array is then stepped over to create the settings form, and the inputted data is automatically saved to the database. Full details of the setting types available and how to add them can be found under [[Admin_settings#Individual_settings]].&lt;br /&gt;
&lt;br /&gt;
We&#039;ve now created a header and checkbox form element to accept configuration details from the site admin. You should pay extra attention to the name of our checkbox element, &#039;&#039;&#039; &#039;simplehtml/Allow_HTML&#039; &#039;&#039;&#039;, as it specifies not only the name of the configuration option, but also how it should be stored. If you simply specify a name for the config option, it will be stored in the global $CFG object, and in the &#039;&#039;&amp;lt;prefix&amp;gt;_config&#039;&#039; database table. This will make your config variable available immediately via $CFG without requiring an additional database call, but will also increase the size of the $CFG object. In addition, we must prefix the variable with the name of our block, otherwise we run the risk of our config variable sharing its name with a similar variable in another plugin, or within Moodle itself.&lt;br /&gt;
&lt;br /&gt;
The preferred method of storing your block&#039;s configuration data is to prefix each config variable name in your settings.php file with your block&#039;s name, followed by a slash ( / ), and the name of the configuration variable, as we have done above. If you write your settings.php file in this way, then your variables will be stored in the &#039;&#039;&amp;lt;prefix&amp;gt;_config_plugin&#039;&#039; table, under your block&#039;s name. Your config data will still be available via a &#039;&#039;&#039;get_config()&#039;&#039;&#039; call, and name collision will be impossible between plugins.&lt;br /&gt;
&lt;br /&gt;
Finally, if you&#039;re wondering why there are two language tags specified for each element, the first tag is for the element&#039;s label or primary text, and the second tag is for its description. And that&#039;s it. Pretty easy, huh?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE FOR UPGRADERS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You&#039;ll notice that the settings.php file and parsed element names replaces Moodle&#039;s old storage method, wherein it would send all the configuration data to your block&#039;s [[Blocks/Appendix_A#config_save.28.29|config_save()]] method, and allow you to override how the data is saved. The [[Blocks/Appendix_A#config_save.28.29|config_save()]] method is no longer used in Moodle 2.x; however the [[Blocks/Appendix_A#instance_config_save.28.29|instance_config_save()]] method is very much alive and well, as you will see shortly.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Global Config Data  ===&lt;br /&gt;
&lt;br /&gt;
Now that we have global data defined for the plugin, we need to know how to access it within our code.  If you saved your config variables in the global namespace, you can access them from the global $CFG object, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = $CFG-&amp;gt;Allow_HTML;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If, as recommended, you saved your config variables in a custom namespace for your block, then you can access them via a call to &#039;&#039;&#039;get_config()&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Rolling It All Together ===&lt;br /&gt;
&lt;br /&gt;
OK, so we now have an instance configuration form that allows users to enter custom content text for a block, and a global configuration option that dictates whether or not that user should be allowed to enter HTML tags as part of the content. Now we just need to tie the two together. But if Moodle takes care of the form processing for our instance configuration in edit_form.php, how can we capture it and remove the HTML tags where required?&lt;br /&gt;
&lt;br /&gt;
Well, fortunately, there is a way this can be done.  By overriding the [[Blocks/Appendix_A#instance_config_save.28.29| instance_config_save()]] method in our block class, we can modify the way in which instance configuration data is stored after input. The default implementation is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data) {&lt;br /&gt;
  $data = stripslashes_recursive($data);&lt;br /&gt;
  $this-&amp;gt;config = $data;&lt;br /&gt;
  return set_field(&#039;block_instance&#039;, &lt;br /&gt;
                   &#039;configdata&#039;,&lt;br /&gt;
                    base64_encode(serialize($data)),&lt;br /&gt;
                   &#039;id&#039;, &lt;br /&gt;
                   $this-&amp;gt;instance-&amp;gt;id);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may look intimidating at first (what&#039;s all this stripslashes_recursive() and base64_encode() and serialize() stuff?) but do not despair; we won&#039;t have to touch any of it. We will only add some extra validation code in the beginning and then instruct Moodle to additionally call this default implementation to do the actual storing of the data. Specifically, we will add a method to our class which goes like this:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data) {&lt;br /&gt;
  if(get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;) == &#039;1&#039;) {&lt;br /&gt;
    $data-&amp;gt;text = strip_tags($data-&amp;gt;text);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // And now forward to the default implementation defined in the parent class&lt;br /&gt;
  return parent::instance_config_save($data);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(This example assumes you are using a custom namespace for the block.)&lt;br /&gt;
&lt;br /&gt;
At last! Now the administrator has absolute power of life and death over what type of content is allowed in our &amp;quot;SimpleHTML&amp;quot; block! Absolute? Well... not exactly. In fact, if we think about it for a while, it will become apparent that if at some point in time HTML is allowed and some blocks have saved their content with HTML included, and afterwards the administrator changes the setting to &amp;quot;off&amp;quot;, this will only prevent subsequent content changes from including HTML. Blocks which already had HTML in their content would continue to display it!&lt;br /&gt;
&lt;br /&gt;
Following that train of thought, the next stop is realizing that we wouldn&#039;t have this problem if we had chosen the lazy approach a while back, because in that case we would &amp;quot;sanitize&amp;quot; each block&#039;s content just before it was displayed. &lt;br /&gt;
&lt;br /&gt;
The only thing we can do with the eager approach is strip all the tags from the content of all SimpleHTML instances as soon as the admin setting is changed to &amp;quot;HTML off&amp;quot;; but even then, turning the setting back to &amp;quot;HTML on&amp;quot; won&#039;t bring back the tags we stripped away. On the other hand, the lazy approach might be slower, but it&#039;s more versatile; we can choose whether to strip or keep the HTML before displaying the content, and we won&#039;t lose it at all if the admin toggles the setting off and on again. Isn&#039;t the life of a developer simple and wonderful?&lt;br /&gt;
&lt;br /&gt;
=== Exercise === &lt;br /&gt;
We will let this part of the tutorial come to a close with the obligatory exercise for the reader: &lt;br /&gt;
In order to have the SimpleHTML block work &amp;quot;correctly&amp;quot;, find out how to strengthen the eager approach to strip out all tags from the existing configuration of all instances of our block, &#039;&#039;&#039;or&#039;&#039;&#039; go back and implement the lazy approach instead. &lt;br /&gt;
(Hint: Do that in the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Eye Candy ==&lt;br /&gt;
&lt;br /&gt;
Our block is just about complete functionally, so now let&#039;s take a look at some of the tricks we can use to make its behavior customized in a few more useful ways.&lt;br /&gt;
&lt;br /&gt;
First of all, there are a couple of ways we can adjust the visual aspects of our block. For starters, it might be useful to create a block that doesn&#039;t display a header (title) at all. You can see this effect in action in the Course Description block that comes with Moodle. This behavior is achieved by, you guessed it, adding one more method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function hide_header() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One more note here: we cannot just set an empty title inside the block&#039;s [[Blocks/Appendix_A#init.28.29| init()]] method; it&#039;s necessary for each block to have a unique, non-empty title after [[Blocks/Appendix_A#init.28.29| init()]] is called so that Moodle can use those titles to differentiate between all of the installed blocks.&lt;br /&gt;
&lt;br /&gt;
Next, we can affect some properties of the actual HTML that will be used to print our block. Each block is fully contained within a &amp;amp;lt;div&amp;amp;gt; or &amp;amp;lt;table&amp;amp;gt; elements, inside which all the HTML for that block is printed. We can instruct Moodle to add HTML attributes with specific values to that container. This is generally done to give us freedom to customize the end result using CSS (this is in fact done by default as we&#039;ll see below).&lt;br /&gt;
&lt;br /&gt;
The default behavior of this feature in our case will modify our block&#039;s &amp;quot;class&amp;quot; HTML attribute by appending the value &amp;quot;block_simplehtml&amp;quot; (the prefix &amp;quot;block_&amp;quot; followed by the name of our block, lowercased). We can then use that class to make CSS selectors in our theme to alter this block&#039;s visual style (for example, &amp;quot;.block_simplehtml { border: 1px black solid}&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To change the default behavior, we will need to define a method which returns an associative array of attribute names and values. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function html_attributes() {&lt;br /&gt;
    $attributes = parent::html_attributes(); // Get default values&lt;br /&gt;
    $attributes[&#039;class&#039;] .= &#039; block_&#039;. $this-&amp;gt;name(); // Append our class to class attribute&lt;br /&gt;
    return $attributes;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This results in the block having all its normal HTML attributes, as inherited from the base block class, plus our additional class name. We can now use this class name to change the style of the block, add JavaScript events to it via YUI, and so on. And for one final elegant touch,  we have not set the class to the hard-coded value &amp;quot;block_simplehtml&amp;quot;, but instead used the [[Blocks/Appendix_A#name.28.29| name()]] method to make it dynamically match our block&#039;s name.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Authorized Personnel Only ==&lt;br /&gt;
&lt;br /&gt;
Some blocks are useful in some circumstances, but not in others. An example of this would be the &amp;quot;Social Activities&amp;quot; block, which is useful in courses with the &amp;quot;social&amp;quot; course format, but not courses with the &amp;quot;weeks&amp;quot; format. What we need to be able to do is limit our block&#039;s availability, so that it can only be selected on pages where its content or abilities are appropriate.&lt;br /&gt;
&lt;br /&gt;
Moodle allows us to declare which page formats a block is available on, and enforces these restrictions as set by the block&#039;s developer at all times. The information is given to Moodle as a standard associative array, with each key corresponding to a page format and defining a boolean value (true/false) that declares whether the block should be allowed to appear in that page format.&lt;br /&gt;
&lt;br /&gt;
Notice the deliberate use of the term &#039;&#039;page&#039;&#039; instead of &#039;&#039;course&#039;&#039; in the above paragraph. This is because in Moodle 1.5 and onwards, blocks can be displayed in any page that supports them. The best example of such pages are the course pages, but we are not restricted to them. For instance, the quiz view page (the first one we see when we click on the name of the quiz) also supports blocks.&lt;br /&gt;
&lt;br /&gt;
The format names we can use for the pages derive from the name of the script which is actually used to display that page. For example, when we are looking at a course, the script is &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/course/view.php&amp;lt;/span&amp;gt; (this is evident from the browser&#039;s address line). Thus, the format name of that page is &#039;&#039;&#039;course-view&#039;&#039;&#039;. It follows easily that the format name for a quiz view page is &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039;. This rule of thumb does have a few exceptions, however:&lt;br /&gt;
&lt;br /&gt;
# The format name for the front page of Moodle is &#039;&#039;&#039;site-index&#039;&#039;&#039;.&lt;br /&gt;
# The format name for courses is actually not just &#039;&#039;&#039;course-view&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;; it is &amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;course-view-weeks&#039;&#039;&#039;, &#039;&#039;&#039;course-view-topics&#039;&#039;&#039;, etc.&lt;br /&gt;
# Even though there is no such page, the format name &#039;&#039;&#039;all&#039;&#039;&#039; can be used as a catch-all option.&lt;br /&gt;
&lt;br /&gt;
We can include as many format names as we want in our definition of the applicable formats. Each format can be allowed or disallowed, and there are also three more rules that help resolve the question &amp;quot;is this block allowed into this page or not?&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
# Prefixes of a format name will match that format name; for example, &#039;&#039;&#039;mod&#039;&#039;&#039; will match all the activity modules. &#039;&#039;&#039;course-view&#039;&#039;&#039; will match any course, regardless of the course format. And finally, &#039;&#039;&#039;site&#039;&#039;&#039; will also match the front page (remember that its full format name is &#039;&#039;&#039;site-index&#039;&#039;&#039;).&lt;br /&gt;
# The more specialized a format name that matches our page is, the higher precedence it has when deciding if the block will be allowed. For example, &#039;&#039;&#039;mod&#039;&#039;&#039;, &#039;&#039;&#039;mod-quiz&#039;&#039;&#039; and &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; all match the quiz view page. But if all three are present, &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; will take precedence over the other two because it is a better match.&lt;br /&gt;
# The character &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; can be used in place of any word. For example, &#039;&#039;&#039;mod&#039;&#039;&#039; and &#039;&#039;&#039;mod-*&#039;&#039;&#039; are equivalent. At the time of this document&#039;s writing, there is no actual reason to utilize this &amp;quot;wildcard matching&amp;quot; feature, but it exists for future usage.&lt;br /&gt;
# The order that the format names appear does not make any difference.&lt;br /&gt;
All of the above are enough to make the situation sound complex, so let&#039;s look at some specific examples. First of all, to have our block appear &#039;&#039;&#039;only&#039;&#039;&#039; in the site front page, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&#039;site&#039; =&amp;gt; true);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Since &#039;&#039;&#039;all&#039;&#039;&#039; is missing, the block is disallowed from appearing in &#039;&#039;any&#039;&#039; course format; but then &#039;&#039;&#039;site&#039;&#039;&#039; is set to TRUE, so it&#039;s explicitly allowed to appear in the site front page (remember that &#039;&#039;&#039;site&#039;&#039;&#039; matches &#039;&#039;&#039;site-index&#039;&#039;&#039; because it&#039;s a prefix).&lt;br /&gt;
&lt;br /&gt;
For another example, if we wanted to allow the block to appear in all course formats &#039;&#039;except&#039;&#039; social, and also to &#039;&#039;not&#039;&#039; be allowed anywhere but in courses, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
    &#039;course-view-social&#039; =&amp;gt; false);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This time, we first allow the block to appear in all courses and then we explicitly disallow the social format.&lt;br /&gt;
For our final, most complicated example, suppose that a block can be displayed in the site front page, in courses (but not social courses) and also when we are viewing any activity module, &#039;&#039;except&#039;&#039; quiz. This would be:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;site-index&#039; =&amp;gt; true,&lt;br /&gt;
          &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
   &#039;course-view-social&#039; =&amp;gt; false,&lt;br /&gt;
                  &#039;mod&#039; =&amp;gt; true, &lt;br /&gt;
             &#039;mod-quiz&#039; =&amp;gt; false&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is not difficult to realize that the above accomplishes the objective if we remember that there is a &amp;quot;best match&amp;quot; policy to determine the end result.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Responding to Cron ==&lt;br /&gt;
&lt;br /&gt;
It is possible to have our block respond to the global Moodle cron process; we can have a method that is run at regular intervals regardless of user interaction. There are two parts to this. Firstly we need to define a new function within our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function cron() {&lt;br /&gt;
    mtrace( &amp;quot;Hey, my cron script is running&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
    // do something&lt;br /&gt;
&lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we will need to set the (minimum) execution interval for our cron function. Prior to Moodle 2.0, this was achieved by setting the value of a block&#039;s $this-&amp;gt;cron field, via the init() method. This is now achieved by adding an additional line to our &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039; file. Open it up and add the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $plugin-&amp;gt;cron = 300;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cron intervals are set in seconds, so the above line will set our minimum execution interval to 5 minutes. However, the function can only be called as frequently as cron has been set to run in the Moodle installation. So if our block is set to wait at least 5 minutes between runs, as in this example, but Moodle&#039;s cron system is only set to run every 24 hours, then our block is going to be waiting a lot longer between runs than we expected!&lt;br /&gt;
&lt;br /&gt;
Remember that if we change any values in the version file or block file we &#039;&#039;&#039;must&#039;&#039;&#039; bump the version number and visit the Notifications page to upgrade the block, otherwise they will be ignored.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039;&lt;br /&gt;
The block cron is designed to call the cron script for that block &#039;&#039;&#039;type&#039;&#039;&#039; only. That is, cron does not care about individual instances of blocks. Inside your cron function &#039;&#039;$this&#039;&#039; is defined, but it has almost nothing in it (only title and content fields are populated). If you need to execute cron for individual instances it is your own responsibility to iterate over them in the block&#039;s cron function. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function cron() {&lt;br /&gt;
&lt;br /&gt;
    global $DB; // Global database object&lt;br /&gt;
&lt;br /&gt;
    // Get the instances of the block&lt;br /&gt;
    $instances = $DB-&amp;gt;get_records( &#039;block_instance&#039;, array(&#039;blockid&#039;=&amp;gt;&#039;simplehtml&#039;) );&lt;br /&gt;
&lt;br /&gt;
    // Iterate over the instances&lt;br /&gt;
    foreach ($instances as $instance) {&lt;br /&gt;
&lt;br /&gt;
        // Recreate block object&lt;br /&gt;
        $block = block_instance(&#039;simplehtml&#039;, $instance);&lt;br /&gt;
&lt;br /&gt;
        // $block is now the equivalent of $this in &#039;normal&#039; block&lt;br /&gt;
        // usage, e.g.&lt;br /&gt;
        $someconfigitem = $block-&amp;gt;config-&amp;gt;item2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TIP: This also means that creating a block is a possible way to create code that can respond to cron with a reasonably low overhead. No actual instances of the block are required.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Additional Content Types == &lt;br /&gt;
&lt;br /&gt;
=== Lists ===&lt;br /&gt;
&lt;br /&gt;
In this final part of the guide we will briefly discuss several additional capabilities of Moodle&#039;s block system, namely the ability to create blocks that display different kinds of content to the user. The first of these creates a list of options and displays them to the user.  This list is displayed with one item per line, and an optional image (icon) next to the item. An example of such a &#039;&#039;list block&#039;&#039; is the standard Moodle &amp;quot;admin&amp;quot; block, which illustrates all the points discussed in this section.&lt;br /&gt;
&lt;br /&gt;
As we have seen so far, blocks use two properties of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]]: &amp;quot;text&amp;quot; and &amp;quot;footer&amp;quot;. The text is displayed as-is as the block content, and the footer is displayed below the content in a smaller font size. List blocks use $this-&amp;gt;content-&amp;gt;footer in the exact same way, but they ignore $this-&amp;gt;content-&amp;gt;text.&lt;br /&gt;
&lt;br /&gt;
Instead, Moodle expects such blocks to set two other properties when the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called: $this-&amp;gt;content-&amp;gt;items and $this-&amp;gt;content-&amp;gt;icons. $this-&amp;gt;content-&amp;gt;items should be a numerically indexed array containing elements that represent the HTML for each item in the list that is going to be displayed. Usually these items will be HTML anchor tags which provide links to some page. $this-&amp;gt;content-&amp;gt;icons should also be a numerically indexed array, with exactly as many items as $this-&amp;gt;content-&amp;gt;items has. Each of these items should be a fully qualified HTML &amp;lt;img&amp;gt; tag, with &amp;quot;src&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;width&amp;quot; and &amp;quot;alt&amp;quot; attributes. Obviously, it makes sense to keep the images small and of a uniform size. We would recommend standard 16x16 images for this purpose.&lt;br /&gt;
&lt;br /&gt;
In order to tell Moodle that we want to have a list block instead of the standard text block, we need to make a small change to our block class declaration. Instead of extending class &#039;&#039;&#039;block_base&#039;&#039;&#039;, our block will extend class &#039;&#039;&#039;block_list&#039;&#039;&#039;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
class block_my_menu extends block_list {&lt;br /&gt;
     // The init() method does not need to change at all&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition to making this change, we must of course also modify the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method to construct the [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] variable as discussed above:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function get_content() {&lt;br /&gt;
  if ($this-&amp;gt;content !== null) {&lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content         = new stdClass;&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items[] = html_writer::tag(&#039;a&#039;, &#039;Menu Option 1&#039;, array(&#039;href&#039; =&amp;gt; &#039;some_file.php&#039;));&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons[] = html_writer::empty_tag(&#039;img&#039;, array(&#039;src&#039; =&amp;gt; &#039;images/icons/1.gif&#039;, &#039;class&#039; =&amp;gt; &#039;icon&#039;));&lt;br /&gt;
&lt;br /&gt;
  // Add more list items here&lt;br /&gt;
 &lt;br /&gt;
  return $this-&amp;gt;content;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To summarise, if we want to create a list block instead of a text block, we just need to change the block class declaration and the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method. Adding the mandatory [[Blocks/Appendix_A#init.28.29| init()]] method as discussed earlier will then give us our first list block in no time!&lt;br /&gt;
&lt;br /&gt;
=== Trees ===&lt;br /&gt;
&lt;br /&gt;
As of 23rd December 2011, this functionality remains inoperable in all Moodle 2.x versions. It appears that classes are missing from the code base. This has been added to the tracker at the URL below. Please upvote this issue if you require this functionality.&lt;br /&gt;
&lt;br /&gt;
[http://tracker.moodle.org/browse/MDL-28289 Visit this issue on the tracker @ MDL28289]&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Database support ==&lt;br /&gt;
In case we need to have a database table that holds some specific information used within our block, we will need to create the file &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;install.xml&#039;&#039;&#039;&#039;&#039; with the table schema contained within it.&lt;br /&gt;
&lt;br /&gt;
To create the install.xml file, use the [[XMLDB editor]]. See [[Database_FAQ#XMLDB|Database FAQ &amp;gt; XMLDB]] for further details.&lt;br /&gt;
&lt;br /&gt;
Up-to-date documentation on upgrading our block, as well as providing new capabilities and events to the system, can be found under [https://docs.moodle.org/dev/Installing_and_upgrading_plugin_database_tables#install.php Installing and Upgrading Plugin Database Tables]&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Blocks Advanced]] A continuation of this tutorial.&lt;br /&gt;
* [http://dev.moodle.org/mod/resource/view.php?id=48 Unit 7 of the Introduction to Moodle Programming course] is a follow up to this course. (But you should follow the forum discussions of that course closely as there are still some bugs and inconsistencies.)&lt;br /&gt;
* A [http://cvs.moodle.org/contrib/plugins/blocks/NEWBLOCK/ NEWBLOCK template] you can all use to start you own block.&lt;br /&gt;
&lt;br /&gt;
== Appendices ==&lt;br /&gt;
&lt;br /&gt;
The appendices have been moved to separate pages:&lt;br /&gt;
&lt;br /&gt;
* Appendix A: [[Blocks/Appendix A|&#039;&#039;block_base&#039;&#039; Reference]] &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;br /&gt;
[[ja:開発:ブロック]]&lt;br /&gt;
[[:en:Blocks|Blocks]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=36119</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=36119"/>
		<updated>2012-11-08T08:21:15Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Ready, Set, Go! */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039; A Step-by-step Guide To Creating Blocks &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Original Author: Jon Papaioannou ([mailto:pj@moodle.org pj@moodle.org])&lt;br /&gt;
&lt;br /&gt;
Updated to Moodle 2.0 and above by: Greg J Preece ([mailto:greg.preece@blackboard.com greg.preece@blackboard.com])&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
The present document serves as a guide to developers who want to create their own blocks for use in Moodle. It applies to the 2.0 development version of Moodle (and any newer) &#039;&#039;&#039;only&#039;&#039;&#039;, as the blocks API changed significantly enough to warrant new documentation. Those wishing to read the old tutorial for Moodles 1.5 to 1.9 can find it under [[Blocks/Blocks for 1.5 to 1.9| Blocks for 1.5 to 1.9]].&lt;br /&gt;
&lt;br /&gt;
The guide is written as an interactive course which aims to develop a configurable, multi-purpose block that displays arbitrary HTML. It&#039;s targeted mainly at people with little experience with Moodle or programming in general and aims to show how easy it is to create new blocks for Moodle. A certain small amount of PHP programming knowledge is still required, though. &lt;br /&gt;
&lt;br /&gt;
Experienced developers and those who just want a &#039;&#039;&#039;programmer&#039;s reference&#039;&#039;&#039; text should refer to [[Blocks/Appendix_A| Appendix A]] because the main guide has a rather low concentration of pure information in the text.&lt;br /&gt;
&lt;br /&gt;
== Basic Concepts ==&lt;br /&gt;
&lt;br /&gt;
Through this guide, we will be following the creation of an &amp;quot;HTML&amp;quot; block from scratch in order to demonstrate most of the block features at our disposal. Our block will be named &amp;quot;SimpleHTML&amp;quot;. This does not constrain us regarding the name of the actual directory on the server where the files for our block will be stored, but for consistency we will follow the practice of using the lowercased form &amp;quot;simplehtml&amp;quot; in any case where such a name is required. &lt;br /&gt;
&lt;br /&gt;
Whenever we refer to a file or directory name which contains &amp;quot;simplehtml&amp;quot;, it&#039;s important to remember that &#039;&#039;only&#039;&#039; the &amp;quot;simplehtml&amp;quot; part is up to us to change; the rest is standardised and essential for Moodle to work correctly.&lt;br /&gt;
&lt;br /&gt;
Whenever a file&#039;s path is mentioned in this guide, it will always start with a slash. This refers to the Moodle home directory; all files and directories will be referred to with respect to that directory.&lt;br /&gt;
&lt;br /&gt;
== Ready, Set, Go! ==&lt;br /&gt;
&lt;br /&gt;
To define a &amp;quot;block&amp;quot; in Moodle, in the most basic case we need to provide just three PHP files. Here were are going to create a block called &#039;simplehtml&#039;, change any reference here to the name of the block you are creating. The three files are:&lt;br /&gt;
&lt;br /&gt;
; /blocks/simplehtml/block_simplehtml.php : This file will hold the class definition for the block, and is used both to manage it as a plugin and to render it onscreen.&lt;br /&gt;
&lt;br /&gt;
; /blocks/simplehtml/db/access.php : This file will hold the new capabilities created by the block.&lt;br /&gt;
&lt;br /&gt;
; /blocks/simplehtml/lang/en/block_simplehtml.php : This is the English language file for your block. If you are not an English speaker, you can replace &#039;en&#039; with your appropriate language code. All language files for blocks go under the /lang subfolder of the block&#039;s installation folder.&lt;br /&gt;
&lt;br /&gt;
; /blocks/simplehtml/version.php : This file will hold version information for the plugin, along with other advanced parameters (not covered here - see [[version.php]] if you want more details).&lt;br /&gt;
&lt;br /&gt;
We start by creating the directory &#039;&#039;/blocks/simplehtml/&#039;&#039; and creating the main object file, &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;&#039;&#039;block_simplehtml.php&#039;&#039;&#039;. We then begin coding the block:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
class block_simplehtml extends block_base {&lt;br /&gt;
    public function init() {&lt;br /&gt;
        $this-&amp;gt;title = get_string(&#039;simplehtml&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    // The PHP tag and the curly bracket for the class definition &lt;br /&gt;
    // will only be closed after there is another function added in the next section.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first line is our block class definition; it must be named exactly in the manner shown. Again, only the &amp;quot;simplehtml&amp;quot; part can (and indeed must) change; everything else is standardised.&lt;br /&gt;
&lt;br /&gt;
Our class is then given a small method: [[Blocks/Appendix_A#init.28.29| init()]]. This is essential for all blocks, and its purpose is to give values to any class member variables that need instantiating. &lt;br /&gt;
&lt;br /&gt;
In this very basic example, we only want to set [[Blocks/Appendix_A#.24this-.3Etitle| $this-&amp;gt;title]], which is the title displayed in the header of our block. We can set it to whatever we like; in this case it&#039;s set to read the actual title from the language file mentioned previously, which is then distributed along with the block. I&#039;ll skip ahead a bit here and say that if you want your block to display &#039;&#039;&#039;no&#039;&#039;&#039; title at all, then you should set this to any descriptive value you want (but &#039;&#039;&#039;not&#039;&#039;&#039; make it an empty string). We will later see [[Blocks#Eye_Candy|how to disable the title&#039;s display]].&lt;br /&gt;
&lt;br /&gt;
Moodle 2.4 onwards introduced the capability check addinstance and myaddinstance for each core block. They were introduced so that it was possible to control the use of individual blocks. These capabilities should also be added to your custom block. If your block is not going to be used in the &#039;My Moodle page&#039; (ie, your applicable_formats function (discussed later) has &#039;my&#039; set to false.) then the myaddinstance capability is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:myaddinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_SYSTEM,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;user&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/my:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    &#039;block/simplehtml:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_SPAM | RISK_XSS,&lt;br /&gt;
&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_BLOCK,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/site:manageblocks&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Moodle 2.0 and above require a name for our plugin to show in the upgrading page. We set this value, along with any other language strings we wish to use within the block, in a language package as previously mentioned (the same file where we put our string for the plugin title). Now we will create this language package. Create the file &#039;&#039;/blocks/simplehtml/lang/en/&#039;&#039;&#039;&#039;&#039;block_simplehtml.php&#039;&#039;&#039; and paste the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    $string[&#039;pluginname&#039;] = &#039;Simple html block&#039;;&lt;br /&gt;
    $string[&#039;simplehtml&#039;] = &#039;Simple html&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Prior to Moodle 2.0, version details for blocks were stored as class fields; as of Moodle 2.0 these are stored in a file called version.php, stored under &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039;. The version file is very simple indeed, containing only a few field definitions, depending on your needs. Here is an example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    $plugin-&amp;gt;version = 2011062800;  // YYYYMMDDHH (year, month, day, 24-hr time)&lt;br /&gt;
    $plugin-&amp;gt;requires = 2010112400; // YYYYMMDDHH (This is the release version for Moodle 2.0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file contains object field definitions that denote the version number of the block, along with the minimum version of Moodle that must be installed in order to use it. Please note that the object being used here is &#039;&#039;always&#039;&#039; called &#039;&#039;&#039;$plugin&#039;&#039;&#039;, and that you do not need to create this object yourself within the version file. Note also that we didnt include the closing &amp;quot;?&amp;gt;&amp;quot; tag for PHP. This is intentional, and a [[Coding_style#PHP_tags | workaround for whitespace issues]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== I Just Hear Static ==&lt;br /&gt;
In order to get our block to actually display something on screen, we need to add one more method to our class (before the final closing brace in our file). The new code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;  &lt;br /&gt;
  public function get_content() {&lt;br /&gt;
    if ($this-&amp;gt;content !== null) {&lt;br /&gt;
      return $this-&amp;gt;content;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;content         =  new stdClass;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text   = &#039;The content of our SimpleHTML block!&#039;;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
}   // Here&#039;s the closing bracket for the class definition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Add your block to the front page!&#039;&#039;&#039;&lt;br /&gt;
Don&#039;t forget (especially if you&#039;re a new Moodle user) to add your block to the front page. Turn Editing On, and add your block to the page.&lt;br /&gt;
&lt;br /&gt;
It can&#039;t get any simpler than that, can it? Let&#039;s dissect this method to see what&#039;s going on...&lt;br /&gt;
&lt;br /&gt;
First of all, there is a check that returns the current value of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] if it&#039;s not NULL; otherwise we proceed with &amp;quot;computing&amp;quot; it. Since the computation is potentially a time-consuming operation and it &#039;&#039;&#039;will&#039;&#039;&#039; be called several times for each block (Moodle works that way internally), we take a precaution and include this time-saver.&lt;br /&gt;
Supposing the content had not been computed before (it was NULL), we then define it from scratch. The code speaks for itself there, so there isn&#039;t much to say. Just keep in mind that we can use HTML both in the text &#039;&#039;&#039;and&#039;&#039;&#039; in the footer, if we want to.&lt;br /&gt;
&lt;br /&gt;
It&#039;s worth mentioning that this is not the only type of content a block can output. You can also create lists and hierarchical trees, which are better suited for certain types of output, such as menus. These different content types have an impact on the content object and how it is constructed. For more information, see [[Blocks/Appendix A#.24this-.3Econtent_type|Appendix A]]&lt;br /&gt;
&lt;br /&gt;
At this point our block should be capable of being automatically installed in Moodle and added to courses; visit your administration page to install it (Click &amp;quot;Notifications&amp;quot; under the Site Administration Block) and after seeing it in action come back to continue our tutorial.&lt;br /&gt;
&lt;br /&gt;
== Configure That Out ==&lt;br /&gt;
&lt;br /&gt;
The current version of our block doesn&#039;t really do much; it just displays a fixed message, which is not very useful. What we&#039;d really like to do is allow the teachers to customize what goes into the block. This, in block-speak, is called &amp;quot;instance configuration&amp;quot;. Basic instance configuration is automatic in Moodle 2.0; if you put any page with blocks on it into &amp;quot;editing mode&amp;quot;, you will notice that each block has an edit button in its title bar. Clicking on this will take you to the block configuration form. The settings that Moodle adds to this form by default relate to the block&#039;s appearance and position on Moodle pages. &lt;br /&gt;
&lt;br /&gt;
We can extend this configuration form, and add custom preferences fields, so that users can better tailor our block to a given task or page. To extend the configuration form, create the file &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&amp;lt;/span&amp;gt;, and fill it with the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class block_simplehtml_edit_form extends block_edit_form {&lt;br /&gt;
        &lt;br /&gt;
    protected function specific_definition($mform) {&lt;br /&gt;
        &lt;br /&gt;
        // Section header title according to language file.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;configheader&#039;, get_string(&#039;blocksettings&#039;, &#039;block&#039;));&lt;br /&gt;
&lt;br /&gt;
        // A sample string variable with a default value.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_text&#039;, get_string(&#039;blockstring&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;config_text&#039;, &#039;default value&#039;);&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;config_text&#039;, PARAM_MULTILANG);        &lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The first line declares a class that inherits &#039;&#039;&#039;from block_edit_form&#039;&#039;&#039;, and this allows Moodle to identify the code to execute in the configuration page. The &#039;&#039;&#039;specific_definition()&#039;&#039;&#039; method is where your form elements are defined, and these take the same format as with the standard [[lib/formslib.php_Form_Definition|Moodle form library]].  Within our specific_definition method, we have created a header, and an input field which will accept text to be used within the block.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; All your field names need to start with &amp;quot;config_&amp;quot;, otherwise they will not be saved and will not be available within the block via [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]]. &lt;br /&gt;
&lt;br /&gt;
So once our instance configuration form has been saved, we can use the inputted text within the block like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (! empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text = $this-&amp;gt;config-&amp;gt;text;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] is available in all block methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]. This is because [[Blocks/Appendix_A#init.28.29|init()]] is called immediately as the block is being created, with the purpose of setting things up, so [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] has not yet been instantiated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note about Checkbox:&#039;&#039;&#039; You cannot use the &#039;checkbox&#039; element in the form (once set it will stay set). You must use advcheckbox instead. &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Specialists ==&lt;br /&gt;
&lt;br /&gt;
Implementing instance configuration for the block&#039;s contents was good enough to whet our appetite, but who wants to stop there? Why not customize the block&#039;s title, too?&lt;br /&gt;
&lt;br /&gt;
Why not, indeed. Well, our first attempt to achieve this is natural enough: let&#039;s add another field to &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&#039;&#039;. Here goes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    // A sample string variable with a default value.&lt;br /&gt;
    $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_title&#039;, get_string(&#039;blocktitle&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
    $mform-&amp;gt;setDefault(&#039;config_title&#039;, &#039;default value&#039;);&lt;br /&gt;
    $mform-&amp;gt;setType(&#039;config_title&#039;, PARAM_MULTILANG);        &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We save the edited file, go to a course, edit the title of the block and... nothing happens! The instance configuration is saved correctly, all right (editing it once more proves that) but it&#039;s not being displayed. All we get is just the simple &amp;quot;SimpleHTML&amp;quot; title.&lt;br /&gt;
&lt;br /&gt;
That&#039;s not too weird, if we think back a bit. Do you remember that [[Blocks/Appendix_A#init.28.29|init()]] method, where we set [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]]? We didn&#039;t actually change its value from then, and [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] is definitely not the same as &#039;&#039;&#039;$this-&amp;gt;config-&amp;gt;title&#039;&#039;&#039; (to Moodle, at least). What we need is a way to update [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] with the value in the instance configuration. But as we said a bit earlier, we can use [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] in all methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]! So what can we do?&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pull out another ace from our sleeve, and add this small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function specialization() {&lt;br /&gt;
  if (!empty($this-&amp;gt;config-&amp;gt;title)) {&lt;br /&gt;
    $this-&amp;gt;title = $this-&amp;gt;config-&amp;gt;title;&lt;br /&gt;
  } else {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;title = &#039;Default title ...&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;text = &#039;Default text ...&#039;;&lt;br /&gt;
  }    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aha, here&#039;s what we wanted to do all along! But what&#039;s going on with the [[Blocks/Appendix_A#specialization.28.29| specialization()]] method?&lt;br /&gt;
&lt;br /&gt;
This &amp;quot;magic&amp;quot; method has actually a very nice property: it&#039;s &#039;&#039;guaranteed&#039;&#039; to be automatically called by Moodle as soon as our instance configuration is loaded and available (that is, immediately after [[Blocks/Appendix_A#init.28.29|init()]] is called). That means before the block&#039;s content is computed for the first time, and indeed before &#039;&#039;anything&#039;&#039; else is done with the block. Thus, providing a [[Blocks/Appendix_A#specialization.28.29| specialization()]] method is the natural choice for any configuration data that needs to be acted upon or made available &amp;quot;as soon as possible&amp;quot;, as in this case.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Now You See Me, Now You Don&#039;t ==&lt;br /&gt;
&lt;br /&gt;
Now would be a good time to mention another nifty technique that can be used in blocks, and which comes in handy quite often. Specifically, it may be the case that our block will have something interesting to display some of the time; but in some other cases, it won&#039;t have anything useful to say. An example here would be the &amp;quot;Recent Activity&amp;quot; block, in the case where no recent activity in fact exists. &lt;br /&gt;
&lt;br /&gt;
However in that case the block chooses to explicitly inform you of the lack of said activity, which is arguably useful. It would be nice, then, to be able to have our block &amp;quot;disappear&amp;quot; if it&#039;s not needed to display it.&lt;br /&gt;
&lt;br /&gt;
This is indeed possible, and the way to do it is to make sure that after the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called, the block has no content to display. This means that all fields in $this-&amp;gt;content should be equal to the empty string (&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;). In the case of our HTML-based block, these fields are $this-&amp;gt;content-&amp;gt;text and $this-&amp;gt;content-&amp;gt;footer. Moodle performs this check by calling the block&#039;s [[Blocks/Appendix_A#is_empty.28.29| is_empty()]] method, and if the block is indeed empty then it is not displayed at all.&lt;br /&gt;
&lt;br /&gt;
Note that the exact value of the block&#039;s title and the presence or absence of a [[Blocks/Appendix_A#hide_header.28.29| hide_header()]] method do &#039;&#039;not&#039;&#039; affect this behavior. A block is considered empty if it has no content, irrespective of anything else.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== We Are Legion ==&lt;br /&gt;
&lt;br /&gt;
Right now our block is fully configurable, both in title and content. It&#039;s so versatile, in fact, that we could make pretty much anything out of it. It would be really nice to be able to add multiple blocks of this type to a single course. And, as you might have guessed, doing that is as simple as adding another small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_allow_multiple() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells Moodle that it should allow any number of instances of the SimpleHTML block in any course. After saving the changes to our file, Moodle immediately allows us to add multiple copies of the block without further ado!&lt;br /&gt;
&lt;br /&gt;
Please note that even if a block itself allows multiple instances in the same page, the administrator still has the option of disallowing such behavior. This setting can be set separately for each block from the Administration / Configuration / Blocks page.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Effects of Globalization ==&lt;br /&gt;
&lt;br /&gt;
Configuring each block instance with its own personal data is cool enough, but sometimes administrators need some way to &amp;quot;touch&amp;quot; all instances of a specific block at the same time. In the case of our SimpleHTML block, a few settings that would make sense to apply to all instances aren&#039;t that hard to come up with. &lt;br /&gt;
&lt;br /&gt;
For example, we might want to limit the contents of each block to only so many characters, or we might have a setting that filters HTML out of the block&#039;s contents, only allowing pure text in. Granted, such a feature wouldn&#039;t win us any awards for naming our block &amp;quot;SimpleHTML&amp;quot; but some tormented administrator somewhere might actually find it useful.&lt;br /&gt;
&lt;br /&gt;
This kind of configuration is called &amp;quot;global configuration&amp;quot; and applies only to a specific block type (all instances of that block type are affected, however).  Implementing such configuration for our block is quite similar to implementing the instance configuration. We will now see how to implement the second example, having a setting that only allows text and not HTML in the block&#039;s contents. To enable global configuration for the block, we create a new file, &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;settings.php&#039;&#039;&#039;&#039;&#039;, and populate it with form field definitions for each setting, which Moodle will use to generate and handle a global settings form.  This is quite similar in concept to how we generated the instance configuration form earlier, but the actual code used to generate the form and fields is somewhat different.&lt;br /&gt;
&lt;br /&gt;
Place the following in your settings.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_heading(&lt;br /&gt;
            &#039;headerconfig&#039;,&lt;br /&gt;
            get_string(&#039;headerconfig&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descconfig&#039;, &#039;block_simplehtml&#039;)&lt;br /&gt;
        ));&lt;br /&gt;
&lt;br /&gt;
$settings-&amp;gt;add(new admin_setting_configcheckbox(&lt;br /&gt;
            &#039;simplehtml/Allow_HTML&#039;,&lt;br /&gt;
            get_string(&#039;labelallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            get_string(&#039;descallowhtml&#039;, &#039;block_simplehtml&#039;),&lt;br /&gt;
            &#039;0&#039;&lt;br /&gt;
        ));    &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, to generate a global configuration form, we simply create admin setting objects and add them to an array. This array is then stepped over to create the settings form, and the inputted data is automatically saved to the database. Full details of the setting types available and how to add them can be found under [[Admin_settings#Individual_settings]].&lt;br /&gt;
&lt;br /&gt;
We&#039;ve now created a header and checkbox form element to accept configuration details from the site admin. You should pay extra attention to the name of our checkbox element, &#039;&#039;&#039; &#039;simplehtml/Allow_HTML&#039; &#039;&#039;&#039;, as it specifies not only the name of the configuration option, but also how it should be stored. If you simply specify a name for the config option, it will be stored in the global $CFG object, and in the &#039;&#039;&amp;lt;prefix&amp;gt;_config&#039;&#039; database table. This will make your config variable available immediately via $CFG without requiring an additional database call, but will also increase the size of the $CFG object. In addition, we must prefix the variable with the name of our block, otherwise we run the risk of our config variable sharing its name with a similar variable in another plugin, or within Moodle itself.&lt;br /&gt;
&lt;br /&gt;
The preferred method of storing your block&#039;s configuration data is to prefix each config variable name in your settings.php file with your block&#039;s name, followed by a slash ( / ), and the name of the configuration variable, as we have done above. If you write your settings.php file in this way, then your variables will be stored in the &#039;&#039;&amp;lt;prefix&amp;gt;_config_plugin&#039;&#039; table, under your block&#039;s name. Your config data will still be available via a &#039;&#039;&#039;get_config()&#039;&#039;&#039; call, and name collision will be impossible between plugins.&lt;br /&gt;
&lt;br /&gt;
Finally, if you&#039;re wondering why there are two language tags specified for each element, the first tag is for the element&#039;s label or primary text, and the second tag is for its description. And that&#039;s it. Pretty easy, huh?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE FOR UPGRADERS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You&#039;ll notice that the settings.php file and parsed element names replaces Moodle&#039;s old storage method, wherein it would send all the configuration data to your block&#039;s [[Blocks/Appendix_A#config_save.28.29|config_save()]] method, and allow you to override how the data is saved. The [[Blocks/Appendix_A#config_save.28.29|config_save()]] method is no longer used in Moodle 2.x; however the [[Blocks/Appendix_A#instance_config_save.28.29|instance_config_save()]] method is very much alive and well, as you will see shortly.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Accessing Global Config Data  ===&lt;br /&gt;
&lt;br /&gt;
Now that we have global data defined for the plugin, we need to know how to access it within our code.  If you saved your config variables in the global namespace, you can access them from the global $CFG object, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = $CFG-&amp;gt;Allow_HTML;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If, as recommended, you saved your config variables in a custom namespace for your block, then you can access them via a call to &#039;&#039;&#039;get_config()&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$allowHTML = get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== Rolling It All Together ===&lt;br /&gt;
&lt;br /&gt;
OK, so we now have an instance configuration form that allows users to enter custom content text for a block, and a global configuration option that dictates whether or not that user should be allowed to enter HTML tags as part of the content. Now we just need to tie the two together. But if Moodle takes care of the form processing for our instance configuration in edit_form.php, how can we capture it and remove the HTML tags where required?&lt;br /&gt;
&lt;br /&gt;
Well, fortunately, there is a way this can be done.  By overriding the [[Blocks/Appendix_A#instance_config_save.28.29| instance_config_save()]] method in our block class, we can modify the way in which instance configuration data is stored after input. The default implementation is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data) {&lt;br /&gt;
  $data = stripslashes_recursive($data);&lt;br /&gt;
  $this-&amp;gt;config = $data;&lt;br /&gt;
  return set_field(&#039;block_instance&#039;, &lt;br /&gt;
                   &#039;configdata&#039;,&lt;br /&gt;
                    base64_encode(serialize($data)),&lt;br /&gt;
                   &#039;id&#039;, &lt;br /&gt;
                   $this-&amp;gt;instance-&amp;gt;id);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may look intimidating at first (what&#039;s all this stripslashes_recursive() and base64_encode() and serialize() stuff?) but do not despair; we won&#039;t have to touch any of it. We will only add some extra validation code in the beginning and then instruct Moodle to additionally call this default implementation to do the actual storing of the data. Specifically, we will add a method to our class which goes like this:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_config_save($data) {&lt;br /&gt;
  if(get_config(&#039;simplehtml&#039;, &#039;Allow_HTML&#039;) == &#039;1&#039;) {&lt;br /&gt;
    $data-&amp;gt;text = strip_tags($data-&amp;gt;text);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // And now forward to the default implementation defined in the parent class&lt;br /&gt;
  return parent::instance_config_save($data);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(This example assumes you are using a custom namespace for the block.)&lt;br /&gt;
&lt;br /&gt;
At last! Now the administrator has absolute power of life and death over what type of content is allowed in our &amp;quot;SimpleHTML&amp;quot; block! Absolute? Well... not exactly. In fact, if we think about it for a while, it will become apparent that if at some point in time HTML is allowed and some blocks have saved their content with HTML included, and afterwards the administrator changes the setting to &amp;quot;off&amp;quot;, this will only prevent subsequent content changes from including HTML. Blocks which already had HTML in their content would continue to display it!&lt;br /&gt;
&lt;br /&gt;
Following that train of thought, the next stop is realizing that we wouldn&#039;t have this problem if we had chosen the lazy approach a while back, because in that case we would &amp;quot;sanitize&amp;quot; each block&#039;s content just before it was displayed. &lt;br /&gt;
&lt;br /&gt;
The only thing we can do with the eager approach is strip all the tags from the content of all SimpleHTML instances as soon as the admin setting is changed to &amp;quot;HTML off&amp;quot;; but even then, turning the setting back to &amp;quot;HTML on&amp;quot; won&#039;t bring back the tags we stripped away. On the other hand, the lazy approach might be slower, but it&#039;s more versatile; we can choose whether to strip or keep the HTML before displaying the content, and we won&#039;t lose it at all if the admin toggles the setting off and on again. Isn&#039;t the life of a developer simple and wonderful?&lt;br /&gt;
&lt;br /&gt;
=== Exercise === &lt;br /&gt;
We will let this part of the tutorial come to a close with the obligatory exercise for the reader: &lt;br /&gt;
In order to have the SimpleHTML block work &amp;quot;correctly&amp;quot;, find out how to strengthen the eager approach to strip out all tags from the existing configuration of all instances of our block, &#039;&#039;&#039;or&#039;&#039;&#039; go back and implement the lazy approach instead. &lt;br /&gt;
(Hint: Do that in the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Eye Candy ==&lt;br /&gt;
&lt;br /&gt;
Our block is just about complete functionally, so now let&#039;s take a look at some of the tricks we can use to make its behavior customized in a few more useful ways.&lt;br /&gt;
&lt;br /&gt;
First of all, there are a couple of ways we can adjust the visual aspects of our block. For starters, it might be useful to create a block that doesn&#039;t display a header (title) at all. You can see this effect in action in the Course Description block that comes with Moodle. This behavior is achieved by, you guessed it, adding one more method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function hide_header() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One more note here: we cannot just set an empty title inside the block&#039;s [[Blocks/Appendix_A#init.28.29| init()]] method; it&#039;s necessary for each block to have a unique, non-empty title after [[Blocks/Appendix_A#init.28.29| init()]] is called so that Moodle can use those titles to differentiate between all of the installed blocks.&lt;br /&gt;
&lt;br /&gt;
Next, we can affect some properties of the actual HTML that will be used to print our block. Each block is fully contained within a &amp;amp;lt;div&amp;amp;gt; or &amp;amp;lt;table&amp;amp;gt; elements, inside which all the HTML for that block is printed. We can instruct Moodle to add HTML attributes with specific values to that container. This is generally done to give us freedom to customize the end result using CSS (this is in fact done by default as we&#039;ll see below).&lt;br /&gt;
&lt;br /&gt;
The default behavior of this feature in our case will modify our block&#039;s &amp;quot;class&amp;quot; HTML attribute by appending the value &amp;quot;block_simplehtml&amp;quot; (the prefix &amp;quot;block_&amp;quot; followed by the name of our block, lowercased). We can then use that class to make CSS selectors in our theme to alter this block&#039;s visual style (for example, &amp;quot;.block_simplehtml { border: 1px black solid}&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To change the default behavior, we will need to define a method which returns an associative array of attribute names and values. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function html_attributes() {&lt;br /&gt;
    $attributes = parent::html_attributes(); // Get default values&lt;br /&gt;
    $attributes[&#039;class&#039;] .= &#039; block_&#039;. $this-&amp;gt;name(); // Append our class to class attribute&lt;br /&gt;
    return $attributes;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This results in the block having all its normal HTML attributes, as inherited from the base block class, plus our additional class name. We can now use this class name to change the style of the block, add JavaScript events to it via YUI, and so on. And for one final elegant touch,  we have not set the class to the hard-coded value &amp;quot;block_simplehtml&amp;quot;, but instead used the [[Blocks/Appendix_A#name.28.29| name()]] method to make it dynamically match our block&#039;s name.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Authorized Personnel Only ==&lt;br /&gt;
&lt;br /&gt;
Some blocks are useful in some circumstances, but not in others. An example of this would be the &amp;quot;Social Activities&amp;quot; block, which is useful in courses with the &amp;quot;social&amp;quot; course format, but not courses with the &amp;quot;weeks&amp;quot; format. What we need to be able to do is limit our block&#039;s availability, so that it can only be selected on pages where its content or abilities are appropriate.&lt;br /&gt;
&lt;br /&gt;
Moodle allows us to declare which page formats a block is available on, and enforces these restrictions as set by the block&#039;s developer at all times. The information is given to Moodle as a standard associative array, with each key corresponding to a page format and defining a boolean value (true/false) that declares whether the block should be allowed to appear in that page format.&lt;br /&gt;
&lt;br /&gt;
Notice the deliberate use of the term &#039;&#039;page&#039;&#039; instead of &#039;&#039;course&#039;&#039; in the above paragraph. This is because in Moodle 1.5 and onwards, blocks can be displayed in any page that supports them. The best example of such pages are the course pages, but we are not restricted to them. For instance, the quiz view page (the first one we see when we click on the name of the quiz) also supports blocks.&lt;br /&gt;
&lt;br /&gt;
The format names we can use for the pages derive from the name of the script which is actually used to display that page. For example, when we are looking at a course, the script is &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/course/view.php&amp;lt;/span&amp;gt; (this is evident from the browser&#039;s address line). Thus, the format name of that page is &#039;&#039;&#039;course-view&#039;&#039;&#039;. It follows easily that the format name for a quiz view page is &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039;. This rule of thumb does have a few exceptions, however:&lt;br /&gt;
&lt;br /&gt;
# The format name for the front page of Moodle is &#039;&#039;&#039;site-index&#039;&#039;&#039;.&lt;br /&gt;
# The format name for courses is actually not just &#039;&#039;&#039;course-view&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;; it is &amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;course-view-weeks&#039;&#039;&#039;, &#039;&#039;&#039;course-view-topics&#039;&#039;&#039;, etc.&lt;br /&gt;
# Even though there is no such page, the format name &#039;&#039;&#039;all&#039;&#039;&#039; can be used as a catch-all option.&lt;br /&gt;
&lt;br /&gt;
We can include as many format names as we want in our definition of the applicable formats. Each format can be allowed or disallowed, and there are also three more rules that help resolve the question &amp;quot;is this block allowed into this page or not?&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
# Prefixes of a format name will match that format name; for example, &#039;&#039;&#039;mod&#039;&#039;&#039; will match all the activity modules. &#039;&#039;&#039;course-view&#039;&#039;&#039; will match any course, regardless of the course format. And finally, &#039;&#039;&#039;site&#039;&#039;&#039; will also match the front page (remember that its full format name is &#039;&#039;&#039;site-index&#039;&#039;&#039;).&lt;br /&gt;
# The more specialized a format name that matches our page is, the higher precedence it has when deciding if the block will be allowed. For example, &#039;&#039;&#039;mod&#039;&#039;&#039;, &#039;&#039;&#039;mod-quiz&#039;&#039;&#039; and &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; all match the quiz view page. But if all three are present, &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; will take precedence over the other two because it is a better match.&lt;br /&gt;
# The character &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; can be used in place of any word. For example, &#039;&#039;&#039;mod&#039;&#039;&#039; and &#039;&#039;&#039;mod-*&#039;&#039;&#039; are equivalent. At the time of this document&#039;s writing, there is no actual reason to utilize this &amp;quot;wildcard matching&amp;quot; feature, but it exists for future usage.&lt;br /&gt;
# The order that the format names appear does not make any difference.&lt;br /&gt;
All of the above are enough to make the situation sound complex, so let&#039;s look at some specific examples. First of all, to have our block appear &#039;&#039;&#039;only&#039;&#039;&#039; in the site front page, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&#039;site&#039; =&amp;gt; true);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Since &#039;&#039;&#039;all&#039;&#039;&#039; is missing, the block is disallowed from appearing in &#039;&#039;any&#039;&#039; course format; but then &#039;&#039;&#039;site&#039;&#039;&#039; is set to TRUE, so it&#039;s explicitly allowed to appear in the site front page (remember that &#039;&#039;&#039;site&#039;&#039;&#039; matches &#039;&#039;&#039;site-index&#039;&#039;&#039; because it&#039;s a prefix).&lt;br /&gt;
&lt;br /&gt;
For another example, if we wanted to allow the block to appear in all course formats &#039;&#039;except&#039;&#039; social, and also to &#039;&#039;not&#039;&#039; be allowed anywhere but in courses, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
    &#039;course-view-social&#039; =&amp;gt; false);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This time, we first allow the block to appear in all courses and then we explicitly disallow the social format.&lt;br /&gt;
For our final, most complicated example, suppose that a block can be displayed in the site front page, in courses (but not social courses) and also when we are viewing any activity module, &#039;&#039;except&#039;&#039; quiz. This would be:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;site-index&#039; =&amp;gt; true,&lt;br /&gt;
          &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
   &#039;course-view-social&#039; =&amp;gt; false,&lt;br /&gt;
                  &#039;mod&#039; =&amp;gt; true, &lt;br /&gt;
             &#039;mod-quiz&#039; =&amp;gt; false&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is not difficult to realize that the above accomplishes the objective if we remember that there is a &amp;quot;best match&amp;quot; policy to determine the end result.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Responding to Cron ==&lt;br /&gt;
&lt;br /&gt;
It is possible to have our block respond to the global Moodle cron process; we can have a method that is run at regular intervals regardless of user interaction. There are two parts to this. Firstly we need to define a new function within our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function cron() {&lt;br /&gt;
    mtrace( &amp;quot;Hey, my cron script is running&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
    // do something&lt;br /&gt;
&lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we will need to set the (minimum) execution interval for our cron function. Prior to Moodle 2.0, this was achieved by setting the value of a block&#039;s $this-&amp;gt;cron field, via the init() method. This is now achieved by adding an additional line to our &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;version.php&#039;&#039;&#039;&#039;&#039; file. Open it up and add the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $plugin-&amp;gt;cron = 300;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cron intervals are set in seconds, so the above line will set our minimum execution interval to 5 minutes. However, the function can only be called as frequently as cron has been set to run in the Moodle installation. So if our block is set to wait at least 5 minutes between runs, as in this example, but Moodle&#039;s cron system is only set to run every 24 hours, then our block is going to be waiting a lot longer between runs than we expected!&lt;br /&gt;
&lt;br /&gt;
Remember that if we change any values in the version file or block file we &#039;&#039;&#039;must&#039;&#039;&#039; bump the version number and visit the Notifications page to upgrade the block, otherwise they will be ignored.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039;&lt;br /&gt;
The block cron is designed to call the cron script for that block &#039;&#039;&#039;type&#039;&#039;&#039; only. That is, cron does not care about individual instances of blocks. Inside your cron function &#039;&#039;$this&#039;&#039; is defined, but it has almost nothing in it (only title and content fields are populated). If you need to execute cron for individual instances it is your own responsibility to iterate over them in the block&#039;s cron function. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function cron() {&lt;br /&gt;
&lt;br /&gt;
    global $DB; // Global database object&lt;br /&gt;
&lt;br /&gt;
    // Get the instances of the block&lt;br /&gt;
    $instances = $DB-&amp;gt;get_records( &#039;block_instance&#039;, array(&#039;blockid&#039;=&amp;gt;&#039;simplehtml&#039;) );&lt;br /&gt;
&lt;br /&gt;
    // Iterate over the instances&lt;br /&gt;
    foreach ($instances as $instance) {&lt;br /&gt;
&lt;br /&gt;
        // Recreate block object&lt;br /&gt;
        $block = block_instance(&#039;simplehtml&#039;, $instance);&lt;br /&gt;
&lt;br /&gt;
        // $block is now the equivalent of $this in &#039;normal&#039; block&lt;br /&gt;
        // usage, e.g.&lt;br /&gt;
        $someconfigitem = $block-&amp;gt;config-&amp;gt;item2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TIP: This also means that creating a block is a possible way to create code that can respond to cron with a reasonably low overhead. No actual instances of the block are required.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Additional Content Types == &lt;br /&gt;
&lt;br /&gt;
=== Lists ===&lt;br /&gt;
&lt;br /&gt;
In this final part of the guide we will briefly discuss several additional capabilities of Moodle&#039;s block system, namely the ability to create blocks that display different kinds of content to the user. The first of these creates a list of options and displays them to the user.  This list is displayed with one item per line, and an optional image (icon) next to the item. An example of such a &#039;&#039;list block&#039;&#039; is the standard Moodle &amp;quot;admin&amp;quot; block, which illustrates all the points discussed in this section.&lt;br /&gt;
&lt;br /&gt;
As we have seen so far, blocks use two properties of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]]: &amp;quot;text&amp;quot; and &amp;quot;footer&amp;quot;. The text is displayed as-is as the block content, and the footer is displayed below the content in a smaller font size. List blocks use $this-&amp;gt;content-&amp;gt;footer in the exact same way, but they ignore $this-&amp;gt;content-&amp;gt;text.&lt;br /&gt;
&lt;br /&gt;
Instead, Moodle expects such blocks to set two other properties when the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called: $this-&amp;gt;content-&amp;gt;items and $this-&amp;gt;content-&amp;gt;icons. $this-&amp;gt;content-&amp;gt;items should be a numerically indexed array containing elements that represent the HTML for each item in the list that is going to be displayed. Usually these items will be HTML anchor tags which provide links to some page. $this-&amp;gt;content-&amp;gt;icons should also be a numerically indexed array, with exactly as many items as $this-&amp;gt;content-&amp;gt;items has. Each of these items should be a fully qualified HTML &amp;lt;img&amp;gt; tag, with &amp;quot;src&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;width&amp;quot; and &amp;quot;alt&amp;quot; attributes. Obviously, it makes sense to keep the images small and of a uniform size. We would recommend standard 16x16 images for this purpose.&lt;br /&gt;
&lt;br /&gt;
In order to tell Moodle that we want to have a list block instead of the standard text block, we need to make a small change to our block class declaration. Instead of extending class &#039;&#039;&#039;block_base&#039;&#039;&#039;, our block will extend class &#039;&#039;&#039;block_list&#039;&#039;&#039;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
class block_my_menu extends block_list {&lt;br /&gt;
     // The init() method does not need to change at all&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition to making this change, we must of course also modify the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method to construct the [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] variable as discussed above:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
public function get_content() {&lt;br /&gt;
  if ($this-&amp;gt;content !== null) {&lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content         = new stdClass;&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items[] = html_writer::tag(&#039;a&#039;, &#039;Menu Option 1&#039;, array(&#039;href&#039; =&amp;gt; &#039;some_file.php&#039;));&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons[] = html_writer::empty_tag(&#039;img&#039;, array(&#039;src&#039; =&amp;gt; &#039;images/icons/1.gif&#039;, &#039;class&#039; =&amp;gt; &#039;icon&#039;));&lt;br /&gt;
&lt;br /&gt;
  // Add more list items here&lt;br /&gt;
 &lt;br /&gt;
  return $this-&amp;gt;content;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To summarise, if we want to create a list block instead of a text block, we just need to change the block class declaration and the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method. Adding the mandatory [[Blocks/Appendix_A#init.28.29| init()]] method as discussed earlier will then give us our first list block in no time!&lt;br /&gt;
&lt;br /&gt;
=== Trees ===&lt;br /&gt;
&lt;br /&gt;
As of 23rd December 2011, this functionality remains inoperable in all Moodle 2.x versions. It appears that classes are missing from the code base. This has been added to the tracker at the URL below. Please upvote this issue if you require this functionality.&lt;br /&gt;
&lt;br /&gt;
[http://tracker.moodle.org/browse/MDL-28289 Visit this issue on the tracker @ MDL28289]&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Database support ==&lt;br /&gt;
In case we need to have a database table that holds some specific information used within our block, we will need to create the file &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;install.xml&#039;&#039;&#039;&#039;&#039; with the table schema contained within it.&lt;br /&gt;
&lt;br /&gt;
To create the install.xml file, use the [[XMLDB editor]]. See [[Database_FAQ#XMLDB|Database FAQ &amp;gt; XMLDB]] for further details.&lt;br /&gt;
&lt;br /&gt;
Up-to-date documentation on upgrading our block, as well as providing new capabilities and events to the system, can be found under [https://docs.moodle.org/dev/Installing_and_upgrading_plugin_database_tables#install.php Installing and Upgrading Plugin Database Tables]&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Blocks Advanced]] A continuation of this tutorial.&lt;br /&gt;
* [http://dev.moodle.org/mod/resource/view.php?id=48 Unit 7 of the Introduction to Moodle Programming course] is a follow up to this course. (But you should follow the forum discussions of that course closely as there are still some bugs and inconsistencies.)&lt;br /&gt;
* A [http://cvs.moodle.org/contrib/plugins/blocks/NEWBLOCK/ NEWBLOCK template] you can all use to start you own block.&lt;br /&gt;
&lt;br /&gt;
== Appendices ==&lt;br /&gt;
&lt;br /&gt;
The appendices have been moved to separate pages:&lt;br /&gt;
&lt;br /&gt;
* Appendix A: [[Blocks/Appendix A|&#039;&#039;block_base&#039;&#039; Reference]] &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;br /&gt;
[[ja:開発:ブロック]]&lt;br /&gt;
[[:en:Blocks|Blocks]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Common_unit_test_problems&amp;diff=36117</id>
		<title>Common unit test problems</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Common_unit_test_problems&amp;diff=36117"/>
		<updated>2012-11-08T04:19:09Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Unit tests are taking more than 5 mins to run ===&lt;br /&gt;
This problem is under investigation. We are hoping to find the soluton. On a typical system all tests complete in under 3 mins.--[[User:Dan Poltawski|Dan Poltawski]] 12:43, 15 May 2012 (WST)&lt;br /&gt;
&lt;br /&gt;
You maybe find much better performance on psql as a workaround for now if not doing DB dependent tests.&lt;br /&gt;
&lt;br /&gt;
=== dml_testcase::test_unique_index_collation_trouble===&lt;br /&gt;
&amp;quot;Unique index is accent insensitive, this may cause problems for non-ascii languages. This is usually caused by accent insensitive default collation.&amp;quot;&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your Database is incorrectly configured. You probably are running MySQL and need to switch to utf8_unicode_ci collation.&lt;br /&gt;
&lt;br /&gt;
=== dml_testcase::test_sql_binary_equal ===&lt;br /&gt;
&amp;quot;SQL operator &amp;quot;=&amp;quot; is expected to be case sensitive Failed asserting that 1 matches expected 2.&amp;quot;&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your Database is incorrectly configured. You probably are running MySQL and need to switch to utf8_unicode_ci collation.&lt;br /&gt;
&lt;br /&gt;
=== moodlesimplepie_testcase::test_getfeed ===&lt;br /&gt;
&amp;quot;Failed to load the sample RSS file. Please check your proxy settings in Moodle. %s&amp;quot;&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your moodle needs network connectivity, please check proxy settings.&lt;br /&gt;
&lt;br /&gt;
=== moodlesimplepie_testcase::test_redirect ===&lt;br /&gt;
Failed asserting that &#039;cURL Error: Operation timed out after 2000 milliseconds with 0 bytes received&#039; is null.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your moodle needs network connectivity, please check proxy settings&lt;br /&gt;
&lt;br /&gt;
=== collatorlib_testcase::test_asort_objects_by_method ===&lt;br /&gt;
Collation aware sorting not supported, PHP extension &amp;quot;intl&amp;quot; is not available.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Install php intl extension.&lt;br /&gt;
&lt;br /&gt;
Note that, on Windows, this extension does not seem to be included in the installer, but you can get it by downloading the zip, and copying the right DLLs across. If you Google, there are more detailed instructions on Stack Exchange.&lt;br /&gt;
&lt;br /&gt;
=== grading_manager_testcase::test_tokenize===&lt;br /&gt;
A test using UTF-8 characters has failed. Consider updating PHP and PHP&#039;s PCRE or INTL extensions (MDL-30494) Failed asserting that false is true.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your Database is incorrectly configured. You probably are running MySQL and need to switch to utf8_bin collation.&lt;br /&gt;
&lt;br /&gt;
===  moodlelib_testcase::test_fix_utf8 ===&lt;br /&gt;
Failed asserting that false is identical to &#039;aaabbb&#039;.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
This problem indicates buggy iconv. See [http://tracker.moodle.org/browse/MDL-33007] for discussion.  So this is a real problem, to be fixed in a future integration cycle&lt;br /&gt;
&lt;br /&gt;
=== Segfaults on Oracle ===&lt;br /&gt;
When I was running tests on oracle I was getting phpunit sefaulting.. --[[User:Dan Poltawski|Dan Poltawski]] 00:29, 16 May 2012 (WST)&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Set statement_cache_size in php.ini:&lt;br /&gt;
oci8.statement_cache_size = 0&lt;br /&gt;
&lt;br /&gt;
=== filestoragelib_testcase::test_get_file_preview ===&lt;br /&gt;
Failed asserting that false is an instance of class &amp;quot;stored_file&amp;quot;.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Related to installing GD after you initialised PHP Unit.&lt;br /&gt;
&lt;br /&gt;
Go to your Moodle directory and type &#039;php admin/tool/phpunit/cli/util.php --drop&#039;, then reinitialise PHPunit and run the test again.&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Common_unit_test_problems&amp;diff=36116</id>
		<title>Common unit test problems</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Common_unit_test_problems&amp;diff=36116"/>
		<updated>2012-11-08T04:04:13Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Solution = */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Unit tests are taking more than 5 mins to run ===&lt;br /&gt;
This problem is under investigation. We are hoping to find the soluton. On a typical system all tests complete in under 3 mins.--[[User:Dan Poltawski|Dan Poltawski]] 12:43, 15 May 2012 (WST)&lt;br /&gt;
&lt;br /&gt;
You maybe find much better performance on psql as a workaround for now if not doing DB dependent tests.&lt;br /&gt;
&lt;br /&gt;
=== dml_testcase::test_unique_index_collation_trouble===&lt;br /&gt;
&amp;quot;Unique index is accent insensitive, this may cause problems for non-ascii languages. This is usually caused by accent insensitive default collation.&amp;quot;&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your Database is incorrectly configured. You probably are running MySQL and need to switch to utf8_unicode_ci collation.&lt;br /&gt;
&lt;br /&gt;
=== dml_testcase::test_sql_binary_equal ===&lt;br /&gt;
&amp;quot;SQL operator &amp;quot;=&amp;quot; is expected to be case sensitive Failed asserting that 1 matches expected 2.&amp;quot;&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your Database is incorrectly configured. You probably are running MySQL and need to switch to utf8_unicode_ci collation.&lt;br /&gt;
&lt;br /&gt;
=== moodlesimplepie_testcase::test_getfeed ===&lt;br /&gt;
&amp;quot;Failed to load the sample RSS file. Please check your proxy settings in Moodle. %s&amp;quot;&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your moodle needs network connectivity, please check proxy settings.&lt;br /&gt;
&lt;br /&gt;
=== moodlesimplepie_testcase::test_redirect ===&lt;br /&gt;
Failed asserting that &#039;cURL Error: Operation timed out after 2000 milliseconds with 0 bytes received&#039; is null.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your moodle needs network connectivity, please check proxy settings&lt;br /&gt;
&lt;br /&gt;
=== collatorlib_testcase::test_asort_objects_by_method ===&lt;br /&gt;
Collation aware sorting not supported, PHP extension &amp;quot;intl&amp;quot; is not available.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Install php intl extension.&lt;br /&gt;
&lt;br /&gt;
Note that, on Windows, this extension does not seem to be included in the installer, but you can get it by downloading the zip, and copying the right DLLs across. If you Google, there are more detailed instructions on Stack Exchange.&lt;br /&gt;
&lt;br /&gt;
=== grading_manager_testcase::test_tokenize===&lt;br /&gt;
A test using UTF-8 characters has failed. Consider updating PHP and PHP&#039;s PCRE or INTL extensions (MDL-30494) Failed asserting that false is true.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your Database is incorrectly configured. You probably are running MySQL and need to switch to utf8_bin collation.&lt;br /&gt;
&lt;br /&gt;
===  moodlelib_testcase::test_fix_utf8 ===&lt;br /&gt;
Failed asserting that false is identical to &#039;aaabbb&#039;.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
This problem indicates buggy iconv. See [http://tracker.moodle.org/browse/MDL-33007] for discussion.  So this is a real problem, to be fixed in a future integration cycle&lt;br /&gt;
&lt;br /&gt;
=== Segfaults on Oracle ===&lt;br /&gt;
When I was running tests on oracle I was getting phpunit sefaulting.. --[[User:Dan Poltawski|Dan Poltawski]] 00:29, 16 May 2012 (WST)&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Set statement_cache_size in php.ini:&lt;br /&gt;
oci8.statement_cache_size = 0&lt;br /&gt;
&lt;br /&gt;
=== filestoragelib_testcase::test_get_file_preview ===&lt;br /&gt;
Failed asserting that false is an instance of class &amp;quot;stored_file&amp;quot;.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Go to Dan P&#039;s computer and disturb him.&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Common_unit_test_problems&amp;diff=36115</id>
		<title>Common unit test problems</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Common_unit_test_problems&amp;diff=36115"/>
		<updated>2012-11-08T04:03:51Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Unit tests are taking more than 5 mins to run ===&lt;br /&gt;
This problem is under investigation. We are hoping to find the soluton. On a typical system all tests complete in under 3 mins.--[[User:Dan Poltawski|Dan Poltawski]] 12:43, 15 May 2012 (WST)&lt;br /&gt;
&lt;br /&gt;
You maybe find much better performance on psql as a workaround for now if not doing DB dependent tests.&lt;br /&gt;
&lt;br /&gt;
=== dml_testcase::test_unique_index_collation_trouble===&lt;br /&gt;
&amp;quot;Unique index is accent insensitive, this may cause problems for non-ascii languages. This is usually caused by accent insensitive default collation.&amp;quot;&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your Database is incorrectly configured. You probably are running MySQL and need to switch to utf8_unicode_ci collation.&lt;br /&gt;
&lt;br /&gt;
=== dml_testcase::test_sql_binary_equal ===&lt;br /&gt;
&amp;quot;SQL operator &amp;quot;=&amp;quot; is expected to be case sensitive Failed asserting that 1 matches expected 2.&amp;quot;&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your Database is incorrectly configured. You probably are running MySQL and need to switch to utf8_unicode_ci collation.&lt;br /&gt;
&lt;br /&gt;
=== moodlesimplepie_testcase::test_getfeed ===&lt;br /&gt;
&amp;quot;Failed to load the sample RSS file. Please check your proxy settings in Moodle. %s&amp;quot;&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your moodle needs network connectivity, please check proxy settings.&lt;br /&gt;
&lt;br /&gt;
=== moodlesimplepie_testcase::test_redirect ===&lt;br /&gt;
Failed asserting that &#039;cURL Error: Operation timed out after 2000 milliseconds with 0 bytes received&#039; is null.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your moodle needs network connectivity, please check proxy settings&lt;br /&gt;
&lt;br /&gt;
=== collatorlib_testcase::test_asort_objects_by_method ===&lt;br /&gt;
Collation aware sorting not supported, PHP extension &amp;quot;intl&amp;quot; is not available.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Install php intl extension.&lt;br /&gt;
&lt;br /&gt;
Note that, on Windows, this extension does not seem to be included in the installer, but you can get it by downloading the zip, and copying the right DLLs across. If you Google, there are more detailed instructions on Stack Exchange.&lt;br /&gt;
&lt;br /&gt;
=== grading_manager_testcase::test_tokenize===&lt;br /&gt;
A test using UTF-8 characters has failed. Consider updating PHP and PHP&#039;s PCRE or INTL extensions (MDL-30494) Failed asserting that false is true.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Your Database is incorrectly configured. You probably are running MySQL and need to switch to utf8_bin collation.&lt;br /&gt;
&lt;br /&gt;
===  moodlelib_testcase::test_fix_utf8 ===&lt;br /&gt;
Failed asserting that false is identical to &#039;aaabbb&#039;.&lt;br /&gt;
==== Solution ====&lt;br /&gt;
This problem indicates buggy iconv. See [http://tracker.moodle.org/browse/MDL-33007] for discussion.  So this is a real problem, to be fixed in a future integration cycle&lt;br /&gt;
&lt;br /&gt;
=== Segfaults on Oracle ===&lt;br /&gt;
When I was running tests on oracle I was getting phpunit sefaulting.. --[[User:Dan Poltawski|Dan Poltawski]] 00:29, 16 May 2012 (WST)&lt;br /&gt;
==== Solution ====&lt;br /&gt;
Set statement_cache_size in php.ini:&lt;br /&gt;
oci8.statement_cache_size = 0&lt;br /&gt;
&lt;br /&gt;
=== filestoragelib_testcase::test_get_file_preview ===&lt;br /&gt;
Failed asserting that false is an instance of class &amp;quot;stored_file&amp;quot;.&lt;br /&gt;
=== Solution ====&lt;br /&gt;
Go to Dan P&#039;s computer and disturb him.&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=36046</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=36046"/>
		<updated>2012-11-06T07:16:33Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* access.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabilities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the [[XMLDB_editor]]. Your module should always have a table with the same name as the module with the fields id, name and course as shown above.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the [[XMLDB_editor]] to change the install.xml file AND create the upgrade path.&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;modname&amp;gt;_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The &amp;lt;modname&amp;gt;_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The &amp;lt;modname&amp;gt;_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders it&#039;s page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35880</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35880"/>
		<updated>2012-10-19T04:11:10Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* lib.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the [[XMLDB_editor]]. Your module should always have a table with the same name as the module with the fields id, name and course as shown above.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the [[XMLDB_editor]] to change the install.xml file AND create the upgrade path.&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;modname&amp;gt;_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The &amp;lt;modname&amp;gt;_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The &amp;lt;modname&amp;gt;_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders it&#039;s page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35879</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35879"/>
		<updated>2012-10-19T04:09:48Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* upgrade.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the [[XMLDB_editor]]. Your module should always have a table with the same name as the module with the fields id, name and course as shown above.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the [[XMLDB_editor]] to change the install.xml file AND create the upgrade path.&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders it&#039;s page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35878</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35878"/>
		<updated>2012-10-19T04:08:40Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* install.xml */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the [[XMLDB_editor]]. Your module should always have a table with the same name as the module with the fields id, name and course as shown above.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders it&#039;s page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35877</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35877"/>
		<updated>2012-10-19T04:08:06Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* install.xml */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the [[XMLDB_editor]]. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders it&#039;s page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35876</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35876"/>
		<updated>2012-10-19T04:07:08Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* access.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders it&#039;s page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35875</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35875"/>
		<updated>2012-10-19T04:06:39Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* access.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create, if there are no new capabilities needed then this file is not needed. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders it&#039;s page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35874</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35874"/>
		<updated>2012-10-19T04:02:57Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Standard Files and their Functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that are crucial to Moodle. These files are used to install your module and then integrate it into the Moodle system. Each file has a particular function, some of the files are not necessary and are only created when wanting to use the functionality it offers. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders it&#039;s page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35873</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35873"/>
		<updated>2012-10-19T02:38:27Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== index.php ===&lt;br /&gt;
&lt;br /&gt;
This page is used by Moodle when listing all the instances of your module that are in a particular course with the course id being passed to this script. The beginning of the page should contain the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);           // Course ID&lt;br /&gt;
&lt;br /&gt;
// Ensure that the course specified is valid&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;Course ID is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are then free to display the list of instances as you wish.&lt;br /&gt;
&lt;br /&gt;
=== view.php ===&lt;br /&gt;
&lt;br /&gt;
When a course renders it&#039;s page layout and activities it generates the links to view them using the view.php script, so the links will look like &amp;lt;wwwrootofyoursite&amp;gt;/mod/&amp;lt;modname&amp;gt;/view.php?id=4, where 4 is the course module id. For the certificate example the beginning of the view.php page looks like the following -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
$id = required_param(&#039;id&#039;, PARAM_INT);    // Course Module ID&lt;br /&gt;
&lt;br /&gt;
if (!$cm = get_coursemodule_from_id(&#039;certificate&#039;, $id)) {&lt;br /&gt;
    print_error(&#039;Course Module ID was incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;course))) {&lt;br /&gt;
    print_error(&#039;course is misconfigured&#039;);&lt;br /&gt;
}&lt;br /&gt;
if (!$certificate = $DB-&amp;gt;get_record(&#039;certificate&#039;, array(&#039;id&#039;=&amp;gt; $cm-&amp;gt;instance))) {&lt;br /&gt;
    print_error(&#039;course module is incorrect&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course module id is passed to this script and set as $id, which is then used to retrieve the course data and the information from the certificate table which we can use later on as we wish.&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35864</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35864"/>
		<updated>2012-10-18T09:32:44Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* lib.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit. The id of the instance you are editing is passed as the attribute instance and can be used to edit any existing values in the database for that instance.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the id in the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35863</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35863"/>
		<updated>2012-10-18T09:31:15Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* lib.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is first created, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35862</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35862"/>
		<updated>2012-10-18T09:30:26Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Standard Files and their Functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files.&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35861</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35861"/>
		<updated>2012-10-18T09:30:01Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
Below is an example of the file structure for the certificate plugin.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35860</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35860"/>
		<updated>2012-10-18T09:29:39Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure. Please note, any reference to &amp;lt;modname&amp;gt; in this documentation should be replaced by the name of your module.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35859</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35859"/>
		<updated>2012-10-18T09:28:40Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* lib.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Replace certificate with the name of your module.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35858</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35858"/>
		<updated>2012-10-18T09:26:18Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* upgrade.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached.&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function &amp;lt;modname&amp;gt;_add_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_update_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case &amp;lt;modname&amp;gt; is replaced with certificate.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35857</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35857"/>
		<updated>2012-10-18T09:26:03Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* upgrade.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091800) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Certificate savepoint reached&lt;br /&gt;
        upgrade_mod_savepoint(true, 2012091800, &#039;certificate&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function &amp;lt;modname&amp;gt;_add_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_update_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case &amp;lt;modname&amp;gt; is replaced with certificate.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35856</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35856"/>
		<updated>2012-10-18T09:24:25Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* upgrade.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091801) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new value we put in the version.php file) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function &amp;lt;modname&amp;gt;_add_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_update_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case &amp;lt;modname&amp;gt; is replaced with certificate.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35855</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35855"/>
		<updated>2012-10-18T09:23:16Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* upgrade.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Update the version number in your version.php file.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091801) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new version.php numer) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function &amp;lt;modname&amp;gt;_add_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_update_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case &amp;lt;modname&amp;gt; is replaced with certificate.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35854</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35854"/>
		<updated>2012-10-18T09:21:06Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&lt;br /&gt;
3. Update the version number in your version.php file.&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091801) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new version.php numer) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function &amp;lt;modname&amp;gt;_add_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_update_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case &amp;lt;modname&amp;gt; is replaced with certificate.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35853</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35853"/>
		<updated>2012-10-18T09:20:34Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.  They are the oldest type of plugins in Moodle - that&#039;s why they have this overly-generic name and also why they have a few idiosyncrasies and operate slightly differently from all the plugins that came later.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&lt;br /&gt;
3. Update the version number in your version.php file.&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091801) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new version.php numer) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function &amp;lt;modname&amp;gt;_add_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_update_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case &amp;lt;modname&amp;gt; is replaced with certificate.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:Activities_file_structure_example.jpg&amp;diff=35852</id>
		<title>File:Activities file structure example.jpg</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:Activities_file_structure_example.jpg&amp;diff=35852"/>
		<updated>2012-10-18T09:20:13Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35851</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35851"/>
		<updated>2012-10-18T09:18:13Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* lib.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.  They are the oldest type of plugins in Moodle - that&#039;s why they have this overly-generic name and also why they have a few idiosyncrasies and operate slightly differently from all the plugins that came later.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&lt;br /&gt;
3. Update the version number in your version.php file.&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091801) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new version.php numer) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function &amp;lt;modname&amp;gt;_add_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_update_instance($certificate);&lt;br /&gt;
function &amp;lt;modname&amp;gt;_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case &amp;lt;modname&amp;gt; is replaced with certificate.&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35850</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35850"/>
		<updated>2012-10-18T09:17:35Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* mod_form.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.  They are the oldest type of plugins in Moodle - that&#039;s why they have this overly-generic name and also why they have a few idiosyncrasies and operate slightly differently from all the plugins that came later.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&lt;br /&gt;
3. Update the version number in your version.php file.&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091801) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new version.php numer) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module. The class in the file should be called mod_&amp;lt;modname&amp;gt;_mod_form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $ynoptions = array(0 =&amp;gt; get_string(&#039;no&#039;),&lt;br /&gt;
                           1 =&amp;gt; get_string(&#039;yes&#039;));&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;usecode&#039;, get_string(&#039;usecode&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;usecode&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;usecode&#039;, &#039;usecode&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to display the unique code issued to a user when they receive the certificate or not with a default value of 0 and a help button explaining what this setting does. The function standard_coursemodule_elements adds the elements common to all modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either &amp;lt;modname&amp;gt;_add_instance or &amp;lt;modname&amp;gt;_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35849</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35849"/>
		<updated>2012-10-18T09:13:49Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* lib.php */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.  They are the oldest type of plugins in Moodle - that&#039;s why they have this overly-generic name and also why they have a few idiosyncrasies and operate slightly differently from all the plugins that came later.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&lt;br /&gt;
3. Update the version number in your version.php file.&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091801) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new version.php numer) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;savecert&#039;, get_string(&#039;savecert&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;savecert&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;savecert&#039;, &#039;savecert&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to store the PDF generated by the certificate on the filesystem or not with a default value of 0 and a help button explaining what it&#039;s function is. The function standard_coursemodule_elements adds the elements common to the modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either certificate_add_instance or certificate_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35848</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35848"/>
		<updated>2012-10-18T09:13:04Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* install.xml */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.  They are the oldest type of plugins in Moodle - that&#039;s why they have this overly-generic name and also why they have a few idiosyncrasies and operate slightly differently from all the plugins that came later.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&lt;br /&gt;
3. Update the version number in your version.php file.&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091801) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new version.php numer) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;savecert&#039;, get_string(&#039;savecert&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;savecert&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;savecert&#039;, &#039;savecert&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to store the PDF generated by the certificate on the filesystem or not with a default value of 0 and a help button explaining what it&#039;s function is. The function standard_coursemodule_elements adds the elements common to the modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either certificate_add_instance or certificate_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35847</id>
		<title>Activity modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Activity_modules&amp;diff=35847"/>
		<updated>2012-10-18T09:12:31Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Activity modules reside in the &#039;&#039;&#039;/mod&#039;&#039;&#039; directory.  They are the oldest type of plugins in Moodle - that&#039;s why they have this overly-generic name and also why they have a few idiosyncrasies and operate slightly differently from all the plugins that came later.&lt;br /&gt;
&lt;br /&gt;
Each module is in a separate subdirectory and consists of a number of &#039;&#039;&#039;&#039;mandatory files&#039;&#039;&#039;&#039; and any other files the developer is going to use. The below image is an example of the certificate module&#039;s filestructure.&lt;br /&gt;
&lt;br /&gt;
[[File:Activities_file_structure_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Standard Files and their Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several files that Moodle looks for when using your module, they each have a particular function and are all not necessary. Below are the list of most commonly used files, to view them all please&lt;br /&gt;
&lt;br /&gt;
=== Backup Folder ===&lt;br /&gt;
&lt;br /&gt;
This is the location to place the files that define how your module is going to behave when a course backup or restore is performed. You may have added a lot of information to the database for a specific module that you do not wish to enter again when restoring a course, this is where you define what should be saved during a backup and how to then restore this information from the Moodle backup.&lt;br /&gt;
&lt;br /&gt;
To read more on this please visit [[Backup_2.0_for_developers]] and [[Restore_2.0_for_developers]].&lt;br /&gt;
&lt;br /&gt;
=== DB Folder ===&lt;br /&gt;
&lt;br /&gt;
==== access.php ====&lt;br /&gt;
&lt;br /&gt;
This is where you define what capabilities your plugin will create. Note, if you add new capabilities to this file after your plugin has been installed you will need to increase the version number in your version.php file (discussed later) in order for them to be installed.&lt;br /&gt;
&lt;br /&gt;
An example of the file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
&lt;br /&gt;
    &#039;mod/certificate:addinstance&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;riskbitmask&#039; =&amp;gt; RISK_XSS,&lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;write&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;archetypes&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;clonepermissionsfrom&#039; =&amp;gt; &#039;moodle/course:manageactivities&#039;&lt;br /&gt;
    ),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.3 a new capability called &#039;addinstance&#039; was added for all core modules. Moodle will look for this capability by searching for &#039;mod/&amp;lt;modname&amp;gt;:addinstance&#039; and if it is not created then it assumed that the user does have this capability with a debug message being displayed that the capability is missing. To avoid this situation it is good to add this to your module. For further information on what each attribute in that capabalities array means visit [[NEWMODULE_Adding_capabilities]].&lt;br /&gt;
&lt;br /&gt;
==== install.xml ====&lt;br /&gt;
&lt;br /&gt;
This file is used on installation of your module. It includes the database tables and fields that your module will be creating. If your module does not require any new tables then this file is not necessary. In order to create this XML file please view [[XMLDB_editor]]. Please note, in the XML file the table names are listed without the config.php prefix, this is automatically used when creating the tables and does not need to be specified.&lt;br /&gt;
&lt;br /&gt;
An example of this file is below -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;br /&gt;
&amp;lt;XMLDB PATH=&amp;quot;mod/certificate/db&amp;quot; VERSION=&amp;quot;20120925&amp;quot; COMMENT=&amp;quot;XMLDB file for Moodle mod/certificate&amp;quot;&lt;br /&gt;
    xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;br /&gt;
    xsi:noNamespaceSchemaLocation=&amp;quot;../../../lib/xmldb/xmldb.xsd&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
  &amp;lt;TABLES&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate&amp;quot; COMMENT=&amp;quot;Defines certificates&amp;quot; NEXT=&amp;quot;certificate_issues&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;course&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;course&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;name&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;name&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;course&amp;quot; NEXT=&amp;quot;intro&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;intro&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;name&amp;quot; NEXT=&amp;quot;introformat&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;introformat&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;4&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;intro&amp;quot; NEXT=&amp;quot;emailteachers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailteachers&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;introformat&amp;quot; NEXT=&amp;quot;emailothers&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;emailothers&amp;quot; TYPE=&amp;quot;text&amp;quot; LENGTH=&amp;quot;small&amp;quot; NOTNULL=&amp;quot;false&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailteachers&amp;quot; NEXT=&amp;quot;savecert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;savecert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;emailothers&amp;quot; NEXT=&amp;quot;reportcert&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;reportcert&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;1&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;savecert&amp;quot; NEXT=&amp;quot;delivery&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;delivery&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;3&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;reportcert&amp;quot; NEXT=&amp;quot;requiredtime&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;requiredtime&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;delivery&amp;quot; NEXT=&amp;quot;type&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;type&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;50&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;requiredtime&amp;quot; NEXT=&amp;quot;orientation&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;orientation&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;type&amp;quot; NEXT=&amp;quot;width&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;width&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;orientation&amp;quot; NEXT=&amp;quot;height&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;height&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;width&amp;quot; NEXT=&amp;quot;backgroundimage&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;backgroundimage&amp;quot; TYPE=&amp;quot;char&amp;quot; LENGTH=&amp;quot;255&amp;quot; NOTNULL=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;height&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;backgroundimage&amp;quot;  NEXT=&amp;quot;timemodified&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timemodified&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
    &amp;lt;TABLE NAME=&amp;quot;certificate_issues&amp;quot; COMMENT=&amp;quot;Info about issued certificates&amp;quot; PREVIOUS=&amp;quot;certificate&amp;quot; NEXT=&amp;quot;certificate_images&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;FIELDS&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;id&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; SEQUENCE=&amp;quot;true&amp;quot; ENUM=&amp;quot;false&amp;quot; NEXT=&amp;quot;userid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;userid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;id&amp;quot; NEXT=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;certificateid&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;userid&amp;quot; NEXT=&amp;quot;timecreated&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;FIELD NAME=&amp;quot;timecreated&amp;quot; TYPE=&amp;quot;int&amp;quot; LENGTH=&amp;quot;10&amp;quot; NOTNULL=&amp;quot;true&amp;quot; UNSIGNED=&amp;quot;true&amp;quot; DEFAULT=&amp;quot;0&amp;quot; SEQUENCE=&amp;quot;false&amp;quot; ENUM=&amp;quot;false&amp;quot; PREVIOUS=&amp;quot;certificateid&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/FIELDS&amp;gt;&lt;br /&gt;
      &amp;lt;KEYS&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;primary&amp;quot; TYPE=&amp;quot;primary&amp;quot; FIELDS=&amp;quot;id&amp;quot; COMMENT=&amp;quot;Primary key for certificate_issues&amp;quot; NEXT=&amp;quot;certificate&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;KEY NAME=&amp;quot;certificate&amp;quot; TYPE=&amp;quot;foreign&amp;quot; FIELDS=&amp;quot;certificateid&amp;quot; REFTABLE=&amp;quot;certificate&amp;quot; REFFIELDS=&amp;quot;id&amp;quot; PREVIOUS=&amp;quot;primary&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/KEYS&amp;gt;&lt;br /&gt;
    &amp;lt;/TABLE&amp;gt;&lt;br /&gt;
  &amp;lt;/TABLES&amp;gt;&lt;br /&gt;
&amp;lt;/XMLDB&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example contains the structure of the table certificate and certificate_issues. Each table, field and key lists what element is before and after it (if there are any present). This is automatically created by the XMLDB editor. Your module should always have a table called after the module itself with the fields id, name and course.&lt;br /&gt;
&lt;br /&gt;
==== upgrade.php ====&lt;br /&gt;
&lt;br /&gt;
This file handles upgrading the module to match the latest version. After creating a module and using it extensively on your site (and others) you may want to extend the functionality of your module. Using the certificate example, a suggestion was made that a unique code could be generated for each certificate issued and displayed if a setting was selected. This requires two new database fields, one to store whether the user has chosen to display the code on the certificate and another to store the actual code. This is where the upgrade.php script becomes used. The install.xml file is only executed once, that is when your module is first installed, so adding these two extra columns to this file does not change the database structure for users who have already installed the module. So, to perform this upgrade you need to do three things.&lt;br /&gt;
&lt;br /&gt;
1. Add the new columns to the install.xml file so that any users who install the module after this point are given the new table structure.&lt;br /&gt;
2. Add the instructions for the upgrade.php files.&lt;br /&gt;
3. Update the version number in your version.php file.&lt;br /&gt;
&lt;br /&gt;
In this example we are only adding two new columns to the database, so we can use the XMLDB editor to change the install.xml file AND create the upgrade path. Please view [[XMLDB_editor]].&lt;br /&gt;
&lt;br /&gt;
An example of the upgrade.php file is as follows -&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_certificate_upgrade($oldversion=0) {&lt;br /&gt;
    if ($oldversion &amp;lt; 2012091801) {&lt;br /&gt;
        // Add new fields to certificate table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;showcode&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_INTEGER, &#039;1&#039;, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, &#039;0&#039;, &#039;savecert&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
        // Add new fields to certificate_issues table.&lt;br /&gt;
        $table = new xmldb_table(&#039;certificate_issues&#039;);&lt;br /&gt;
        $field = new xmldb_field(&#039;code&#039;);&lt;br /&gt;
        $field-&amp;gt;set_attributes(XMLDB_TYPE_CHAR, &#039;50&#039;, null, null, null, null, &#039;certificateid&#039;);&lt;br /&gt;
        if (!$dbman-&amp;gt;field_exists($table, $field)) {&lt;br /&gt;
            $dbman-&amp;gt;add_field($table, $field);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whenever you change the version in your version.php module Moodle will look to see if anything needs to be done. The version that is stored in the database is passed to the xmldb_&amp;lt;modname&amp;gt;_upgrade function as the variable $oldversion in this case. In this example lets say that the initial version was 2012091600, since this is less than 2012091800 (the new version.php numer) we will execute the code in the if statement which will then update the version stored in the database meaning this if statement is never executed again. For more extensive details on this please see [[Upgrade_API]].&lt;br /&gt;
&lt;br /&gt;
=== Lang Folder ===&lt;br /&gt;
&lt;br /&gt;
This is where you store any strings you are going to use in your plugin. Each language has a specific folder that needs to be created in order for it to be used with your module. In this case we are going to use the English language (since unfortunately it is the only one I know). A folder called en is created in your lang folder that contains a file called &amp;lt;modname&amp;gt;.php that lists the translations of your string. For example, your module may have a setting called &#039;User preferences&#039;, rather than hard coding this term in your form, you use a placeholder that will then retrieve the appropriate string depending on the language being used on your Moodle site. There is one mandatory placeholder for modules called &#039;pluginname&#039; that Moodle will use when listing this module as an option to add to a course and other various pages. To keep with Moodle standards you should order your strings alphabetically by the placeholder name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificate&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;User preferences&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to add the French translation you would create a folder called fr and add the file &amp;lt;modname&amp;gt;.php to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Certificat&#039;;&lt;br /&gt;
$string[&#039;userpreferences&#039;] = &#039;Préférences d\&#039;utilisateur&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when using the string &#039;User preferences&#039; we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
get_string(&#039;userpreferences&#039;, &#039;&amp;lt;modname&amp;gt;&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pix folder ===&lt;br /&gt;
&lt;br /&gt;
Here you simply store the icon you wish Moodle to display next to the name of your module. The name of the file should be icon.gif and is displayed with the resolution of 64 * 64. Feel free to use this folder to store other pictures you may use.&lt;br /&gt;
&lt;br /&gt;
=== lib.php ===&lt;br /&gt;
&lt;br /&gt;
The list of functions that are possible to override in the lib.php are listed here [[NEWMODULE_Documentation#lib.php]]. The essential ones are listed below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function certificate_add_instance($certificate);&lt;br /&gt;
function certificate_update_instance($certificate);&lt;br /&gt;
function certificate_delete_instance($id);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The certificate_add_instance function is passed the variables from the mod_form.php file (discussed later) as an object when you first create an activity and click submit. This is where you can take that data, do what you want with it and then insert it into the database if you wish. This is only called once when the module instance is added, so this is where you should place the logic to add the activity.&lt;br /&gt;
The certificate_update_instance function is passed the variables from the mod_form.php file as an object whenever you update an activity and click submit.&lt;br /&gt;
The certificate_delete_instance function is passed the id of your module which you can use to delete the records from any database tables associated with that id. For example, in the certificate module the ID of the certificate table is passed, and then used to delete the certificate from the database, any issues of this certificate and any files associated with it on the filesystem.&lt;br /&gt;
&lt;br /&gt;
=== mod_form.php ===&lt;br /&gt;
&lt;br /&gt;
This file is used when adding/editing a module to a course. It contains the elements that will be displayed on the form responsible for creating/installing an instance of your module.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;);    ///  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/moodleform_mod.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/mod/certificate/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class mod_certificate_mod_form extends moodleform_mod {&lt;br /&gt;
&lt;br /&gt;
    function definition() {&lt;br /&gt;
        global $CFG, $DB, $OUTPUT;&lt;br /&gt;
&lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;certificatename&#039;, &#039;certificate&#039;), array(&#039;size&#039;=&amp;gt;&#039;64&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;name&#039;, PARAM_TEXT);&lt;br /&gt;
        $mform-&amp;gt;addRule(&#039;name&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;savecert&#039;, get_string(&#039;savecert&#039;, &#039;certificate&#039;), $ynoptions);&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;savecert&#039;, 0);&lt;br /&gt;
        $mform-&amp;gt;addHelpButton(&#039;savecert&#039;, &#039;savecert&#039;, &#039;certificate&#039;);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;standard_coursemodule_elements();&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;add_action_buttons();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called &#039;name&#039; that is required, this is obviously the name of the instance. I then created another element that stores whether a user wishes to store the PDF generated by the certificate on the filesystem or not with a default value of 0 and a help button explaining what it&#039;s function is. The function standard_coursemodule_elements adds the elements common to the modules, such as the conditional fields. The add_action_buttons function adds the submit and cancel buttons to the form. This data will be passed to either certificate_add_instance or certificate_update_instance depending on whether you are adding a new instance or updating a current one. You can also add validation to this form, just like any other form in Moodle. For more information on how to create forms in Moodle see [[Form_API]].&lt;br /&gt;
&lt;br /&gt;
=== version.php ===&lt;br /&gt;
&lt;br /&gt;
The version.php file keeps track of the version of your module, and other attributes, such as what version of Moodle it requires. For a full list of the attributes please see [[version.php]].&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Conditional_user_fields&amp;diff=33888</id>
		<title>Conditional user fields</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Conditional_user_fields&amp;diff=33888"/>
		<updated>2012-05-18T10:46:13Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page explains how to restrict an activity, resource or course section via user fields and/or custom profile fields.&lt;br /&gt;
&lt;br /&gt;
==Instructions==&lt;br /&gt;
&lt;br /&gt;
1. Conditional access must be enabled. (see [[Conditional_activities]] for instructions on how to enable this for your site).&amp;lt;br /&amp;gt;&lt;br /&gt;
2. When adding or editing an activity, resource or course section scroll to the user fields in the &#039;Restrict Access&#039; section.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Choose which fields you want to restrict by (adding more if needed), select the restriction you want to put in place and then enter a value.&amp;lt;br /&amp;gt;&lt;br /&gt;
4. Save the settings.&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&lt;br /&gt;
This is an example of the interface in Moodle when adding an activity to a course with the conditional functionality enabled &lt;br /&gt;
&lt;br /&gt;
[[File:conditional_user_setup.jpg]]&lt;br /&gt;
&lt;br /&gt;
This is how it will appear to users who fail to meet the restrictions set in place.&lt;br /&gt;
&lt;br /&gt;
[[File:conditional_user_courseview.jpg]]&lt;br /&gt;
&lt;br /&gt;
==User Fields==&lt;br /&gt;
&lt;br /&gt;
You can restrict by using one of the user fields that are located in the Moodle user table. Not all the user fields are included, as not all of them would make sense in this context. The ones included are listed below.&lt;br /&gt;
&lt;br /&gt;
===AIM ID===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;aim&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Address===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;address&#039; column.&lt;br /&gt;
&lt;br /&gt;
===City/town===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;city&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Country===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;country&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Department===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;department&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Email Address===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;email&#039; column.&lt;br /&gt;
&lt;br /&gt;
===First name===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;firstname&#039; column.&lt;br /&gt;
&lt;br /&gt;
===ICQ number===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;icq&#039; column.&lt;br /&gt;
&lt;br /&gt;
===ID number===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;idnumber&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Institution===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;institution&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Interests===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;interests&#039; column.&lt;br /&gt;
&lt;br /&gt;
===MSN ID===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;msn&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Mobile phone===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;phone2&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Phone===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;phone1&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Skype ID===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;skype&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Surname===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;lastname&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Web page===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;url&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Yahoo ID===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;yahoo&#039; column.&lt;br /&gt;
&lt;br /&gt;
==Custom Profile Fields==&lt;br /&gt;
&lt;br /&gt;
These are all the custom profile fields that have been created on the Moodle site. See [[User_profile_fields]]&lt;br /&gt;
&lt;br /&gt;
==Operators==&lt;br /&gt;
&lt;br /&gt;
The operators define the relationship between the field chosen and the value entered. For example, when the user&#039;s email must contain @school.com, the field chosen is &#039;Email address&#039;, the operater is &#039;contains&#039; and the value is &#039;@school.com&#039;.&lt;br /&gt;
&lt;br /&gt;
===Contains===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to those whos chosen field contains the value provided.&lt;br /&gt;
&lt;br /&gt;
===Does not contain===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to those whos chosen field does not contain the value provided.&lt;br /&gt;
&lt;br /&gt;
===Is Equal To===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to those whos chosen field equals the value provided.&lt;br /&gt;
&lt;br /&gt;
===Starts With===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to the activity to those whos chosen field starts with the value provided.&lt;br /&gt;
&lt;br /&gt;
===Ends With===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to the activity to those whos chosen field ends with the value provided.&lt;br /&gt;
&lt;br /&gt;
===Is Empty===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to the activity to those whos chosen field is empty. Note, if any value is provided in this case, it is ignored.&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Conditional_user_fields&amp;diff=33886</id>
		<title>Conditional user fields</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Conditional_user_fields&amp;diff=33886"/>
		<updated>2012-05-18T10:45:19Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Help}}&lt;br /&gt;
This page explains how to set up an activity, resource or course section and restrict it by user fields and/or custom profile fields.&lt;br /&gt;
&lt;br /&gt;
==Instructions==&lt;br /&gt;
&lt;br /&gt;
1. Conditional access must be enabled. (see [[Conditional_activities]] for instructions on how to enable this for your site).&amp;lt;br /&amp;gt;&lt;br /&gt;
2. When adding or editing an activity, resource or course section scroll to the user fields in the &#039;Restrict Access&#039; section.&amp;lt;br /&amp;gt;&lt;br /&gt;
3. Choose which fields you want to restrict by (adding more if needed), select the restriction you want to put in place and then enter a value.&amp;lt;br /&amp;gt;&lt;br /&gt;
4. Save the settings.&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&lt;br /&gt;
This is an example of the interface in Moodle when adding an activity to a course with the conditional functionality enabled &lt;br /&gt;
&lt;br /&gt;
[[File:conditional_user_setup.jpg]]&lt;br /&gt;
&lt;br /&gt;
This is how it will appear to users who fail to meet the restrictions set in place.&lt;br /&gt;
&lt;br /&gt;
[[File:conditional_user_courseview.jpg]]&lt;br /&gt;
&lt;br /&gt;
==User Fields==&lt;br /&gt;
&lt;br /&gt;
You can restrict by using one of the user fields that are located in the Moodle user table. Not all the user fields are included, as not all of them would make sense in this context. The ones included are listed below.&lt;br /&gt;
&lt;br /&gt;
===AIM ID===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;aim&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Address===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;address&#039; column.&lt;br /&gt;
&lt;br /&gt;
===City/town===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;city&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Country===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;country&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Department===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;department&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Email Address===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;email&#039; column.&lt;br /&gt;
&lt;br /&gt;
===First name===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;firstname&#039; column.&lt;br /&gt;
&lt;br /&gt;
===ICQ number===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;icq&#039; column.&lt;br /&gt;
&lt;br /&gt;
===ID number===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;idnumber&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Institution===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;institution&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Interests===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;interests&#039; column.&lt;br /&gt;
&lt;br /&gt;
===MSN ID===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;msn&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Mobile phone===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;phone2&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Phone===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;phone1&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Skype ID===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;skype&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Surname===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;lastname&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Web page===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;url&#039; column.&lt;br /&gt;
&lt;br /&gt;
===Yahoo ID===&lt;br /&gt;
&lt;br /&gt;
This is the value in the &#039;yahoo&#039; column.&lt;br /&gt;
&lt;br /&gt;
==Custom Profile Fields==&lt;br /&gt;
&lt;br /&gt;
These are all the custom profile fields that have been created on the Moodle site. See [[User_profile_fields]]&lt;br /&gt;
&lt;br /&gt;
==Operators==&lt;br /&gt;
&lt;br /&gt;
The operators define the relationship between the field chosen and the value entered. For example, when the user&#039;s email must contain @school.com, the field chosen is &#039;Email address&#039;, the operater is &#039;contains&#039; and the value is &#039;@school.com&#039;.&lt;br /&gt;
&lt;br /&gt;
===Contains===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to those whos chosen field contains the value provided.&lt;br /&gt;
&lt;br /&gt;
===Does not contain===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to those whos chosen field does not contain the value provided.&lt;br /&gt;
&lt;br /&gt;
===Is Equal To===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to those whos chosen field equals the value provided.&lt;br /&gt;
&lt;br /&gt;
===Starts With===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to the activity to those whos chosen field starts with the value provided.&lt;br /&gt;
&lt;br /&gt;
===Ends With===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to the activity to those whos chosen field ends with the value provided.&lt;br /&gt;
&lt;br /&gt;
===Is Empty===&lt;br /&gt;
&lt;br /&gt;
This operator restricts access to the activity to those whos chosen field is empty. Note, if any value is provided in this case, it is ignored.&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:conditional_user_courseview.jpg&amp;diff=33884</id>
		<title>File:conditional user courseview.jpg</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:conditional_user_courseview.jpg&amp;diff=33884"/>
		<updated>2012-05-18T10:44:05Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:conditional_user_setup.jpg&amp;diff=33883</id>
		<title>File:conditional user setup.jpg</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:conditional_user_setup.jpg&amp;diff=33883"/>
		<updated>2012-05-18T10:43:44Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User_talk:Jerome_mouneyrac&amp;diff=24148</id>
		<title>User talk:Jerome mouneyrac</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User_talk:Jerome_mouneyrac&amp;diff=24148"/>
		<updated>2010-02-10T04:00:07Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Soccer==&lt;br /&gt;
&lt;br /&gt;
==6 Jan          7:35==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Sam-agol&lt;br /&gt;
* St Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
* Mark&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Not playing: Martin, Rolf Harris, Dongsheng&lt;br /&gt;
&lt;br /&gt;
Result: Orange 0 - 4 Black&amp;lt;br/&amp;gt;&lt;br /&gt;
Players: Sam, Jerome, Jordan, Shane, Damon, Andrew, Mark&amp;lt;br/&amp;gt;&lt;br /&gt;
Goals: sam hurted the post but Mark hurted it even more&lt;br /&gt;
&lt;br /&gt;
==13 Jan        Bye==&lt;br /&gt;
&lt;br /&gt;
==20 Jan        7:35==&lt;br /&gt;
&lt;br /&gt;
* Sam-apost&lt;br /&gt;
* St Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Not playing: Martin, Andrew&lt;br /&gt;
&lt;br /&gt;
==27 Jan        6:00==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: &lt;br /&gt;
&lt;br /&gt;
==3 Feb          6:00==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: Sam, Damon&lt;br /&gt;
&lt;br /&gt;
==10 Feb        10:15==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
* Damon&lt;br /&gt;
* Markus Arrelius&lt;br /&gt;
&lt;br /&gt;
Not playing:&lt;br /&gt;
&lt;br /&gt;
==17 Feb         6:30==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
* Damon&lt;br /&gt;
&lt;br /&gt;
Not playing:&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User_talk:Jerome_mouneyrac&amp;diff=24143</id>
		<title>User talk:Jerome mouneyrac</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User_talk:Jerome_mouneyrac&amp;diff=24143"/>
		<updated>2010-01-18T04:43:02Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* 13 Jan        Bye */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Soccer==&lt;br /&gt;
&lt;br /&gt;
==6 Jan          7:35==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Sam-agol&lt;br /&gt;
* St Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
* Mark&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Not playing: Martin, Rolf Harris, Dongsheng&lt;br /&gt;
&lt;br /&gt;
Result: Orange 0 - 4 Black&amp;lt;br/&amp;gt;&lt;br /&gt;
Players: Sam, Jerome, Jordan, Shane, Damon, Andrew, Mark&amp;lt;br/&amp;gt;&lt;br /&gt;
Goals: sam hurted the post but Mark hurted it even more&lt;br /&gt;
&lt;br /&gt;
==13 Jan        Bye==&lt;br /&gt;
&lt;br /&gt;
==20 Jan        7:35==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Sam-apost&lt;br /&gt;
* St Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Not playing: Martin&lt;br /&gt;
&lt;br /&gt;
==27 Jan        6:00==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==3 Feb          6:00==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: Sam&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==10 Feb        10:15==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==17 Feb         6:30==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing:&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User_talk:Jerome_mouneyrac&amp;diff=24142</id>
		<title>User talk:Jerome mouneyrac</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User_talk:Jerome_mouneyrac&amp;diff=24142"/>
		<updated>2010-01-18T04:42:39Z</updated>

		<summary type="html">&lt;p&gt;Markn86: /* 13 Jan        Bye */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Soccer==&lt;br /&gt;
&lt;br /&gt;
==6 Jan          7:35==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Sam-agol&lt;br /&gt;
* St Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
* Mark&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Not playing: Martin, Rolf Harris, Dongsheng&lt;br /&gt;
&lt;br /&gt;
Result: Orange 0 - 4 Black&amp;lt;br/&amp;gt;&lt;br /&gt;
Players: Sam, Jerome, Jordan, Shane, Damon, Andrew, Mark&amp;lt;br/&amp;gt;&lt;br /&gt;
Goals: sam hurted the post but Mark hurted it even more&lt;br /&gt;
&lt;br /&gt;
==13 Jan        Bye==&lt;br /&gt;
&lt;br /&gt;
:(&lt;br /&gt;
&lt;br /&gt;
==20 Jan        7:35==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Sam-apost&lt;br /&gt;
* St Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Not playing: Martin&lt;br /&gt;
&lt;br /&gt;
==27 Jan        6:00==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==3 Feb          6:00==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: Sam&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==10 Feb        10:15==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==17 Feb         6:30==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing:&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User_talk:Jerome_mouneyrac&amp;diff=24141</id>
		<title>User talk:Jerome mouneyrac</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User_talk:Jerome_mouneyrac&amp;diff=24141"/>
		<updated>2010-01-18T04:42:01Z</updated>

		<summary type="html">&lt;p&gt;Markn86: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Soccer==&lt;br /&gt;
&lt;br /&gt;
==6 Jan          7:35==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Sam-agol&lt;br /&gt;
* St Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
* Mark&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Not playing: Martin, Rolf Harris, Dongsheng&lt;br /&gt;
&lt;br /&gt;
Result: Orange 0 - 4 Black&amp;lt;br/&amp;gt;&lt;br /&gt;
Players: Sam, Jerome, Jordan, Shane, Damon, Andrew, Mark&amp;lt;br/&amp;gt;&lt;br /&gt;
Goals: sam hurted the post but Mark hurted it even more&lt;br /&gt;
&lt;br /&gt;
==13 Jan        Bye==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==20 Jan        7:35==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Sam-apost&lt;br /&gt;
* St Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Not playing: Martin&lt;br /&gt;
&lt;br /&gt;
==27 Jan        6:00==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==3 Feb          6:00==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: Sam&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==10 Feb        10:15==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==17 Feb         6:30==&lt;br /&gt;
&lt;br /&gt;
* Andrew&lt;br /&gt;
* Martin&lt;br /&gt;
* Sam&lt;br /&gt;
* Jerome&lt;br /&gt;
* The Shananator&lt;br /&gt;
&lt;br /&gt;
Not playing:&lt;/div&gt;</summary>
		<author><name>Markn86</name></author>
	</entry>
</feed>