MDL-22145 backup storage - provide 'user_tohub' storage for HUB files

This commit is contained in:
Eloy Lafuente 2010-04-27 01:02:38 +00:00
parent 96449a1698
commit ce937f9957
11 changed files with 131 additions and 12 deletions

View file

@ -98,7 +98,7 @@ abstract class backup implements checksumable {
/* /*
* Exception class used by all the @backup stuff * Exception class used by all the @backup stuff
*/ */
class backup_exception extends moodle_exception { abstract class backup_exception extends moodle_exception {
public function __construct($errorcode, $a=NULL, $debuginfo=null) { public function __construct($errorcode, $a=NULL, $debuginfo=null) {
parent::__construct($errorcode, 'error', '', $a, null, $debuginfo); parent::__construct($errorcode, 'error', '', $a, null, $debuginfo);

View file

@ -254,6 +254,10 @@ class backup_controller extends backup implements loggable {
return $this->plan->execute(); return $this->plan->execute();
} }
public function get_results() {
return $this->plan->get_results();
}
public function log($message, $level, $a = null, $depth = null, $display = false) { public function log($message, $level, $a = null, $depth = null, $display = false) {
backup_helper::log($message, $level, $a, $depth, $display, $this->logger); backup_helper::log($message, $level, $a, $depth, $display, $this->logger);
} }

View file

@ -84,6 +84,12 @@ class backup_final_task extends backup_task {
// to the backup, settings, license, versions and other useful information // to the backup, settings, license, versions and other useful information
$this->add_step(new backup_main_structure_step('mainfile', 'moodle_backup.xml')); $this->add_step(new backup_main_structure_step('mainfile', 'moodle_backup.xml'));
// Generate the zip file
$this->add_step(new backup_zip_contents('zip_contents'));
// Copy the generated zip file to final destination
$this->add_step(new backup_store_backup_file('save_backupfile'));
$this->built = true; $this->built = true;
} }

View file

@ -1049,6 +1049,59 @@ class backup_main_structure_step extends backup_structure_step {
} }
/**
* Execution step that will generate the final zip file with all the contents
*/
class backup_zip_contents extends backup_execution_step {
protected function define_execution() {
// Get basepath
$basepath = $this->get_basepath();
// Get the list of files in directory
$filestemp = get_directory_list($basepath, '', false, true, true);
$files = array();
foreach ($filestemp as $file) { // Add zip paths and fs paths to all them
$files[$file] = $basepath . '/' . $file;
}
// Add the log file if exists
$logfilepath = $basepath . '.log';
if (file_exists($logfilepath)) {
$files['moodle_backup.log'] = $logfilepath;
}
// Calculate the zip fullpath
$zipfile = $basepath . '/' . $this->get_setting_value('filename');
// Get the zip packer
$zippacker = get_file_packer('application/zip');
// Zip files
$zippacker->archive_to_pathname($files, $zipfile);
}
}
/**
* This step will send the generated backup file to its final destination
*/
class backup_store_backup_file extends backup_execution_step {
protected function define_execution() {
// Get basepath
$basepath = $this->get_basepath();
// Calculate the zip fullpath
$zipfile = $basepath . '/' . $this->get_setting_value('filename');
// Perform storage and return it (TODO: shouldn't be array but proper result object)
return array('backup_destination' => backup_helper::store_backup_file($this->get_backupid(), $zipfile));
}
}
/** /**
* This step will search for all the activity (not calculations, categories nor aggregations) grade items * This step will search for all the activity (not calculations, categories nor aggregations) grade items
* and put them to the backup_ids tables, to be used later as base to backup them * and put them to the backup_ids tables, to be used later as base to backup them

View file

@ -178,7 +178,7 @@ abstract class backup_controller_dbops extends backup_dbops {
'activity' => $prefix, 'activity' => $prefix,
'name' => $setting->get_name(), 'name' => $setting->get_name(),
'value' => $setting->get_value()); 'value' => $setting->get_value());
$settingsinfo[] = (object)$settinginfo; $settingsinfo[$setting->get_name()] = (object)$settinginfo;
} }
return array($contentinfo, $settingsinfo); return array($contentinfo, $settingsinfo);
} }
@ -212,7 +212,7 @@ abstract class backup_controller_dbops extends backup_dbops {
'section ' => $prefix, 'section ' => $prefix,
'name' => $setting->get_name(), 'name' => $setting->get_name(),
'value' => $setting->get_value()); 'value' => $setting->get_value());
$settingsinfo[] = (object)$settinginfo; $settingsinfo[$setting->get_name()] = (object)$settinginfo;
} }
return array($contentinfo, $settingsinfo); return array($contentinfo, $settingsinfo);
} }
@ -245,7 +245,7 @@ abstract class backup_controller_dbops extends backup_dbops {
'level' => 'course', 'level' => 'course',
'name' => $setting->get_name(), 'name' => $setting->get_name(),
'value' => $setting->get_value()); 'value' => $setting->get_value());
$settingsinfo[] = (object)$settinginfo; $settingsinfo[$setting->get_name()] = (object)$settinginfo;
} }
return array($contentinfo, $settingsinfo); return array($contentinfo, $settingsinfo);
} }
@ -267,7 +267,7 @@ abstract class backup_controller_dbops extends backup_dbops {
'level' => 'root', 'level' => 'root',
'name' => $setting->get_name(), 'name' => $setting->get_name(),
'value' => $setting->get_value()); 'value' => $setting->get_value());
$settingsinfo[] = (object)$settinginfo; $settingsinfo[$setting->get_name()] = (object)$settinginfo;
} }
return array(null, $settingsinfo); return array(null, $settingsinfo);
} }
@ -291,6 +291,7 @@ abstract class backup_controller_dbops extends backup_dbops {
$detailsinfo['mode'] = $bc->get_mode(); $detailsinfo['mode'] = $bc->get_mode();
$detailsinfo['execution'] = $bc->get_execution(); $detailsinfo['execution'] = $bc->get_execution();
$detailsinfo['executiontime'] = $bc->get_executiontime(); $detailsinfo['executiontime'] = $bc->get_executiontime();
$detailsinfo['userid'] = $bc->get_userid();
// Init content placeholders // Init content placeholders

View file

@ -60,7 +60,7 @@ abstract class backup_factory {
// Create file_logger, observing $CFG->backup_file_logger_level // Create file_logger, observing $CFG->backup_file_logger_level
check_dir_exists($CFG->dataroot . '/temp/backup', true, true); // need to ensure that temp/backup already exists check_dir_exists($CFG->dataroot . '/temp/backup', true, true); // need to ensure that temp/backup already exists
$fllevel = isset($CFG->backup_file_logger_level) ? $CFG->backup_file_logger_level : $dfltloglevel; $fllevel = isset($CFG->backup_file_logger_level) ? $CFG->backup_file_logger_level : $dfltloglevel;
$enabledloggers[] = new file_logger($fllevel, true, true, $CFG->dataroot . '/temp/backup/' . $backupid . '.log.html'); $enabledloggers[] = new file_logger($fllevel, true, true, $CFG->dataroot . '/temp/backup/' . $backupid . '.log');
// Create database_logger, observing $CFG->backup_database_logger_level and defaulting to LOG_WARNING // Create database_logger, observing $CFG->backup_database_logger_level and defaulting to LOG_WARNING
// and pointing to the backup_logs table // and pointing to the backup_logs table

View file

@ -163,6 +163,44 @@ abstract class backup_helper {
output_controller::get_instance()->output($message, 'backup', $a, $depth); output_controller::get_instance()->output($message, 'backup', $a, $depth);
} }
} }
/**
* Given one backupid and the (FS) final generated file, perform its final storage
* into Moodle file storage
*/
static public function store_backup_file($backupid, $filepath) {
// First of all, get some information from the backup_controller to help us decide
list($dinfo, $cinfo, $sinfo) = backup_controller_dbops::get_moodle_backup_information($backupid);
// Extract useful information to decide
$hasusers = (bool)$sinfo['users']->value; // Backup has users
$isannon = (bool)$sinfo['anonymize']->value; // Backup is annonymzed
$backupmode= $dinfo[0]->mode; // Backup mode backup::MODE_GENERAL/IMPORT/HUB
$userid = $dinfo[0]->userid; // User->id executing the backup
// Backups of type IMPORT aren't stored ever
if ($backupmode == backup::MODE_IMPORT) {
return true;
}
// Backups of type HUB (by definition never have user info)
// are sent to user's "user_tohub" file area. The upload process
// will be responsible for cleaning that filearea once finished
if ($backupmode == backup::MODE_HUB) {
$ctxid = get_context_instance(CONTEXT_USER, $userid)->id;
$fs = get_file_storage();
$fr = array(
'contextid' => $ctxid,
'filearea' => 'user_tohub',
'itemid' => 0,
'filepath' => '/',
'filename' => basename($filepath),
'timecreated' => time(),
'timemodified'=> time());
return $fs->create_file_from_pathname($fr, $filepath);
}
}
} }
/* /*

View file

@ -31,7 +31,7 @@ abstract class backup_execution_step extends backup_step {
public function execute() { public function execute() {
// Simple, for now // Simple, for now
$this->define_execution(); return $this->define_execution();
} }
// Protected API starts here // Protected API starts here

View file

@ -32,6 +32,7 @@ abstract class base_plan implements checksumable, executable {
protected $name; // One simple name for identification purposes protected $name; // One simple name for identification purposes
protected $settings; // One array of (accumulated from tasks) base_setting elements protected $settings; // One array of (accumulated from tasks) base_setting elements
protected $tasks; // One array of base_task elements protected $tasks; // One array of base_task elements
protected $results; // One array of results received from tasks
protected $built; // Flag to know if one plan has been built protected $built; // Flag to know if one plan has been built
@ -42,6 +43,7 @@ abstract class base_plan implements checksumable, executable {
$this->name = $name; $this->name = $name;
$this->settings = array(); $this->settings = array();
$this->tasks = array(); $this->tasks = array();
$this->results = array();
$this->built = false; $this->built = false;
} }
@ -68,6 +70,14 @@ abstract class base_plan implements checksumable, executable {
return $this->tasks; return $this->tasks;
} }
public function add_result($result) {
$this->results = array_merge($this->results, $result);
}
public function get_results() {
return $this->results;
}
public function get_settings() { public function get_settings() {
return $this->settings; return $this->settings;
} }

View file

@ -144,7 +144,12 @@ abstract class base_task implements checksumable, executable, loggable {
throw new base_task_exception('base_task_not_built', $this->name); throw new base_task_exception('base_task_not_built', $this->name);
} }
foreach ($this->steps as $step) { foreach ($this->steps as $step) {
$step->execute(); $result = $step->execute();
// If step returns array, it will be forwarded to plan
// (TODO: shouldn't be array but proper result object)
if (is_array($result) and !empty($result)) {
$this->plan->add_result($result);
}
} }
} }

View file

@ -52,9 +52,10 @@ abstract class base_setting {
const HIDDEN = 0; const HIDDEN = 0;
// Editable/locked (by different causes) // Editable/locked (by different causes)
const NOT_LOCKED = 5; const NOT_LOCKED = 3;
const LOCKED_BY_PERMISSION = 6; const LOCKED_BY_CONFIG = 5;
const LOCKED_BY_HIERARCHY = 7; const LOCKED_BY_HIERARCHY = 7;
const LOCKED_BY_PERMISSION = 9;
// Type of change to inform dependencies // Type of change to inform dependencies
const CHANGED_VALUE = 1; const CHANGED_VALUE = 1;
@ -237,8 +238,9 @@ abstract class base_setting {
if (is_null($status)) { if (is_null($status)) {
$status = self::NOT_LOCKED; $status = self::NOT_LOCKED;
} }
if ($status !== self::NOT_LOCKED && $status !== self::LOCKED_BY_PERMISSION && $status !== self::LOCKED_BY_HIERARCHY) { if ($status !== self::NOT_LOCKED && $status !== self::LOCKED_BY_CONFIG &&
throw new base_setting_exception('setting_invalid_status'); $status !== self::LOCKED_BY_PERMISSION && $status !== self::LOCKED_BY_HIERARCHY) {
throw new base_setting_exception('setting_invalid_status', $status);
} }
return $status; return $status;
} }