Friday, December 9, 2011

Converting Moodle 1.9 Plug-ins to Moodle 2 - Activity Module Upgrade - Part 3

When I left off, I had completed bulk changing the DML function code for the module. Now I'll move on to other functional and output changes.

One of the key changes that affects this module is the standard use of the "intro" field. This is the field that typically provided the textual description for an instance of the module. In Moodle 1.9, some modules called it "intro". Others called it "description". This module called it "text". The point is, it was not standard and was not necessarily the same in all modules. In Moodle 2, it is standard, and needs to be called "intro".

To do this, I will first need to change the database code that sets it up, and add an upgrade script for existing installations.

For the "install.xml" file, there are three changes of "text" to "intro" I need to do: the actual entry for the "text" field's "NAME" parameter and the two entries on either side of it's "NEXT" and "PREVIOUS" parameters.

Along with "intro", Moodle 2 now requires that the module have an "introformat" field in the database table. This needs to be added to the "install.xml" file as well as the upgrade script. For this module, I need to change the old "format" field to "introformat". I'm not including the XML code here, but you can see it if you check it out of Git.

Next, I need to add an upgrade script to handle changing the database field name for sites that are upgrading from an older version. I add the following lines to the bottom of "db/upgrade.php" in my module:
if ($oldversion < 2010080300) {

/// Rename field text on table stampcoll to intro
    $table = new xmldb_table('stampcoll');
    $field = new xmldb_field('text', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, null, 'name');

/// Launch rename field description
    $dbman->rename_field($table, $field, 'intro');


/// Define field introformat to be added to data
    $field = new xmldb_field('format', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'intro');

/// Launch rename field introformat
    $dbman->rename_field($table, $field, 'introformat');

    // conditionally migrate to html format in intro
    if ($CFG->texteditors !== 'textarea') {
        $rs = $DB->get_recordset('stampcoll', array('introformat'=>FORMAT_MOODLE), '', 'id,intro,introformat');
        foreach ($rs as $d) {
            $d->intro       = text_to_html($d->intro, false, false, true);
            $d->introformat = FORMAT_HTML;
            $DB->update_record('stampcoll', $d);
            upgrade_set_timeout();
        }
        $rs->close();
    }
/// stampcoll savepoint reached
    upgrade_mod_savepoint(true, 2010080300, 'stampcoll');
}
This block of code will rename the "text" field of the "stampcoll" table to "intro" and the "format" field to "introformat". It will also reset the format values where necessary for existing instances. Just to be sure, I test this by manually changing the version of the "stampcoll" entry to a lesser number, and then hitting the "Notifications" screen of my site. As expected, the "stampcoll" table "text" and the "format" fields are renamed.

Lastly I test the XML changes by removing the "stampcoll" module, and then allowing it to be reinstalled from the "Notifications" screen. This works too.

After making those changes, I need to then go and change every use of the "text" variable to "intro". This will also be important in my restore code that I will deal with later on, since older restore sets will be using "text" and not "intro". Searching, and being careful to find only the correct places, I replace the few "text" instances that need replacing (in "lib.php" and "view.php"). There will be changes in backup and restore as well, but I'm doing that later.

I don't need to worry about "introformat", since that is a variable used internally by the API, and not directly by my code. 

Next, I'm going to change the module edit form in "mod_form.php". Most of this remains the same as before, but there are some crucial differences.

The first and easiest is changing the "intro" component. In Moodle 1.9. this involved several lines. In Moodle 2, thanks to the standardization of the "intro" field (which I just fixed), it is now only one line. So I change the lines:
/// text (description)
    $mform->addElement('htmleditor', 'text', get_string('description'));
    $mform->setType('text', PARAM_RAW);
    //$mform->addRule('text', get_string('required'), 'required', null, 'client');
    $mform->setHelpButton('text', array('writing', 'richtext'), false, 'editorhelpbutton');
/// introformat
    $mform->addElement('format', 'introformat', get_string('format'));
to:
/// intro
    $this->add_intro_editor(true, get_string('description'));
The next change I have to make involves the help system. Now, in this particular module, there are no specific help buttons added. But if there were, I would need to change each occurrence of:
$mform->setHelpButton('elementname', array('helpfilename', get_string('helpstring', 'component'), 'component'));
to:
$mform->addHelpButton('elementname', 'helpstring', 'component');
The function name changes, and the arguments are simplified. Additionally, all old "help" files in your language directories need to removed, and their contents added to the main language file, assigned to the string "helpstring_help".

One thing to consider at this point, is that the help buttons that are added now are mouseover text areas. The amount of text displayed there should be suitably limited. If you need more help content, you can create HTML files elsewhere, and link to them in the help string. Moodle docs provides a space to create this content if you want to use it.

One thing I will change for this module is the help text for the main edit screen, up next to the title. In Moodle 1.9, this content was in the "lang/en_utf8/help/stampcoll/mods.html" file. In Moodle 2, this is in the language string "modulename_help". I add a shortened version of this text to that string in my "lang/en/stampcoll.php" file.

These changes should be all I need to be able to add and edit instances of the module. I test it to make sure, and indeed I can successfully add and edit instances. I'm far from done though. Clicking on an added module will display a lot of errors still. In the next part, I'll work on fixing those.

Make sure you get the latest code from Git, to follow along.