Development:Themes 2.0 adding upgrade code
As theme's have got considerably more advanced in Moodle 2 there is now on occasion a need to write upgrade code for a theme. This quick tutorial looks at just how to do that.
Why?
As part of the Moodle 2 revamp theme's have been given the same abilities as many of the other plugin types within Moodle. They are now able to have settings pages, database tables, they can override renderers, and they can do all sorts of great things.
Unfortunately this change has its positives and negatives, on the positive you can now really get some cool stuff happening within a theme, the downside is just like any other plugin you need to think about those who are already using your theme when you make changes.
If you are changing the name of a setting, or if you are changing the database schema for the theme you will need to add upgrade code to your theme so that those who are already using your theme are moved along nicely and don't lose the effort they've put into customising and setting up your theme.
Step 1: version.php
For those of you who are already familiar with writing Moodle plugins you will be familiar with the version.php, however for many themer's the reality is that they've never gone beyond adding a settings page so this will be new.
The version.php file is a requirement for many plugin types, however for theme's it is optional. The idea is that it contains just two or three lines of code that tell Moodle what version the plugin is and a little bit about where it is meant to be, or what version of Moodle it requires. The version.php file for a theme should be created within the theme's base directory e.g. moodle/theme/mythemename/version.php.
The following is an example of what a version.php file for a theme looks like.
<?php
/**
* This is the version.php file for my theme.
*/
defined('MOODLE_INTERNAL') || die;
$plugin->version = 2011032900;
$plugin->component = 'theme_mythemename';
$plugin->requires = 2010122500;
$plugin->maturity = MATURITY_STABLE;
The first thing to notice here is that we are setting properties of an object called $plugin, this object will be used to describe our theme. We are setting four properties here, version, component, requires, and maturity. The version property is required and the rest are optional however it is best practice to put them in as well.
The version property
The version property is the version number of our theme and needs to be an integer, although you can set it to any integer value you want it is HIGHLY recommended to use the date format shown above as it is used everywhere else throughout Moodle.
The format is YYYYMMDDXX :
- YYYY is the four digit year, e.g. 2011
- MM is the month with preceding 0 if required, e.g. 03
- DD is the day with preceding 0 is required, e.g. 28
- XX is an incrementing value starting at 00, you can increment this if you add several upgrade code blocks on the same day.
As a hint its easiest just to set the version property to today's date when adding upgrade code, or releasing a version of your theme that introduces something new such as a database table, or config setting.
The component property
The component is used to describe the plugin and its type. In our case we are working with themes and the theme name I have used in my example is mythemename, therefore the component is theme_mythemename.
When installing or upgrading a plugin Moodle checks the component and uses it to make sure that the plugin has been installed in the correct location. This is particularly helpful for the end user as it prevents nasty accidents where they accidentally put a plugin in the wrong place.
If you are working on other types of plugins the component of course will differ, its best to refer to the docs for those plugin types to find out what you would have to use there.
The requires property
The requires property sets the version of Moodle that is required by this plugin. This is particularly handy if your plugin makes use of a feature that was introduced in a specific version of Moodle, or if your plugin relies on a bug fix that was introduced in a specific version.
You can find the current Moodle version by looking at main Moodle version.php file. In the example above I have set my theme to require Moodle 2.0.1 by setting the requires property to Moodle's version number when that was released. If you are trying to find out a specific version number you can do so by heading to https://github.com/moodle/moodle, changing the tag drop down to the version you desire, then inspecting the version.php file at the bottom of the files list. You should see $version = XXXXXXXXXX;.
The maturity property
This is a property that is expected to be fully supported in Moodle 2.1. It informs Moodle about the state of the code and can be one of the following values:
- MATURITY_STABLE
- Use this when the theme is stable and works well.
- MATURITY_RC
- This marks the theme as a release candidate, users can expect the theme to contain one or two bugs but be largely stable and usable.
- MATURITY_BETA
- This marks the theme as a beta release, users can expect the theme to contain several bugs and for it to be likely to change still.
- MATURITY_ALPHA
- This marks the theme as an alpha release, this is the first release of a new theme and users will expect to find a lot still needs to be done.
Step 2: install.php
If as part of this upgrade you are adding a version.php file to your theme then you will need to add your upgrade code to install.php rather than upgrade.php.
The reason for this is because Moodle processes install.php the first time that a version number is used rather than upgrade.php.
The install.php file should contain a single function that needs to be named following a strict naming scheme and it should be located in a directory called db located within your theme's directory, for example moodle/theme/mythemename/db/install.php.
For this example I have called my theme mythemename so the function will be as follows:
defined('MOODLE_INTERNAL') || die();
function xmldb_theme_mythemename_install() {
// We'll look at what is in here shortly.
return true;
}
This special function is called when a theme is first installed (if it has a version.php file and it has been newly added to your Moodle site) or the first time that the theme has a version.php file if you are developing or upgrading a theme.
The install function can perform any upgrade routines you require. For the following example lets assume I have two settings for my theme, mythemename_settingone, and mythemename_settingtwo. As part of my upgrade I want to rename the settings to mythemename_settinga, and mythemename_settingb.
defined('MOODLE_INTERNAL') || die();
function xmldb_theme_mythemename_install() {
$currentsetting = get_config('theme_mythemename');
// Create a new config called settinga and give it settingone's value.
set_config('settinga', $currentsetting->settingone, 'theme_mythemename');
// Remove settingone
unset_config('settingone', 'theme_mythemename');
// Create a new config called settingb and give it settingtwo's value.
set_config('settingb', $currentsetting->settingtwo, 'theme_mythemename');
// Remove settingtwo
unset_config('settingtwo', 'theme_mythemename');
return true;
}
Looking at this code it does the following things:
- The install code gets the current settings so that we can change them.
- It creates a new setting called settinga and we give it settingb's value.
- It deletes settingone as we no longer want it.
- It repeats the last two steps for settingb/settingtwo.
- It returns true so that Moodle knows the installation was successful.
And thats it, there's no need to add an upgrade.php file at this point.
Step 3: upgrade.php
The upgrade.php script allows you to write upgrade code for subsequent upgrade requirements for your theme. If your theme already has a version.php then you should bump the version number there and add your upgrade code here.
This is the main upgrade file. It should be located in a directory called db located within your theme's directory, for example moodle/theme/mythemename/db/upgrade.php.
The upgrade.php file should contain just a single function that needs to be named following a strict naming scheme. In the case of my theme that for this example I've called mythemename that function will be as follows:
<?php
defined('MOODLE_INTERNAL') || die();
function xmldb_theme_mythemename_upgrade($oldversion) {
// We'll look at what is in here shortly.
return true;
}
This special function gets called when ever the admin is upgrading the site and gives our theme the opportunity to run any upgrade code it requires.
Upgrade code within this function should be written in a special style where each operation is written as a block and the theme version is upgraded incrementally after each operation.
For the following example lets assume I have two settings for my theme, mythemename_settingone, and mythemename_settingtwo. As part of my upgrade I want to rename the settings to mythemename_settinga, and mythemename_settingb.
<?php
defined('MOODLE_INTERNAL') || die();
function xmldb_theme_mythemename_upgrade($oldversion) {
if ($oldversion < 2011032900) {
$currentsetting = get_config('theme_mythemename');
// Create a new config called settinga and give it settingone's value.
set_config('settinga', $currentsetting->settingone, 'theme_mythemename');
// Remove settingone
unset_config('settingone', 'theme_mythemename');
// Create a new config called settingb and give it settingtwo's value.
set_config('settingb', $currentsetting->settingtwo, 'theme_mythemename');
// Remove settingtwo
unset_config('settingtwo', 'theme_mythemename');
// Upgrade the version that Moodle knows is installed so that this upgrade
// isn't run again.
upgrade_plugin_savepoint(true, 2011032900, 'theme', 'mythemename');
}
return true;
}
Looking at this code it does the following things:
- It compares and the $oldversion to the version we set (2011032900) and our version is newer it runs the upgrade code.
- The upgrade code gets the current settings so that we can change them.
- It creates a new setting called settinga and we give it settingb's value.
- It deletes settingone as we no longer want it.
- It repeats the last two steps for settingb/settingtwo.
- It updates the version Moodle knows is installed by calling upgrade_plugin_savepoint
- Finally the function returns true so that the rest of the upgrade continues.
Done
Just like that we have added upgrade code to our theme that renames two settings. To do that we had to add a version.php file and a upgrade.php file.