Thursday, October 11, 2012

Adding Moodle 1.9 Block Restore to Moodle 2.3 - Part 1

I discovered recently, when trying to restore a Moodle 1.9 course into a Moodle 2.3 site, that the blocks that were part of the 1.9 course were not restored at all to the Moodle 2.3 course. This is a problem for me and my clients.

To look into the situation, I went to the Moodle tracker to see if  there was any information about this. I found MDL-32880.

After some communication through the issue, and through other development channels, I discovered that in fact that functionality had not made it into Moodle 2 yet. This led me to start looking for what it would take to get this functionality done, and if you look at the tracker issue, well, led me to be the one assigned to the task! Be careful when you offer to help.

Anyway, since I now have to figure out what to do, how the Moodle 1.0 to Moodle 2 conversion works and how the entire Moodle 2 restore framework works, I am inviting you along.

This series will document my efforts to build the Moodle 1.9 to Moodle 2 course block restore functionality. You should have a good working knowledge of PHP and Moodle code to be able to follow along. And, I since this is a work in progress, I cannot guarantee success. But you should at least learn what I do.

. . .

The first struggle I have come up against is understanding how Moodle 1.9 courses get identified and how the execution structure works to convert and restore them into Moodle 2. There are some hints in the tracker item, referring to handlers and restore log output. For example, there is reference to the following messages in the restore log when blocks are attempted:
[Wed Aug 29 15:25:32 2012] [warn] (moodle1) no handler attached /MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/PARTICIPANTS
[Wed Aug 29 15:25:32 2012] [warn] (moodle1) no handler attached /MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/ACTIVITY_MODULES
[Wed Aug 29 15:25:32 2012] [warn] (moodle1) no handler attached /MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/SEARCH_FORUMS
[Wed Aug 29 15:25:32 2012] [warn] (moodle1) no handler attached /MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/ADMIN
[Wed Aug 29 15:25:32 2012] [warn] (moodle1) no handler attached /MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/COURSE_LIST
[Wed Aug 29 15:25:32 2012] [warn] (moodle1) no handler attached /MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/NEWS_ITEMS
[Wed Aug 29 15:25:32 2012] [warn] (moodle1) no handler attached /MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/CALENDAR_UPCOMING
[Wed Aug 29 15:25:32 2012] [warn] (moodle1) no handler attached /MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/RECENT_ACTIVITY
As well, there is a recommendation to look at the "/backup/converter/moodle1/handlerlib.php" file.

From this, I learn three things. First, the warning message comes from the process_chunk function in "/backup/converter/moodle1/lib.php". Second, there is an empty, defined block handler in "/backup/converter/moodle1/handlerlib.php" called moodle1_block_handler. Third, I still have no idea how any of this works together.

After a few more questions and a few more code searches, I have some more useful information. First, there is an architectural document called "Backup 1.9 conversion for developers" that begins to describe the process of conversion and the execution flow of the restore process. Second the log information for the restore is in the "moodledata" directory located in "/temp/backup" in files called "{restore-controller-id}.log". This will help me to run some tests and determine if I am on the correct track.

Because there isn't always a good document to follow when building something like this, I try to use what's there to determine what is needed. The log file and the code in process_chunk and moodle1_block_handler are telling me that the Moodle 1.9 to 2 restore conversion process already is set up to try and perform block conversion. I want to find out how much is already there for me.

Looking at the document I referred to, and the code used by course modules, I can see that any block will probably need a "backup/moodle1/lib.php" file to define the restore conversion code. And looking at the warnings in the restore log file, it looks like that file needs to have a block restore handler. And, looking at the way modules are restored, I believe that handler needs to extend the moodle1_block_handler class and add the block name to the extended class like moodle1_block_[blockname]_handler.

Armed with that, I'm going to experiment using the "Participants" block. I create a new "/blocks/participants/backup/moodle1/lib.php" file as follows:
<?php

/**
 * Provides support for the conversion of moodle1 backup to the moodle2 format
 *
 * @package    block_participants
 * @copyright  2012 Mike Churchward (mike@remote-learner.net)
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

defined('MOODLE_INTERNAL') || die();

/**
 * Block Participants conversion handler
 */
class moodle1_block_participants_handler extends moodle1_block_handler {

}
Now, I am going to retry my Moodle 1.9 restore, and see what happens. If I get it right, the warning for that block should not appear in the restore log. Re-running the restore operation, I am stopped with the error:
Fatal error: Call to undefined method moodle1_block_participants_handler::get_paths() in /home/www/moodlehq.git/backup/converter/moodle1/lib.php on line 138
Believe it or not, this is reassuring. My addition to this block changed the way the restore operation worked. This means that there are definitely hooks already in the 1.9 to 2 restore conversion for blocks that are called when present. In this case, my new class was instantiated, executed and found wanting. But, it was executed!

Looking at the document I referred to, I see that it mentions that all module handlers must define the function "get_paths". This is also the function noted as missing in the error message I received. I'm going to add that function, but have it return an empty array for now, like:
public function get_paths() {
    return array(
    );
}
Retrying my restore operation, yields no errors. No blocks either; but I didn't expect any yet. And, unfortunately, I am still getting the "[warn] (moodle1) no handler attached /MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/PARTICIPANTS" warning in the restore log. Still, I am pretty sure I now know where my work needs to begin. I will look more deeply into what the minimum handler requirements are, and see where I can go from there.

I'll pick this up in my next post.