Note:

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

Available update notifications

From MoodleDocs
Available update notifications
Project state Completed - code integrated into Moodle 2.3
Tracker issue MDL-20438
Discussion Talk page
Assignee David Mudrak, Eloy Lafuente

Moodle 2.3


Goals and milestones

Keeping a Moodle site up-to-date is the primary way of keeping it secure. We should encourage admins to update their sites to the most recent stable version on a regular basis. As a first step, for Moodle 2.3, we will implement a notification infrastructure to:

  • notify admins about Moodle core updates available for their site; and
  • notify admins about available updates for the contributed plugins installed on their site.

Notifications will be displayed at the Admin notifications page and Plugins overview page. In their messaging preferences, admins will be able to set up notifications to be sent by email, Jabber, etc. (using standard messaging features).

Scrolls of Wisdom

Prior to displaying these notifications (and eventually sending them in email/message via the inbuilt messaging system) we need to fetch the relevant information from some authoritative source. There are two places with the required "knowledge".

download.moodle.org
The Download site is the place where standard Moodle packages are announced and published. This is the place where Moodle HQ officially declare what is the most recent version of Moodle core available (for each supported branch).
moodle.org/plugins
The Plugins directory is the place where contributed plugins are registered. Although contributed extensions can be published and announced anywhere, Moodle HQ provide notification support for plugins registered at the Plugins directory only.  : This is definitely the new Plugins repository at .

Even though there are these two authoritative sources, Moodle sites access a single URL when fetching the information about available updates. See the communication protocol described below for details.

From now on, "the client" in the text represents the local Moodle site where the information about available update should be displayed. "The remote site" represents a site maintained by Moodle HQ where the information about available update is defined. Clients read from the remote site and display eventual notifications to their admins.

One Click to Rule Then All

From the user's perspective, obtaining the information about available updates (and actually obtaining those updates themselves in the future) should be as simple as clicking a button, or simpler (that is the check is done automatically by cron every now and then). But it should be clearly documented what's going on behind the scene and what information about the client is sent to the remote site during the request.

The privacy aspect of this project was discussed. There was a proposal to gather overview stats about the client during the request. But there was also an objection that this feature should be specific for hub subscription exclusively with an easy and single place to opt-out. At the end it was decided that:

  • The client must provide just basic information about itself - the installed Moodle version and the branch.
  • If the client wants to receive the information about available updates for additional (non-standard, contributed) plugins, it must provide their list together with their current versions.
  • The remote site uses submitted data to return just the relevant update information. If the client declares it is a Moodle 2.3 site with the mod_foo and mod_bar extensions installed, the remote site returns the information about the most recent version at MOODLE_23_STABLE, MOODLE_24_STABLE and any other higher branch, including master. The information about the most recent versions of mod_foo and mod_bar for the current MOODLE_23_STABLE branch (if there are such versions) is returned, too.
  • As a part of each response, the remote site returns a special hash-like value called "ticket". The client should use the ticket during the next request. This mechanism helps Moodle HQ to match all requests coming from a single client even without using any sensitive information that would identify the site. This way, Moodle HQ can monitor the distribution of Moodle versions and deployed plugins while fully respecting the anonymous access to the update notification service.

Communication protocol, or There and Back Again

This section describes how a Moodle site as a client can fetch the information from the remote site.

Available Moodle update

UML sequence diagram - Checking for the available updates of Moodle core


  • A: The admin visits the Notifications page
  • B: During the page rendering, the available_update_checker class is called, requesting the information for the "core" component.
  • C: The checker looks into the local storage/cache (currently implemented using the config_plugins table) for the available update info.
  • D: The available update info is returned to the caller script. It is basically a data object that holds some useful properties like version, release (build) and maturity of Moodle code available at the remote site.
  • E: If the version available at the remote site is newer than the one currently installed, inform the admin. Admins can configure what maturity level the updates must have to be informed about (eg "Inform me about stable releases only") and whether they want to be informed about weekly builds, too.
  • F: The admin presses the button "Check for update now" (eventually a cronjob to do so is executed, the procedure is the same).
  • G: The checker's method fetch() is called
  • H: Internally, the checker class prepares the request URL to contain the currently installed Moodle version, branch and the list of installed plugins. It makes the HTTP POST request to the remote site script http://download.moodle.org/api/1.0/updates.php
  • J: The remote site returns requested data in a form of JSON encoded structure.
  • K: The checker class stores the response in the local storage for later usage
  • L: The browser is redirected back to the screen with the button. GOTO A.

Available plugin updates

UML sequence diagram - Checking for the available updates of Moodle plugins


The mechanism is the same from the client's point of view. The remote site runs its own cron jobs to fetch and populate required data from both sources and make them ready to be served.

Example response format

   $data = array(
       'status' => 'OK', // the constant 'OK' is checked by the client
       'provider' => 'http://download.moodle.org/api/1.0/updates.php', // our URL that prepared these data
       'apiver' => '1.0', // API version determines the format of the response
       'timegenerated' => time(), // our timestamp of when the data were populated and sent back
       'forbranch' => '2.3', // the caller's major version they provided in the request
       'forversion' => '2012031500.00', // the caller's version they provided in the request
       'ticket' => $newticket, // a value that the client should pass via the 'ticket' param during the next request
       'updates' => array( // list of available updates for the caller (based on their version provided in the request)
           'core' => array( // Moodle core updates. eg for a 2.3 client it would return all stable 2.3.x, 2.4.y, 2.5.z etc
               array(
                   'version' => 2012031500.04,
                   'release' => '2.3dev (Build: 20121201)',
                   'maturity' => 200, // one of the MATURITY_xxx constants
                   'url' => 'http://download.moodle.org/', // general URL to visit and know more about the component
                   'download' => 'http://download.moodle.org/download.php/MOODLE_23_STABLE/moodle-2.3.3-latest.zip', // URL to get the ZIP
               ),
               array(
                   'version' => 2012120100.06,
                   'release' => '2.3dev (Build: 20121201)',
                   'maturity' => 150, // one of the MATURITY_RC constants
                   'url' => 'http://download.moodle.org/',
                   'download' => 'http://download.moodle.org/download.php/MOODLE_24_STABLE/moodle-2.4.0-latest.zip',
               ),
               array(
                   'version' => 2012120804,
                   'release' => '2.3dev (Build: 20121208)',
                   'maturity' => 50, // one of the MATURITY_xxx constants
                   'url' => 'http://download.moodle.org/',
                   'download' => 'http://download.moodle.org/download.php/master/moodle-2.5-dev.zip',
               ),
           ),
           'local_moodlecheck' => array(
               array(
                   // info from the plugin's version.php, just 'version' is mandatory
                   'version' => 2012011000,
                   'requires' => 2010112400,
                   'maturity' => 200, // {@link MATURITY_STABLE}
                   'release' => '1.0',
                   'url' => 'http://moodle.org/plugins/',
                   'download' => 'http://moodle.org/plugins/download.php',
               ),
               array(
                   'version' => 2012091501,
                   'requires' => 2010112400,
                   'maturity' => 150, // {@link MATURITY_STABLE}
                   'release' => '1.1 RC1',
                   'url' => 'http://moodle.org/plugins/',
                   'download' => 'http://moodle.org/plugins/download.php',
               ),
               array(
                   'version' => 2012120100,
                   'requires' => 2010112400,
                   'maturity' => 50, // {@link MATURITY_STABLE}
                   'release' => '1.2 dev',
                   'url' => 'http://moodle.org/plugins/',
                   'download' => 'http://moodle.org/plugins/download.php',
               ),
           ),
           'qtype_oumultiresponse' => array(
               array(
                   'version' => 2011051200,
                   'requires' => 2011070100,
                   'maturity' => 200, // {@link MATURITY_STABLE}
                   'release' => '1.0',
                   'dependencies' => array(
                       'qtype_multichoice' => 'any', // {@link ANY_VERSION}
                   ),
               ),
           ),
       ),
   );

Discussion

This section contains some leftover notes from the previous versions of this spec to illustrate the background and considered aspects of the design.

Originally there have been several suggestions of how the information about the available updates would be transferred from primary sources to target sites.

Generated XML files
This was proposed by Petr in October 2009 and is described at the Upgrade notification page. The format itself (XML) does not matter much and can be replaced by JSON or another format. The pros of this approach is that these files can be generated by a cronjob and cached to improve performance by reducing queries.
Using the current component_installer
This overlaps the previous approach. As Eloy pointed out, correctly, we already have a system like this in Moodle core. We use it for timezones and language packs at the moment. The pros of this is that we already use it and it seems to work pretty well.
Using heavy-weight web service
This project seems to be a good opportunity for the new WS framework we have. The source of information would expose the functionality via the WS API. REST/JSON format seems to be the way to go. See Specification - create a public web service server.
Using light-weight web service
As we do not need to cope with the access control here (and need something really cheap in terms of resources and performance), there is actually no need to use the underlying WS subsystem. The service can be produced by a simple script. There is already this approach used at http://lang.moodle.org/local/amos/rest/greylist?format=csv (see this commit to see how it is implemented).
Combining with current site registration system
The registration system is used to gather information about sites for statistical purposes. It could be enhanced to return information about current versions.

It is also wise to consider extending the system in the future. We should come up with a solution that is capable of not only providing a list of available updates, but also delivers the source code packages themselves.

Gathering statistical information during an update check

There is potential to gather information about the Moodle version and plugin versions related to a site.

At the moment, plugin downloads and page views is the only measure of plugin popularity we are capturing. If we can gather real information about plugins installed on sites and the number of instances in use, we can build up a realistic picture of the popularity of plugins, which can be returned as feedback to plugin developers and potential users.

Moodle version information is shared via site registration, however, not all sites register. Perhaps offering this service with a prerequisite of registering will encourage more admins to register, leading to a clearer picture of Moodle use.

The information gathered by this system could be seen as confidential, so it would be necessary to include an opt in/out mechanism similar to, or combined with, the current site registration. If this update notification system is to be constructed separately to the registration system, it may still be possible to gather information about Moodle and plugin versions during a passive update check. If the site transmits a list of plugins and versions, this could be paired to the sender's IP address and retained semi-anonymously.

See also