MDL-27379 Backup conversion logging facilities

This commit is contained in:
David Mudrak 2011-06-06 13:56:06 +02:00
parent 1b85912abb
commit fe50f530fd
10 changed files with 163 additions and 41 deletions

View File

@ -387,13 +387,17 @@ class restore_controller extends backup implements loggable {
throw new restore_controller_exception('cannot_convert_not_required_status');
}
$this->log('backup format conversion required', backup::LOG_INFO);
// Run conversion to the proper format
if (!convert_helper::to_moodle2_format($this->get_tempdir(), $this->format)) {
if (!convert_helper::to_moodle2_format($this->get_tempdir(), $this->format, $this->get_logger())) {
// todo - unable to find the conversion path, what to do now?
// throwing the exception as a temporary solution
throw new restore_controller_exception('unable_to_find_conversion_path');
}
$this->log('backup format conversion successful', backup::LOG_INFO);
// If no exceptions were thrown, then we are in the proper format
$this->format = backup::FORMAT_MOODLE;

View File

@ -35,28 +35,68 @@ require_once($CFG->dirroot . '/backup/util/includes/convert_includes.php');
*
* @throws convert_exception
*/
abstract class base_converter {
abstract class base_converter implements loggable {
/** @var string unique identifier of this converter instance */
protected $id;
/** @var string the name of the directory containing the unpacked backup being converted */
protected $tempdir;
/** @var string the name of the directory where the backup is converted to */
protected $workdir;
/** @var null|base_logger logger to use during the conversion */
protected $logger = null;
/**
* Constructor
*
* @param string $tempdir the relative path to the directory containing the unpacked backup to convert
* @param null|base_logger logger to use during the conversion
*/
public function __construct($tempdir) {
public function __construct($tempdir, $logger = null) {
$this->tempdir = $tempdir;
$this->id = convert_helper::generate_id($tempdir);
$this->workdir = $tempdir . '_' . $this->get_name() . '_' . $this->id;
$this->set_logger($logger);
$this->log('instantiating '.$this->get_name().' converter '.$this->get_id(), backup::LOG_DEBUG);
$this->log('conversion source directory', backup::LOG_DEBUG, $this->tempdir);
$this->log('conversion target directory', backup::LOG_DEBUG, $this->workdir);
$this->init();
}
/**
* Sets the logger to use during the conversion
*
* @param null|base_logger $logger
*/
public function set_logger($logger) {
if (is_null($logger) or ($logger instanceof base_logger)) {
$this->logger = $logger;
}
}
/**
* If the logger was set for the converter, log the message
*
* If the $display is enabled, the spaces in the $message text are removed
* and the text is used as a string identifier in the core_backup language file.
*
* @see backup_helper::log()
* @param string $message message text
* @param int $level message level {@example backup::LOG_WARNING}
* @param null|mixed $a additional information
* @param null|int $depth the message depth
* @param bool $display whether the message should be sent to the output, too
*/
public function log($message, $level, $a = null, $depth = null, $display = false) {
if ($this->logger instanceof base_logger) {
backup_helper::log($message, $level, $a, $depth, $display, $this->logger);
}
}
/**
* Get instance identifier
*
@ -81,8 +121,13 @@ abstract class base_converter {
public function convert() {
try {
$this->log('creating the target directory', backup::LOG_DEBUG);
$this->create_workdir();
$this->log('executing the conversion', backup::LOG_DEBUG);
$this->execute();
$this->log('replacing the source directory with the converted version', backup::LOG_DEBUG);
$this->replace_tempdir();
} catch (Exception $e) {
}
@ -96,6 +141,24 @@ abstract class base_converter {
}
}
/**
* @return string the full path to the working directory
*/
public function get_workdir_path() {
global $CFG;
return "$CFG->dataroot/temp/backup/$this->workdir";
}
/**
* @return string the full path to the directory with the source backup
*/
public function get_tempdir_path() {
global $CFG;
return "$CFG->dataroot/temp/backup/$this->tempdir";
}
/// public static methods //////////////////////////////////////////////////
/**
@ -142,24 +205,6 @@ abstract class base_converter {
);
}
/**
* @return string the full path to the working directory
*/
public function get_workdir_path() {
global $CFG;
return "$CFG->dataroot/temp/backup/$this->workdir";
}
/**
* @return string the full path to the directory with the source backup
*/
public function get_tempdir_path() {
global $CFG;
return "$CFG->dataroot/temp/backup/$this->tempdir";
}
/// end of public API //////////////////////////////////////////////////////
/**

View File

@ -103,7 +103,7 @@ abstract class moodle1_handlers_factory {
/**
* Base backup conversion handler
*/
abstract class moodle1_handler {
abstract class moodle1_handler implements loggable {
/** @var moodle1_converter */
protected $converter;
@ -121,6 +121,19 @@ abstract class moodle1_handler {
public function get_converter() {
return $this->converter;
}
/**
* Log a message using the converter's logging mechanism
*
* @param string $message message text
* @param int $level message level {@example backup::LOG_WARNING}
* @param null|mixed $a additional information
* @param null|int $depth the message depth
* @param bool $display whether the message should be sent to the output, too
*/
public function log($message, $level, $a = null, $depth = null, $display = false) {
$this->converter->log($message, $level, $a, $depth, $display);
}
}
@ -287,6 +300,7 @@ class moodle1_root_handler extends moodle1_xml_handler {
* Converts course_files and site_files
*/
public function on_root_element_start() {
// convert course files
$fileshandler = new moodle1_files_handler($this->converter);
$fileshandler->process();
@ -542,6 +556,7 @@ class moodle1_files_handler extends moodle1_xml_handler {
$ids = $fileman->migrate_directory('course_files');
$this->converter->set_stash('course_files_ids', $ids);
}
$this->log('course files migrated', backup::LOG_INFO, count($ids));
}
}
@ -602,6 +617,8 @@ class moodle1_info_handler extends moodle1_handler {
if (file_exists($CFG->dirroot.'/mod/'.$modname.'/backup/moodle1/lib.php')) {
$this->converter->set_stash('modinfo_'.$modname, $this->currentmod);
$this->modnames[] = $modname;
} else {
$this->log('unsupported activity module', backup::LOG_WARNING, $modname);
}
$this->currentmod = array();
@ -1154,7 +1171,7 @@ class moodle1_question_bank_handler extends moodle1_xml_handler {
$data['questiontext'] .= ' <img src="@@PLUGINFILE@@/' . $filename . '" />';
} else {
debugging('Question id '.$data['id']. ' file not found: '.$filepath.$filename);
$this->log('question file not found', backup::LOG_WARNING, array($data['id'], $filepath.$filename));
}
}
}
@ -1178,7 +1195,7 @@ class moodle1_question_bank_handler extends moodle1_xml_handler {
if (!in_array($qtype, array('description', 'random'))) {
$handler = $this->get_qtype_handler($qtype);
if ($handler === false) {
debugging('Question type '.$qtype.' converter not found.', DEBUG_DEVELOPER);
$this->log('question type converter not found', backup::LOG_ERROR, $qtype);
} else {
$this->xmlwriter->begin_tag('plugin_qtype_'.$qtype.'_question');
@ -1235,7 +1252,7 @@ class moodle1_question_bank_handler extends moodle1_xml_handler {
protected function get_qtype_handler($qtype) {
if (is_null($this->qtypehandlers)) {
// initialize the static list of qtype handler instances
// initialize the list of qtype handler instances
$this->qtypehandlers = array();
foreach (get_plugin_list('qtype') as $qtypename => $qtypelocation) {
$filename = $qtypelocation.'/backup/moodle1/lib.php';
@ -1245,6 +1262,7 @@ class moodle1_question_bank_handler extends moodle1_xml_handler {
if (!class_exists($classname)) {
throw new moodle1_convert_exception('missing_handler_class', $classname);
}
$this->log('registering handler', backup::LOG_DEBUG, $classname, 2);
$this->qtypehandlers[$qtypename] = new $classname($this, $qtypename);
}
}

View File

@ -66,6 +66,20 @@ class moodle1_converter extends base_converter {
*/
const SKIP_ALL_CHILDREN = -991399;
/**
* Log a message
*
* @see parent::log()
* @param string $message message text
* @param int $level message level {@example backup::LOG_WARNING}
* @param null|mixed $a additional information
* @param null|int $depth the message depth
* @param bool $display whether the message should be sent to the output, too
*/
public function log($message, $level, $a = null, $depth = null, $display = false) {
parent::log('(moodle1) '.$message, $level, $a, $depth, $display);
}
/**
* Detects the Moodle 1.9 format of the backup directory
*
@ -104,9 +118,13 @@ class moodle1_converter extends base_converter {
// ask your mother first before going out playing with toys
parent::init();
$this->log('initializing '.$this->get_name().' converter', backup::LOG_INFO);
// good boy, prepare XML parser and processor
$this->log('setting xml parser', backup::LOG_DEBUG, null, 1);
$this->xmlparser = new progressive_parser();
$this->xmlparser->set_file($this->get_tempdir_path() . '/moodle.xml');
$this->log('setting xml processor', backup::LOG_DEBUG, null, 1);
$this->xmlprocessor = new moodle1_parser_processor($this);
$this->xmlparser->set_processor($this->xmlprocessor);
@ -116,6 +134,7 @@ class moodle1_converter extends base_converter {
// register the conversion handlers
foreach (moodle1_handlers_factory::get_handlers($this) as $handler) {
$this->log('registering handler', backup::LOG_DEBUG, get_class($handler), 1);
$this->register_handler($handler, $handler->get_paths());
}
}
@ -124,8 +143,14 @@ class moodle1_converter extends base_converter {
* Converts the contents of the tempdir into the target format in the workdir
*/
protected function execute() {
$this->log('creating the stash storage', backup::LOG_DEBUG);
$this->create_stash_storage();
$this->log('parsing moodle.xml starts', backup::LOG_DEBUG);
$this->xmlparser->process();
$this->log('parsing moodle.xml done', backup::LOG_DEBUG);
$this->log('dropping the stash storage', backup::LOG_DEBUG);
$this->drop_stash_storage();
}
@ -235,8 +260,7 @@ class moodle1_converter extends base_converter {
if ($path !== $data['path']) {
if (!array_key_exists($path, $this->pathelements)) {
// no handler registered for the transformed MOD or BLOCK path
// todo add this event to the convert log instead of debugging
//debugging('No handler registered for the path ' . $path);
$this->log('no handler attached', backup::LOG_WARNING, $path);
return;
} else {
@ -554,7 +578,7 @@ class moodle1_converter extends base_converter {
$fileman->migrate_file('course_files'.$file, dirname($file));
} catch (moodle1_convert_exception $e) {
// file probably does not exist
// todo add to the conversion log
$fileman->log('error migrating file', backup::LOG_WARNING, 'course_files'.$file);
}
}
$text = self::rewrite_filephp_usage($text, $files);
@ -1086,7 +1110,7 @@ class convert_path_exception extends moodle_exception {
* The files in Moodle 1.9 backup are stored in moddata, user_files, group_files,
* course_files and site_files folders.
*/
class moodle1_file_manager {
class moodle1_file_manager implements loggable {
/** @var moodle1_converter instance we serve to */
public $converter;
@ -1270,6 +1294,19 @@ class moodle1_file_manager {
$this->fileids = array();
}
/**
* Log a message using the converter's logging mechanism
*
* @param string $message message text
* @param int $level message level {@example backup::LOG_WARNING}
* @param null|mixed $a additional information
* @param null|int $depth the message depth
* @param bool $display whether the message should be sent to the output, too
*/
public function log($message, $level, $a = null, $depth = null, $display = false) {
$this->converter->log($message, $level, $a, $depth, $display);
}
/// internal implementation details ////////////////////////////////////////
/**

View File

@ -33,11 +33,12 @@ abstract class convert_factory {
* Instantinates the given converter operating on a given directory
*
* @throws coding_exception
* @param $name The converter name
* @param $tempdir The temp directory to operate on
* @param $name The converter name
* @param $tempdir The temp directory to operate on
* @param base_logger|null if the conversion should be logged, use this logger
* @return base_converter
*/
public static function get_converter($name, $tempdir) {
public static function get_converter($name, $tempdir, $logger = null) {
global $CFG;
$name = clean_param($name, PARAM_SAFEDIR);
@ -53,6 +54,7 @@ abstract class convert_factory {
if (!class_exists($classname)) {
throw new coding_exception("Converter factory error: class not found $classname");
}
return new $classname($tempdir);
return new $classname($tempdir, $logger);
}
}

View File

@ -114,10 +114,11 @@ abstract class convert_helper {
*
* @param string $tempdir The directory to convert
* @param string $format The current format, if already detected
* @param base_logger|null if the conversion should be logged, use this logger
* @throws convert_helper_exception
* @return bool false if unable to find the conversion path, true otherwise
*/
public static function to_moodle2_format($tempdir, $format = null) {
public static function to_moodle2_format($tempdir, $format = null, $logger = null) {
if (is_null($format)) {
$format = backup_general_helper::detect_backup_format($tempdir);
@ -131,6 +132,9 @@ abstract class convert_helper {
if (!class_exists($classname)) {
throw new convert_helper_exception('class_not_loaded', $classname);
}
if ($logger instanceof base_logger) {
backup_helper::log('available converter', backup::LOG_DEBUG, $classname, 1, false, $logger);
}
$descriptions[$name] = call_user_func($classname .'::description');
}
@ -138,12 +142,22 @@ abstract class convert_helper {
$path = self::choose_conversion_path($format, $descriptions);
if (empty($path)) {
// unable to convert
if ($logger instanceof base_logger) {
backup_helper::log('unable to find the conversion path', backup::LOG_ERROR, null, 0, false, $logger);
}
return false;
}
if ($logger instanceof base_logger) {
backup_helper::log('conversion path established', backup::LOG_INFO,
implode(' => ', array_merge($path, array('moodle2'))), 0, false, $logger);
}
foreach ($path as $name) {
$converter = convert_factory::get_converter($name, $tempdir);
if ($logger instanceof base_logger) {
backup_helper::log('running converter', backup::LOG_INFO, $name, 0, false, $logger);
}
$converter = convert_factory::get_converter($name, $tempdir, $logger);
$converter->convert();
}

View File

@ -26,6 +26,7 @@
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/backup/util/interfaces/loggable.class.php'); // converters are loggable
require_once($CFG->dirroot . '/backup/util/interfaces/checksumable.class.php'); // req by backup.class.php
require_once($CFG->dirroot . '/backup/backup.class.php'); // provides backup::FORMAT_xxx constants
require_once($CFG->dirroot . '/backup/util/helper/convert_helper.class.php');

View File

@ -73,7 +73,7 @@ class moodle1_mod_imscp_handler extends moodle1_resource_successor_handler {
$this->fileman->itemid = 1;
$this->fileman->migrate_file('moddata/resource/'.$data['id'].'/'.$packagename);
} else {
// todo add to log
$this->log('missing imscp package', backup::LOG_WARNING, 'moddata/resource/'.$data['id'].'/'.$packagename);
}
}
@ -117,12 +117,12 @@ class moodle1_mod_imscp_handler extends moodle1_resource_successor_handler {
global $CFG;
if (!file_exists($manifestfilepath)) {
// todo add to conversion log
$this->log('missing imscp manifest file', backup::LOG_WARNING);
return null;
}
$manifestfilecontents = file_get_contents($manifestfilepath);
if (empty($manifestfilecontents)) {
// todo add to conversion log
$this->log('empty imscp manifest file', backup::LOG_WARNING);
return null;
}

View File

@ -106,7 +106,7 @@ class moodle1_mod_lesson_handler extends moodle1_mod_handler {
$this->fileman->migrate_file('course_files/'.$data['mediafile']);
} catch (moodle1_convert_exception $e) {
// the file probably does not exist
// todo add to log
$this->log('error migrating lesson mediafile', backup::LOG_WARNING, 'course_files/'.$data['mediafile']);
}
}

View File

@ -186,7 +186,7 @@ class moodle1_mod_resource_handler extends moodle1_mod_handler {
$this->fileman->migrate_file('course_files/'.$data['reference'], '/', null, 1);
} catch (moodle1_convert_exception $e) {
// the file probably does not exist
// todo add to log
$this->log('error migrating the resource main file', backup::LOG_WARNING, 'course_files/'.$data['reference']);
}
// write resource.xml
@ -258,6 +258,7 @@ class moodle1_mod_resource_handler extends moodle1_mod_handler {
}
if (!isset($this->successors[$name])) {
$this->log('preparing resource successor handler', backup::LOG_DEBUG, $name);
$class = 'moodle1_mod_'.$name.'_handler';
$this->successors[$name] = new $class($this->converter, 'mod', $name);