Development:NEWMODULE Documentation: Difference between revisions

From MoodleDocs
Line 151: Line 151:
:You can read:
:You can read:
<pre>//------------------------------------------------------------------------------
<pre>//------------------------------------------------------------------------------
// add standard elements, common to all modules
        // add standard elements, common to all modules
         $this->standard_coursemodule_elements();
         $this->standard_coursemodule_elements();
//------------------------------------------------------------------------------</pre>
//------------------------------------------------------------------------------</pre>

Revision as of 12:03, 10 September 2009

Note: This page is a work-in-progress. Feedback and suggested improvements are welcome. Please join the discussion on moodle.org or use the page comments.


Template:New Module

This first draft of Moodle Docs page about the creation of a new module is divided into the following sections:


Daniele, did you know about Development:Modules, which is linked to from Developer_documentation#Make_a_new_plugin? You may be better off editing that, rather than starting a new page. However don't let me discourage you. That documentation is very limited, and badly needs to be expanded, so it is absolutely brilliant that you want to work on it.--Tim Hunt 12:03, 28 March 2008 (CDT)

Good point Tim! Anyway... I think we can use this as temporary root for Daniele's work and then, simply, move things to their final place. Let's see how this evolves. -- Eloy Lafuente (stronk7) 12:33, 28 March 2008 (CDT)
Dear Tim, Sam and Eloy, I wrote what was my learning path in these things. I wrote whatever I found in your powerpoint guide (thanks again, Sam) and whatever I got mainly from Tim, Eloy and Petr. A lot of issue are still obscure to me like, grades, groups, groupings, backup and so forth. Please let me know your opinion to make all together a plan to carry on in the best way. Thanks. -- Daniele Cordella 11:55, 10 September 2009 (UTC)

My powerpoint about creating moodle modules is a bit old (1.8) and maybe not that comprehensible but I use it when I'm trying to explain things to people. It includes a list of all the things you need to have in a module, except the ones I forgot (backuplib iirc is missing). Sam marshall 12:52, 28 March 2008 (CDT)

That's really great, Sam. For sure that presentation will help.Thanks! -- Eloy Lafuente (stronk7) 13:08, 28 March 2008 (CDT)

Getting started

To download the newmodule package, please refer to:

   * 1.8: http://download.moodle.org/plugins18/mod/NEWMODULE.zip
   * 1.9: http://download.moodle.org/plugins19/mod/NEWMODULE.zip
   * HEAD: http://download.moodle.org/plugins/mod/NEWMODULE.zip

Although you can download the newmodule package for moodle 1.8, such as 1.9 and head, this tutorial is intended for the newmodule development in Moodle 1.9 ONLY.

Let's start by getting an idea about what you find in the newmodule folder taken from http://download.moodle.org/plugins19/mod/NEWMODULE.zip

NEWMODULE:
01)    db/install.xml
02)    db/upgrade.php
03)    icon.gif
04)    index.php
05)    lang/en_utf8/help/newmodule/index.html
06)    lang/en_utf8/help/newmodule/mods.html
07)    lang/en_utf8/newmodule.php
08)    lib.php
09)    mod_form.php
10)    README.txt
11)    version.php
12)    view.php

The path where you find each file is the correct one. So don't change the path of files and folders in this module package. Inside the db folder, at the beginning, you can only find install.xml and upgrade.php but sooner you will start to always add the new file "access.php"


01) db/install.xml is the file to write the xml describing the tables needed by the module. Tables are at least two, one named with the same name of the module, one named "log_display". They follow a strict syntax that you can learn by editing one of the several example you can find inside moodle modules. Ultimately the only thing to take care is the <<previous>> <<next>> connection between tables and fields. This is the mandatory file where you MUST write the structure of the tables your module is going to use. Tha table "log_display" is the tables where you are requested to list all the "actions" that you will add to the logs of your module.

02) db/upgrade.php is the file that you will write each time you need to change the structure of the tables of your module. To learn how to write this file, please refer to the examples you may find in the file itself.

03) icon.gif, it is a 10px per 10px icon identifying each instance of your module in the frame of a course

04) index.php is...

05) lang is the folder reserved to language packs. A module language pack is a folder named "xx_utf8" containing, in turn, a folder named "help" and a language file named with the same name of the module. xx is the two char long name of the language, i.e. en, de, es, it, fr and so forth.

Each language file is dedicated to a specific language. The lang folder may contain as much language packs as provided by different translators. The lang/xx_utf8/newmodule/ folder contains all the help files you want to provide to your module. In order to link a help file from inside the code of your module pages try:
  • helpbutton('<<name of your help file saved in lang/xx_utf8/newmodule/>>', get_string('your_string','newmodule'), 'newmodule');
or, in mod_form.php,
  • $mform->setHelpButton as stated in

08) lib.php is the pre-filled file with "core" functions needed by each module. Let me start by remembering the convention to name functions into lib.php and locallib.php.

See: https://docs.moodle.org/en/Development:Coding_style#Functions_and_Methods
or
https://docs.moodle.org/en/Development:Modules
Mandatory function are, at least:
  • function newmodule_add_instance($newmodule)
This function is executed after an editing teacher create an instance of newmodule
See, lib.php for more details just above the function.
  • function newmodule_update_instance($newmodule)
This function is executed after an editing teacher update an instance of newmodule
See, lib.php for more details just above the function.
  • function newmodule_delete_instance($id)
This function is executed after an editing teacher delete an instance of newmodule
See, lib.php for more details just above the function.
  • function newmodule_user_outline()
See, lib.php for more details just above the function.
  • function newmodule_user_complete($course, $user, $mod, $newmodule)
See, lib.php for more details just above the function.
  • function newmodule_print_recent_activity($course, $isteacher, $timestart)
See, lib.php for more details just above the function.
  • function newmodule_cron()
Take care with this function.
Differently by all the other functions, this function is not called by passing it the $newmodule record. This means that this function, called by moodle core cron has to look for each newmodule instance id before operating.
Don't worry, even if you have more than a single instance of your module among moodle courses, this function will be executed just one time.
  • function newmodule_get_participants($newmoduleid)
See, lib.php for more details just above the function.
  • function newmodule_scale_used($newmoduleid, $scaleid)
See, lib.php for more details just above the function.
  • function newmodule_scale_used_anywhere($scaleid)
See, lib.php for more details just above the function.
  • function newmodule_install()
See, lib.php for more details just above the function.
  • function newmodule_uninstall()
See, lib.php for more details just above the function.
In my honest opinion some more functions should be added. Among these I want to list:
  • function newmodule_reset_course_form_definition(&$mform)
  • function newmodule_reset_course_form_defaults($course)
  • function newmodule_reset_userdata($data)
These last three functions are responsible for the mewmodule reset process during the more general course reset process. Please, refer to mod/data/lib.php or to mod/feedback/lib.php, for instance, to understand them better.
Two more functions should be added to lib.php are, in my opinion:
  • function webdim_get_view_actions()
  • function webdim_get_post_actions()
They distinguish between read and post log actions.
These functions are used by moodle core during log gather.
The action you list inside these two functions, must match the ones you listed in the table "log_display" in install.xml

Still about the lib.php file, it is important to read what is stated at the end of lib.php:

//////////////////////////////////////////////////////////////////////////////////////
/// Any other newmodule functions go here.  Each of them must have a name that
/// starts with newmodule_
/// Remember (see note in first lines) that, if this section grows, it's HIGHLY
/// recommended to move all functions below to a new "locallib.php" file.
One important issue is about the connection between lib.php and locallib.php
Who has to call the other and why?
It has to be locallib.php to call lib.php through
require_once("$CFG->dirroot/mod/newmodule/lib.php");
as first line.
In this way, if moodle core calls function inside mod/newmodule/lib.php no module specific function will be loaded in memory.
If it is your newmodule to call a function, it has to require_once('locallib.php'); that, in turn, will require_once('lib.php') o that your module will "see" all its available functions.

09) mod_form.php is the file describing the form you get at the module instance creation or at the instance editing time. The syntax is very simple and by reading the file it is simple to change it on your need.

It uses the syntax you can learn in:
https://docs.moodle.org/en/Development:lib/formslib.php_Form_Definition
At date, there is a missing detail by the end of the file.
You can read:
//------------------------------------------------------------------------------
        // add standard elements, common to all modules
        $this->standard_coursemodule_elements();
//------------------------------------------------------------------------------
This part is responsible for the common modules section at the end of your newmodule editing instance page. (the section related to groups)
This code can be customized by changing it as described below:
//------------------------------------------------------------------------------
        // add standard elements, common to all modules
        $features = new object();
        $features->groups           = false;
        $features->groupings        = false;
        $features->groupmembersonly = true;
        $this->standard_coursemodule_elements($features);
//------------------------------------------------------------------------------

One more tip about this file.

Once you submit the form described by this file, your module executes the function: newmodule_add_instance or newmodule_update_instance already pre-written in lib.php.
It seems that by adding a check box to editing instance form doesn't work. To test this, please verify the passed parameter $newmodule inside your function newmodule_update_instance through a simple
print_object($newmodule);
You will find that even by selecting or unselecting the check box in the newmodule instance editing form, the corresponding value in the array doesn't change. This is not an error, but at least a lack of code.
By adding a simple code like:
$checkboxes = array('myfirstcheckboxfield', 'mysecondcheckboxfield', and so fort with all your checkbox field);
foreach ($checkboxes as $checkbox) {
    if (empty($newmodule->{$checkbox})) {
        $newmodule->{$checkbox} = 0;
    }
}
at the beginning of both functions, you will find that all works fine.

10) README.txt is the file where you are welcome to write what your newmodule does.

11) version.php is a really very simple file as simple as important. To understand why it is important, you need to know that there are a bunch of actions that moodle performs for your newmodule ONLY (with only one exception) at the newmodule installation. They are, at least, db tables editing and load of capability. If during the development of your module (that you already installed on your development environment or that you already shared with remote users) you need to change the structure of your newmodule tables or you need to change the capability used by your newmodule, you need to force moodle to edit tables and reload capability. This is done by:

  • adding the proper code in newmodule/db/upgrade.php (to do this, use XMLDB as stated in this same page below)
  • increasing the newmodule version.
  • visiting the notification page of your installation of Moodle.

12) view.php is the first executed code of your module. By selecting the link of the instance of your module, the code of newmodule/view.php is executed.

Some very important missing files

There are five files that are not present in the newmodule package that 90% of times you will go to add to your newmodule.

1. The first one is locallib already described before.

2. The second one is access.php that has to be saved inside newmodule/db/ folder.

In this file you will add all the capability used by your newmodule and loaded at the installation time or upgrade time. To learn the syntax of the capability, please refer to the same file in other modules or to: https://docs.moodle.org/en/Development:NEWMODULE_Adding_capabilities

3. The third missing file must be added to newmodule/ folder. It is settings.php and describes the form that can be accessed from: Site Administration block -> Modules -> Activities -> <<your newmodule name>>

This form stores general settings for your newmodule into the site wide $CFG object. Because of this, it is strongly recommended to give to your newmodule general settings with names starting with "newmodule_". This file is useful when there is a setting that doesn't depend from the instance. I.e., if your newmodule simulates a telephone, you will probably save your telephone number in this newmodule setting site wide form instead of typing it each time you add a new instance of your newmodule into a course. In this case, to refer to you telephone number inside your newmodule you will use: $CFG->newmodule_telephonenumber

4. Directly in the newmodule folder, you need to add backuplib.php that is responsible for the backup of each instance of your module and of its log.

To learn how to code it, start by stealing it from some other module and read it.

5. Again in the newmodule folder, you need to add restorelib.php that is responsible for the restore of each instance your module and of its log.

To learn how to code it, start by stealing it from some other module and read it.

Let's start

To start using a downloaded package, please perform the 7 actions described in https://docs.moodle.org/en/Development:NEWMODULE_Tutorial in How to Begin the Creation of a New Module paragraph.

Then, draw the structure of your tables on a sheet, edit the file db/install.xml according to your project, save, put your renamed newmodule folder in moodle/mod/ and visit the moodle notification page.

To add code to db/upgrade.php never do it manually. I always make use of Site Administration block -> Miscellaneous -> XMLDB editor and I ask it to write the code for me. It never fails.

Please remember: within your module, never use "embedded messages" like:

echo 'Welcome to this newmodule';

but make use of get_string or print_string. In this way your module will be multilang with a really small effort. Use, for instance:

print_string('welcomemessage','newmodule');

saving in newmodule/lang/en_utf8/newmodule.php

$string['welcomemessage'] = 'Welcome to this newmodule';

Some code snippets that I find useful

**To check the capability of a user, try:

if (newmodule_hascapabilitytodothis()) {
    //user is allowed
} else {
    // user is not allowed
}

typing in locallib.php

function newmodule_hascapabilitytodothis($cm) {
    $context = get_context_instance(CONTEXT_MODULE, $cm->id);

    return (has_capability('mod/newmodule:condothis', $context));
}

typing in db/access.php

$mod_newmodule_capabilities = array(
    'mod/newmodule:condothis' => array(
        'captype' => 'read',
        'contextlevel' => CONTEXT_MODULE,
        'legacy' => array(
            'teacher' => CAP_ALLOW,
            'editingteacher' => CAP_ALLOW,
            'admin' => CAP_ALLOW
        )
    )
)


To edit the tables in use by your newmodule, try:

  • edit install.xml manually by editing fields and or tables in the xml structure.
  • go to Site Administration block -> Miscellaneous -> XMLDB editor and load the tables of your module
  • ask to the XMLDB editor the snippets of code you need to add to db/upgrade.php
  • copy and paste in db/upgrade.php
  • in the line: if ($result && $oldversion < xxxxxxxxxxxx) {, replace xxxxxxxxxxxx with the version number you are going to give to your newmodule
  • change (increase) the version number
  • visit the Moodle notification page


To add a single line to logs from your mewmodule, try:

add_to_log($course->id, 'newmodule', '<<action already listed in log_display>>', "view.php?id=$cm->id", "$newmodule->id");


To be sure that remote user will not be able to contact your pages by typing their URL directly in the address bar]], try: as first line of each of your php script

defined('NEWMODULE_INCLUDE_TEST') OR die('not allowed');

typing in lib.php, at the beginning

define('NEWMODULE_INCLUDE_TEST', 1);

Some suggestion I find useful

To include php scripts, try:

require_once(myscript.php);


To include php library, try:

require_once('locallib.php');


To periodically execute function newmodule_cron(), try:

$module->cron = xxxx;

providing some code in:

function newmodule_cron()

Your function newmodule_cron() will be executed about each xxxx seconds


Do not include config when it is not needed

require_once('config.php')

is not needed in library scripts


Do not use global $cm or $newmodule in your function but use proper function parameters.

So, never use:

function newmodule_lookatthesky() {
    global $cm, $newmodule;
    
    // your stuff
}

but use:

function newmodule_lookatthesky($cm, $newmodule) {
    
    // your stuff
}

See also

Template:CategoryDeveloper