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

Activity modules

From MoodleDocs
(Redirected from Modules)

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

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


Activity modules reside in the /mod directory.

Each module is in a separate subdirectory and consists of a number of 'mandatory files' and any other files the developer is going to use. The below image is an example of the certificate module's filestructure. Please note, any reference to <modname> in this documentation should be replaced by the name of your module.

Below is an example of the file structure for the certificate plugin.

Activities file structure example.jpg

Standard Files and their Functions

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.

Backup Folder

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.

To read more on this please visit Backup_2.0_for_developers and Restore_2.0_for_developers.

DB Folder


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.

An example of the file is below -

$capabilities = array(

    'mod/certificate:addinstance' => array(
        'riskbitmask' => RISK_XSS,
        'captype' => 'write',
        'contextlevel' => CONTEXT_COURSE,
        'archetypes' => array(
            'editingteacher' => CAP_ALLOW,
            'manager' => CAP_ALLOW
        'clonepermissionsfrom' => 'moodle/course:manageactivities'

In Moodle 2.3 a new capability called 'addinstance' was added for all core modules. Moodle will look for this capability by searching for 'mod/<modname>:addinstance' 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.

We also recommend that every activity module also provides a 'mod/<modname>:view' capability to control visibility. (See MDL-40854)

For consistency and ease of use for the teachers it is advisable to use the following archetypes with the



'mod/MODULENAME:view' => array(
    'captype' => 'read',
    'contextlevel' => CONTEXT_MODULE,
    'archetypes' => array(
        'guest' => CAP_ALLOW,
        'student' => CAP_ALLOW,
        'teacher' => CAP_ALLOW,
        'editingteacher' => CAP_ALLOW,
        'manager' => CAP_ALLOW

For further information on what each attribute in that capabilities array means visit NEWMODULE_Adding_capabilities.


Setup observer(s) for monitoring events

Once we got the observer in place, now we need to tell Moodle about it. We do this by adding an entry in the plugin events.php

Example - mod/quiz/db/events.php

$observers = [
        'eventname' => '\mod_quiz\event\attempt_submitted',
        'includefile' => '/mod/quiz/locallib.php',
        'callback' => 'quiz_attempt_submitted_handler',
        'internal' => false,

See Events API page for details.


This file is used on installation of your module; it defines the associated database tables. For each module, the database must have a main table with the same name as the module itself. In addition, other database tables may be defined. In order to create the 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.

An example of the file generated by the XMLDB_editor is below - it contains the structure of the table certificate and certificate_issues:

<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/certificate/db" VERSION="20120925" COMMENT="XMLDB file for Moodle mod/certificate"
    <TABLE NAME="certificate" COMMENT="Defines certificates">
        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true"/>
        <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" />
        <FIELD NAME="intro" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" />
        <FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="emailteachers" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="emailothers" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" />
        <FIELD NAME="savecert" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="reportcert" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="delivery" TYPE="int" LENGTH="3" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="requiredtime" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="type" TYPE="char" LENGTH="50" NOTNULL="true" SEQUENCE="false" />
        <FIELD NAME="orientation" TYPE="char" LENGTH="10" NOTNULL="true" SEQUENCE="false" />
        <FIELD NAME="width" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" />
        <FIELD NAME="height" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" />
        <FIELD NAME="backgroundimage" TYPE="char" LENGTH="255" NOTNULL="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for certificate"/>
    <TABLE NAME="certificate_issues" COMMENT="Info about issued certificates">
        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" />
        <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="certificateid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" />
        <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for certificate_issues" />
        <KEY NAME="certificate" TYPE="foreign" FIELDS="certificateid" REFTABLE="certificate" REFFIELDS="id" />

There are some fields that the Moodle core expects to be present in every activity module's main table (or just became de-facto standard):

Field name Properties Notes
id INT(10), auto sequence primary key for the table (as any other table in Moodle)
course INT(10), foreign key to the course table id of the course this activity is part of
name CHAR(255) holds the name of the activity module instance
timemodified INT(10) timestamp of when the instance was last modified
intro TEXT standard field to hold the activity's description (see FEATURE_MOD_INTRO)
introformat INT(4) the format of the text in the intro field


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.

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.
2. Add the instructions for the upgrade.php files.
3. Update the version number in your version.php file.

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.

An example of the upgrade.php file is as follows -

function xmldb_certificate_upgrade($oldversion=0) {
    if ($oldversion < 2012091800) {
        // Add new fields to certificate table.
        $table = new xmldb_table('certificate');
        $field = new xmldb_field('showcode');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'savecert');
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        // Add new fields to certificate_issues table.
        $table = new xmldb_table('certificate_issues');
        $field = new xmldb_field('code');
        $field->set_attributes(XMLDB_TYPE_CHAR, '50', null, null, null, null, 'certificateid');
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);

        // Certificate savepoint reached.
        upgrade_mod_savepoint(true, 2012091800, 'certificate');

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_<modname>_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.


New in Moodle 3.1

This is where you define the Moodle Mobile Remote addons included in the plugin.

The Moodle Mobile remote add-on is the mobile app version of the plugin that will be loaded when a user accesses the plugin on the app.

You can include several Mobile add-ons. For each add-on you must indicate a unique name (it must be unique so we recommend not to use generic names, the best way would be to use the component name of the Moodle plugin the add-on will support).

Names cannot include blank spaces, and we recommend not to use capitals.

Each addon referenced here must be included as a zip file containing the javascript/html/css code in the plugin mobile/ folder. The name of the zip must be the same as the addon name.

For the following example the file name path would be: mobile/

$addons = array(
    "mod_certificate" => array(
       "dependencies" => array("pdfbuilder")

The dependencies field is optional, if you have several add-ons in the same file (or in different plugins) you can indicate here the dependencies.

For further information on developing Mobile add-ons visit Moodle Mobile Remote addons.

Lang Folder

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 <modname>.php that lists the translations of your string. For example, your module may have a setting called 'User preferences', 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 'pluginname' 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.

$string['pluginname'] = 'Certificate';
$string['userpreferences'] = 'User preferences';

If you wanted to add the French translation you would create a folder called fr and add the file <modname>.php to it.

$string['pluginname'] = 'Certificat';
$string['userpreferences'] = 'Préférences d\'utilisateur';

Now, when using the string 'User preferences' we will use the Moodle function get_string instead, which will get the appropriate string depending on the language being used.

get_string('userpreferences', 'certificate');

Pix folder

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.

Update: Since 2.4 SVG files were introduced with all core Moodle activities. Please see Moodle_icons_2.4 for more details on this.


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

function certificate_add_instance($certificate);
function certificate_update_instance($certificate);
function certificate_delete_instance($id);

The <modname>_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.

The <modname>_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.

The <modname>_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. When a Moodle course has the recycle bin enabled, your activity will be queued for deletion and deleted when a scheduled cron task runs. For the delete_instance function to run immediately upon activity deletion, disable the course recycle bin.


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_<modname>_mod_form.

if (!defined('MOODLE_INTERNAL')) {
    die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page


class mod_certificate_mod_form extends moodleform_mod {

    function definition() {
        global $CFG, $DB, $OUTPUT;

        $mform =& $this->_form;

        $mform->addElement('text', 'name', get_string('certificatename', 'certificate'), array('size'=>'64'));
        $mform->setType('name', PARAM_TEXT);
        $mform->addRule('name', null, 'required', null, 'client');

        $ynoptions = array(0 => get_string('no'),
                           1 => get_string('yes'));
        $mform->addElement('select', 'usecode', get_string('usecode', 'certificate'), $ynoptions);
        $mform->setDefault('usecode', 0);
        $mform->addHelpButton('usecode', 'usecode', 'certificate');



The above example does not contain the full file, just enough to provide you with an idea. First we create a text element called 'name' 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 <modname>_add_instance or <modname>_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.


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 -


$id = required_param('id', PARAM_INT);           // Course ID

// Ensure that the course specified is valid
if (!$course = $DB->get_record('course', array('id'=> $id))) {
    print_error('Course ID is incorrect');

You are then free to display the list of instances as you wish.


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 <wwwrootofyoursite>/mod/<modname>/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 -


$id = required_param('id', PARAM_INT);    // Course Module ID

if (!$cm = get_coursemodule_from_id('certificate', $id)) {
    print_error('Course Module ID was incorrect'); // NOTE this is invalid use of print_error, must be a lang string id
if (!$course = $DB->get_record('course', array('id'=> $cm->course))) {
    print_error('course is misconfigured');  // NOTE As above
if (!$certificate = $DB->get_record('certificate', array('id'=> $cm->instance))) {
    print_error('course module is incorrect'); // NOTE As above

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.

If you are using Moodle 2.8 and above, there is a better way to achieve most of this using a new function:


$id = required_param('id', PARAM_INT);
list ($course, $cm) = get_course_and_cm_from_cmid($id, 'certificate');
$certificate = $DB->get_record('certificate', array('id'=> $cm->instance), '*', MUST_EXIST);


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.

See also