From a374ba237c8a9a0198499ac6604c62aad2781008 Mon Sep 17 00:00:00 2001 From: Paul Nicholls Date: Wed, 24 Oct 2012 10:04:21 +1300 Subject: [PATCH 1/3] MDL-32880: moodle1 backup converter: add generic block handler This handler will automatically be used for any block which does not provide its own handler, and should be subclassed by any block which needs to do anything extra (or different). This commit incorporates contributions from Mike Churchward and API design suggestions from David Mudrak. --- backup/converter/moodle1/handlerlib.php | 91 ++++++++++++++++++++++++- backup/converter/moodle1/lib.php | 8 +-- 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/backup/converter/moodle1/handlerlib.php b/backup/converter/moodle1/handlerlib.php index 51cad6429d2..a2744c284c3 100644 --- a/backup/converter/moodle1/handlerlib.php +++ b/backup/converter/moodle1/handlerlib.php @@ -88,10 +88,13 @@ abstract class moodle1_handlers_factory { foreach ($plugins as $name => $dir) { $handlerfile = $dir . '/backup/moodle1/lib.php'; $handlerclass = "moodle1_{$type}_{$name}_handler"; - if (!file_exists($handlerfile)) { + if (file_exists($handlerfile)) { + require_once($handlerfile); + } elseif ($type == 'block') { + $handlerclass = "moodle1_block_generic_handler"; + } else { continue; } - require_once($handlerfile); if (!class_exists($handlerclass)) { throw new moodle1_convert_exception('missing_handler_class', $handlerclass); @@ -1989,9 +1992,93 @@ abstract class moodle1_resource_successor_handler extends moodle1_mod_handler { */ abstract class moodle1_block_handler extends moodle1_plugin_handler { + public function get_paths() { + $blockname = strtoupper($this->pluginname); + return array( + new convert_path('block', "/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/{$blockname}"), + ); + } + + public function process_block(array $data) { + $newdata = $this->convert_common_block_data($data); + + $this->write_block_xml($newdata, $data); + $this->write_inforef_xml($newdata, $data); + $this->write_roles_xml($newdata, $data); + + return $data; + } + + protected function convert_common_block_data(array $olddata) { + $newdata = array(); + + $newdata['blockname'] = $olddata['name']; + $newdata['parentcontextid'] = $this->converter->get_contextid(CONTEXT_COURSE, 0); + $newdata['showinsubcontexts'] = 0; + $newdata['pagetypepattern'] = $olddata['pagetype'].='-*'; + $newdata['subpagepattern'] = null; + $newdata['defaultregion'] = ($olddata['position']=='l')?'side-pre':'side-post'; + $newdata['defaultweight'] = $olddata['weight']; + $newdata['configdata'] = $this->convert_configdata($olddata); + + return $newdata; + } + + protected function convert_configdata(array $olddata) { + return $olddata['configdata']; + } + + protected function write_block_xml($newdata, $data) { + $contextid = $this->converter->get_contextid(CONTEXT_BLOCK, $data['id']); + + $this->open_xml_writer("course/blocks/{$data['name']}_{$data['id']}/block.xml"); + $this->xmlwriter->begin_tag('block', array('id' => $data['id'], 'contextid' => $contextid)); + + foreach ($newdata as $field => $value) { + $this->xmlwriter->full_tag($field, $value); + } + + $this->xmlwriter->begin_tag('block_positions'); + $this->xmlwriter->begin_tag('block_position', array('id' => 1)); + $this->xmlwriter->full_tag('contextid', $newdata['parentcontextid']); + $this->xmlwriter->full_tag('pagetype', $data['pagetype']); + $this->xmlwriter->full_tag('subpage', ''); + $this->xmlwriter->full_tag('visible', $data['visible']); + $this->xmlwriter->full_tag('region', $newdata['defaultregion']); + $this->xmlwriter->full_tag('weight', $newdata['defaultweight']); + $this->xmlwriter->end_tag('block_position'); + $this->xmlwriter->end_tag('block_positions'); + $this->xmlwriter->end_tag('block'); + $this->close_xml_writer(); + } + + protected function write_inforef_xml($newdata, $data) { + $this->open_xml_writer("course/blocks/{$data['name']}_{$data['id']}/inforef.xml"); + $this->xmlwriter->begin_tag('inforef'); + // Subclasses may provide inforef contents if needed + $this->xmlwriter->end_tag('inforef'); + $this->close_xml_writer(); + } + + protected function write_roles_xml($newdata, $data) { + // This is an empty shell, as the moodle1 converter doesn't handle user data. + $this->open_xml_writer("course/blocks/{$data['name']}_{$data['id']}/roles.xml"); + $this->xmlwriter->begin_tag('roles'); + $this->xmlwriter->full_tag('role_overrides', ''); + $this->xmlwriter->full_tag('role_assignments', ''); + $this->xmlwriter->end_tag('roles'); + $this->close_xml_writer(); + } } +/** + * Base class for block generic handler + */ +class moodle1_block_generic_handler extends moodle1_block_handler { + +} + /** * Base class for the activity modules' subplugins */ diff --git a/backup/converter/moodle1/lib.php b/backup/converter/moodle1/lib.php index 46d7514cfe0..3d95d3002ef 100644 --- a/backup/converter/moodle1/lib.php +++ b/backup/converter/moodle1/lib.php @@ -254,7 +254,7 @@ class moodle1_converter extends base_converter { $path = '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentblock; } else if (strpos($path, '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK') === 0) { - $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentmod, $path); + $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentblock, $path); } if ($path !== $data['path']) { @@ -350,12 +350,12 @@ class moodle1_converter extends base_converter { } if ($path === '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK') { - $this->currentmod = null; + $this->currentblock = null; $forbidden = true; } else if (strpos($path, '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK') === 0) { // expand the BLOCK paths so that they contain the module name - $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentmod, $path); + $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentblock, $path); } if (empty($this->pathelements[$path])) { @@ -397,7 +397,7 @@ class moodle1_converter extends base_converter { $path = '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentblock; } else if (strpos($path, '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK') === 0) { - $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentmod, $path); + $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentblock, $path); } if (empty($this->pathelements[$path])) { From 14bb973bfa701d2e6aa7fdc1f04187a4bd256e70 Mon Sep 17 00:00:00 2001 From: Paul Nicholls Date: Tue, 20 Nov 2012 11:59:51 +1300 Subject: [PATCH 2/3] MDL-32880: Add moodle1 backup converter for html block. This converter processes the HTML block's content, migrating any referenced files. --- blocks/html/backup/moodle1/lib.php | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 blocks/html/backup/moodle1/lib.php diff --git a/blocks/html/backup/moodle1/lib.php b/blocks/html/backup/moodle1/lib.php new file mode 100644 index 00000000000..d4a491f1c86 --- /dev/null +++ b/blocks/html/backup/moodle1/lib.php @@ -0,0 +1,46 @@ +converter->get_contextid(CONTEXT_BLOCK, $olddata['id']); + $configdata = unserialize(base64_decode($olddata['configdata'])); + + // get a fresh new file manager for this instance + $this->fileman = $this->converter->get_file_manager($contextid, 'block_html'); + + // convert course files embedded in the block content + $this->fileman->filearea = 'content'; + $this->fileman->itemid = 0; + $configdata->text = moodle1_converter::migrate_referenced_files($configdata->text, $this->fileman); + $configdata->format = FORMAT_HTML; + + return base64_encode(serialize($configdata)); + } + + protected function write_inforef_xml($newdata, $data) { + $this->open_xml_writer("course/blocks/{$data['name']}_{$data['id']}/inforef.xml"); + $this->xmlwriter->begin_tag('inforef'); + $this->xmlwriter->begin_tag('fileref'); + foreach ($this->fileman->get_fileids() as $fileid) { + $this->write_xml('file', array('id' => $fileid)); + } + $this->xmlwriter->end_tag('fileref'); + $this->xmlwriter->end_tag('inforef'); + $this->close_xml_writer(); + } +} \ No newline at end of file From c931551acb269dd4dc784bbcb95fb09cc83b9503 Mon Sep 17 00:00:00 2001 From: Paul Nicholls Date: Wed, 7 Nov 2012 14:06:03 +1300 Subject: [PATCH 3/3] MDL-32880: Add moodle1 backup converter for rss_client block. Creates a shell rss_client.xml file, which contains no feeds. This makes it behave the same as restoring a Moodle 1.9 backup into a different 1.9 site - the block is created, its title is as per the original course, but it has no feeds selected (and none are added to the site's feed list). --- blocks/rss_client/backup/moodle1/lib.php | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 blocks/rss_client/backup/moodle1/lib.php diff --git a/blocks/rss_client/backup/moodle1/lib.php b/blocks/rss_client/backup/moodle1/lib.php new file mode 100644 index 00000000000..95da634ac0a --- /dev/null +++ b/blocks/rss_client/backup/moodle1/lib.php @@ -0,0 +1,34 @@ +converter->get_contextid(CONTEXT_BLOCK, $data['id']); + + // Moodle 1.9 backups do not include sufficient data to restore feeds, so we need an empty shell rss_client.xml + // for the restore process to find + $this->open_xml_writer("course/blocks/{$data['name']}_{$instanceid}/rss_client.xml"); + $this->xmlwriter->begin_tag('block', array('id' => $instanceid, 'contextid' => $contextid, 'blockname' => 'rss_client')); + $this->xmlwriter->begin_tag('rss_client', array('id' => $instanceid)); + $this->xmlwriter->full_tag('feeds', ''); + $this->xmlwriter->end_tag('rss_client'); + $this->xmlwriter->end_tag('block'); + $this->close_xml_writer(); + + return $data; + } +} \ No newline at end of file