Note:

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

Backup 2.0 theme data

From MoodleDocs

Moodle 2.0


Introduction

In Moodle 2, themes can have data tables and files which can be backed up with a course. (To create data tables in a theme, use the standard db folder.)

None of the standard themes have any course-related data so it is not obvious how to code the backup and restore for them. This page gives an example theme as a case study which you can use to implement your own backup code for a theme which contains per-course data.

Note: Theme data backup requires Moodle 2.0.3 or later.

Example: the 'ou' theme

Our theme called the 'ou' theme (i.e. in the folder theme/ou) contains the following per-course data which needs to be backed up:

  • Each course using the theme can select a different colour (referred to as 'variant' of the theme). This is so we can have different courses in any of 10 different colours without having to make 10 different themes.
  • Each course can also select a custom image which is used in the header on some screens. This is so we can have cute kitten pictures on our test servers.

The variant is stored in a table called theme_ou_courseoptions. This table has 3 fields: id, courseid, and variant. (If we ever need to add more theme data, we can add fields to it.)

The image file is stored using the Moodle file API at the course context, in the theme_ou component and the image file area.

Backup

The backup code is in the file theme/ou/backup/moodle2/backup_theme_ou_plugin.class.php. Leaving out the headers, this file looks like:

class backup_theme_ou_plugin extends backup_theme_plugin {

    /**
     * Returns the theme information to attach to course element
     */
    protected function define_course_plugin_structure() {
        // Define virtual plugin element
        $plugin = $this->get_plugin_element(null, $this->get_theme_condition(), 'ou');

        // Create plugin container element with standard name
        $pluginwrapper = new backup_nested_element($this->get_recommended_name());

        // Add wrapper to plugin
        $plugin->add_child($pluginwrapper);

        // Set up theme's own structure and add to wrapper
        $ou = new backup_nested_element('ou', array('id'), array(
            'variant'));
        $pluginwrapper->add_child($ou);

        // Use database to get source
        $ou->set_source_table('theme_ou_courseoptions',
                array('courseid' => backup::VAR_COURSEID));

        // Include files which have theme_ou and area image and no itemid
        $ou->annotate_files('theme_ou', 'image', null);

        return $plugin;
    }
}

As you can see this works in a similar way to backup for modules and other plugins. The first line:

$this->get_plugin_element(null, $this->get_theme_condition(), 'ou');

means that the theme data will only be backed up if the current theme for the course is actually the 'ou' theme. In other words, if you change the course theme to 'standard', this backup data will not be created. (It is possible to change this behaviour if you want to backup theme data even when a different theme is currently selected for the course; leave out the last two parameters.)

You can see how you would change the code to use a different theme name, database table, fields, or file area. It's also possible to add a more complicated data structured in the same way as for other plugins. You could even store user data - however, unless the user data is course-specific, it would probably be more appropriate to store user theme options in user preferences rather than within theme-managed tables.

Testing

To test the backup, carry it out and then look inside the resulting zip file. In the course folder there should be a file called course.xml. If theme data is backed up, it will include a section like the following:

<plugin_theme_ou_course>
 <ou id="2">
  <variant>purple</variant>
 </ou>
</plugin_theme_ou_course>

Additionally, if the file backup worked, you should be able to find any files from within the specified file area inside the 'files' section of the backup (it will help if you know the hash code of the file; otherwise, note the size and make sure the test course doesn't have many other files to look through).

If you switch the course to a different theme, this data will not be backed up.

Restore

Unsurprisingly, restore code goes in the file theme/ou/backup/moodle2/restore_theme_ou_plugin.class.php. Leaving out the headers, this file is:

class restore_theme_ou_plugin extends restore_theme_plugin {

    /**
     * Returns the paths to be handled by the plugin at course level
     */
    protected function define_course_plugin_structure() {
        $paths = array();

        // Because of using get_recommended_name() it is able to find the
        // correct path just by using the part inside the element name (which
        // only has a /ou element).
        $elepath = $this->get_pathfor('/ou');

        // The 'ou' here defines that it will use the process_ou function
        // to restore its element.
        $paths[] = new restore_path_element('ou', $elepath);

        return $paths;
    }

    /**
     * Called after this runs for a course.
     */
    function after_execute_course() {
        // Need to restore file
        $this->add_related_files('theme_ou', 'image', null);
    }

    /**
     * Process the 'ou' element
     */
    public function process_ou($data) {
        global $DB;

        // Get data record ready to insert in database
        $data = (object)$data;
        $data->courseid = $this->task->get_courseid();

        // See if there is an existing record for this course
        $existingid = $DB->get_field('theme_ou_courseoptions', 'id',
                array('courseid'=>$data->courseid));
        if ($existingid) {
            $data->id = $existingid;
            $DB->update_record('theme_ou_courseoptions', data);
        } else {
            $DB->insert_record('theme_ou_courseoptions', $data);
        }

        // No need to record the old/new id as nothing ever refers to
        // the id of this table.
    }
}

Again this is just the same as restoring a module. To change this to support your own theme, you would change the word 'ou' to your own theme's name, change references to the theme_ou_courseoptions table to your own data table (or otherwise change what exactly it does when restoring), and change the file area details in the add_related_files call.

Unlike backup, the restore code always runs if the data was included in the backup, even if the course actually has a different theme once it is restored (e.g. the site default theme has changed). This should not cause a particular problem; at worst you'll get a superfluous database row on rare occasions.

Testing

It is probably obvious how to test restore :) Once you've verified that backup is producing the correct XML data, just check that restore recreates the necessary data for you.

In our case, we know restore works if the restored course is purple and has a cute kitten picture.