Skip to content

Commit

Permalink
The first attempt to include backup conversion in the restore process
Browse files Browse the repository at this point in the history
With this initial implementation, we do not display any information
about the backup contents yet. The non-standard backup file is just
silently converted at the beginning of the settings stage, as soon as
the restore controller is available.

In the future we will probably want to display the information about the
contents of the converted file as if we were restoring from standard
MBZ format. However this includes more work in the restore UI machinery
and I leave it open for now.
  • Loading branch information
mudrd8mz committed May 17, 2011
1 parent 3a07672 commit f666f14
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 78 deletions.
8 changes: 7 additions & 1 deletion backup/restore.php
Expand Up @@ -5,7 +5,7 @@
require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');

$contextid = required_param('contextid', PARAM_INT);
$stage = optional_param('stage', restore_ui::STAGE_CONFIRM, PARAM_INT);
$stage = optional_param('stage', restore_ui::STAGE_CONFIRM, PARAM_INT);

list($context, $course, $cm) = get_context_info_array($contextid);

Expand All @@ -30,9 +30,15 @@
}
}
if ($rc) {
// check if the format conversion must happen first
if ($rc->get_status() == backup::STATUS_REQUIRE_CONV) {
$rc->convert();
}

$restore = new restore_ui($rc, array('contextid'=>$context->id));
}
}

$outcome = $restore->process();
if (!$restore->is_independent()) {
if ($restore->get_stage() == restore_ui::STAGE_PROCESS && !$restore->requires_substage()) {
Expand Down
60 changes: 43 additions & 17 deletions backup/util/ui/renderer.php
Expand Up @@ -157,6 +157,49 @@ public function backup_details($details, $nextstageurl) {
return $html;
}

/**
* Displays the general information about a backup file with non-standard format
*
* @param string $format the name of the format
* @param moodle_url $nextstageurl URL to send user to
* @param array $details not supported yet
* @return string HTML code to display
*/
public function backup_details_nonstandard($format, $nextstageurl, array $details = array()) {

$formatname = get_string('backupformat'.$format, 'backup');

$html = html_writer::start_tag('div', array('class' => 'backup-restore nonstandardformat'));
$html .= html_writer::start_tag('div', array('class' => 'backup-section'));
$html .= $this->output->heading(get_string('backupdetails', 'backup'), 2, 'header');
$html .= $this->backup_detail_pair(
get_string('backupformat', 'backup'),
get_string('backupdetailsnonstandardinfo', 'backup', get_string('backupformat'.$format, 'backup'))
);
$html .= html_writer::end_tag('div');
$html .= $this->output->single_button($nextstageurl, get_string('continue'), 'post');
$html .= html_writer::end_tag('div');

return $html;
}

/**
* Displays the general information about a backup file with unknown format
*
* @param moodle_url $nextstageurl URL to send user to
* @return string HTML code to display
*/
public function backup_details_unknown(moodle_url $nextstageurl) {

$html = html_writer::start_tag('div', array('class' => 'unknownformat'));
$html .= $this->output->heading(get_string('errorinvalidformat', 'backup'), 2, 'notifyproblem');
$html .= html_writer::tag('div', get_string('errorinvalidformatinfo', 'backup'), array('class' => 'notifyproblem'));
$html .= $this->output->single_button($nextstageurl, get_string('continue'), 'post');
$html .= html_writer::end_tag('div');

return $html;
}

/**
* Displays a course selector for restore
*
Expand Down Expand Up @@ -618,23 +661,6 @@ public function render_restore_category_search(restore_category_search $componen
$output .= html_writer::end_tag('div');
return $output;
}

public function invalid_format($format) {
$html = html_writer::start_tag('div', array('class'=>'invalidformat'));
$html .= html_writer::tag('h2', get_string('errorinvalidformat', 'backup'), array('class'=>'notifyproblem'));
if ($format == 'moodle1') {
// Moodle 1.x backups
$icon = $this->output->help_icon('errormoodle1format', 'backup');
$message = get_string('errormoodle1formatdesc', 'backup').' '.$icon;

} else {
// Totally unknown format
$message = get_string('errorinvalidformatdesc', 'backup');
}
$html .= html_writer::tag('div', $message, array('class'=>'notifyproblem'));
$html .= html_writer::end_tag('div');
return $html;
}
}

/**
Expand Down
158 changes: 105 additions & 53 deletions backup/util/ui/restore_ui_stage.class.php
@@ -1,6 +1,5 @@
<?php


// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -171,17 +170,38 @@ protected function extract_file_to_dir() {
$fb = get_file_packer();
return ($fb->extract_to_pathname("$CFG->dataroot/temp/backup/".$this->filename, "$CFG->dataroot/temp/backup/$this->filepath/"));
}

/**
* Renders the confirmation stage screen
*
* @param core_backup_renderer $renderer renderer instance to use
* @return string HTML code
*/
public function display($renderer) {

// TODO: Remove this when backup formats are better supported
$prevstageurl = new moodle_url('/backup/restorefile.php', array('contextid' => $this->contextid));
$nextstageurl = new moodle_url('/backup/restore.php', array(
'contextid' => $this->contextid,
'filepath' => $this->filepath,
'stage' => restore_ui::STAGE_DESTINATION));

$format = backup_general_helper::detect_backup_format($this->filepath);
if ($format !== 'moodle2') {
return $renderer->invalid_format($format);
}

$this->details = backup_general_helper::get_backup_information($this->filepath);
return $renderer->backup_details($this->details, new moodle_url('/backup/restore.php', array('contextid'=>$this->contextid, 'filepath'=>$this->filepath, 'stage'=>restore_ui::STAGE_DESTINATION)));
if ($format === backup::FORMAT_UNKNOWN) {
// unknown format - we can't do anything here
return $renderer->backup_details_unknown($prevstageurl);

} else if ($format !== backup::FORMAT_MOODLE) {
// non-standard format to be converted
return $renderer->backup_details_nonstandard($format, $nextstageurl);

} else {
// standard MBZ backup, let us get information from it and display
$this->details = backup_general_helper::get_backup_information($this->filepath);
return $renderer->backup_details($this->details, $nextstageurl);
}
}

public function get_stage_name() {
return get_string('restorestage'.restore_ui::STAGE_CONFIRM, 'backup');
}
Expand All @@ -198,7 +218,6 @@ public function get_stage() {
class restore_ui_stage_destination extends restore_ui_independent_stage {
protected $contextid;
protected $filepath = null;
protected $details;
protected $courseid = null;
protected $target = backup::TARGET_NEW_COURSE;
protected $coursesearch = null;
Expand Down Expand Up @@ -235,29 +254,48 @@ public function process() {
}
return false;
}

/**
* Renders the destination stage screen
*
* @global moodle_database $DB
* @param core_backup_renderer $renderer
* @return string
* @param core_backup_renderer $renderer renderer instance to use
* @return string HTML code
*/
public function display($renderer) {
global $DB, $USER, $PAGE;

$format = backup_general_helper::detect_backup_format($this->filepath);
if ($format !== 'moodle2') {
return $renderer->invalid_format($format);

if ($format === backup::FORMAT_MOODLE) {
// standard Moodle 2 format, let use get the type of the backup
$details = backup_general_helper::get_backup_information($this->filepath);
if ($details->type === backup::TYPE_1COURSE) {
$wholecourse = true;
} else {
$wholecourse = false;
}

} else {
// non-standard format to be converted. We assume it contains the
// whole course for now. However, in the future there might be a callback
// to the installed converters
$wholecourse = true;
}

$this->details = backup_general_helper::get_backup_information($this->filepath);
$url = new moodle_url('/backup/restore.php', array('contextid'=>$this->contextid, 'filepath'=>$this->filepath, 'stage'=>restore_ui::STAGE_SETTINGS));

$nextstageurl = new moodle_url('/backup/restore.php', array(
'contextid' => $this->contextid,
'filepath' => $this->filepath,
'stage' => restore_ui::STAGE_SETTINGS));
$context = get_context_instance_by_id($this->contextid);
$currentcourse = ($context->contextlevel == CONTEXT_COURSE && has_capability('moodle/restore:restorecourse', $context))?$context->instanceid:false;

$html = $renderer->course_selector($url, $this->details, $this->categorysearch, $this->coursesearch, $currentcourse);
return $html;
if ($context->contextlevel == CONTEXT_COURSE and has_capability('moodle/restore:restorecourse', $context)) {
$currentcourse = $context->instanceid;
} else {
$currentcourse = false;
}

return $renderer->course_selector($nextstageurl, $wholecourse, $this->categorysearch, $this->coursesearch, $currentcourse);
}

public function get_stage_name() {
return get_string('restorestage'.restore_ui::STAGE_DESTINATION, 'backup');
}
Expand Down Expand Up @@ -564,7 +602,6 @@ protected function initialise_stage_form() {
class restore_ui_stage_process extends restore_ui_stage {

const SUBSTAGE_NONE = 0;
const SUBSTAGE_CONVERT = 1;
const SUBSTAGE_PRECHECKS = 2;

protected $substage = 0;
Expand Down Expand Up @@ -592,20 +629,16 @@ public function process(base_moodleform $form=null) {

// First decide whether a substage is needed
$rc = $this->ui->get_controller();
if ($rc->get_status() == backup::STATUS_REQUIRE_CONV) {
$this->substage = self::SUBSTAGE_CONVERT;
} else {
if ($rc->get_status() == backup::STATUS_SETTING_UI) {
$rc->finish_ui();
if ($rc->get_status() == backup::STATUS_SETTING_UI) {
$rc->finish_ui();
}
if ($rc->get_status() == backup::STATUS_NEED_PRECHECK) {
if (!$rc->precheck_executed()) {
$rc->execute_precheck(true);
}
if ($rc->get_status() == backup::STATUS_NEED_PRECHECK) {
if (!$rc->precheck_executed()) {
$rc->execute_precheck(true);
}
$results = $rc->get_precheck_results();
if (!empty($results)) {
$this->substage = self::SUBSTAGE_PRECHECKS;
}
$results = $rc->get_precheck_results();
if (!empty($results)) {
$this->substage = self::SUBSTAGE_PRECHECKS;
}
}

Expand Down Expand Up @@ -635,37 +668,52 @@ public function process(base_moodleform $form=null) {
protected function initialise_stage_form() {
throw new backup_ui_exception('backup_ui_must_execute_first');
}

/**
* should NEVER be called... throws an exception
* Renders the process stage screen
*
* @param core_backup_renderer $renderer renderer instance to use
* @return string HTML code
*/
public function display($renderer) {
global $PAGE;

$html = '';
$haserrors = false;
$url = new moodle_url($PAGE->url, array('restore'=>$this->get_uniqueid(), 'stage'=>restore_ui::STAGE_PROCESS, 'substage'=>$this->substage, 'sesskey'=>sesskey()));
echo html_writer::start_tag('form', array('action'=>$url->out_omit_querystring(), 'class'=>'backup-restore', 'method'=>'post'));
foreach ($url->params() as $name=>$value) {
echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>$name, 'value'=>$value));
$url = new moodle_url($PAGE->url, array(
'restore' => $this->get_uniqueid(),
'stage' => restore_ui::STAGE_PROCESS,
'substage' => $this->substage,
'sesskey' => sesskey()));
$html .= html_writer::start_tag('form', array(
'action' => $url->out_omit_querystring(),
'class' => 'backup-restore',
'method' => 'post'));
foreach ($url->params() as $name => $value) {
$html .= html_writer::empty_tag('input', array(
'type' => 'hidden',
'name' => $name,
'value' => $value));
}
switch ($this->substage) {
case self::SUBSTAGE_CONVERT :
echo '<h2>Need to show the conversion screens here</h2>';
break;
case self::SUBSTAGE_PRECHECKS :
$results = $this->ui->get_controller()->get_precheck_results();
$info = $this->ui->get_controller()->get_info();
$haserrors = (!empty($results['errors']));
echo $renderer->precheck_notices($results);
$html .= $renderer->precheck_notices($results);
if (!empty($info->role_mappings->mappings)) {
$context = get_context_instance(CONTEXT_COURSE, $this->ui->get_controller()->get_courseid());
$assignableroles = get_assignable_roles($context, ROLENAME_ALIAS, false);
echo $renderer->role_mappings($info->role_mappings->mappings, $assignableroles);
$html .= $renderer->role_mappings($info->role_mappings->mappings, $assignableroles);
}
break;
default:
throw new restore_ui_exception('backup_ui_must_execute_first');
}
echo $renderer->substage_buttons($haserrors);
echo html_writer::end_tag('form');
$html .= $renderer->substage_buttons($haserrors);
$html .= html_writer::end_tag('form');

return $html;
}

public function has_sub_stages() {
Expand Down Expand Up @@ -695,20 +743,24 @@ public function __construct(restore_ui $ui, array $params=null, array $results=n
parent::__construct($ui, $params);
$this->stage = restore_ui::STAGE_COMPLETE;
}

/**
* Displays the completed backup stage.
*
* Currently this just envolves redirecting to the file browser with an
* appropriate message.
*
* @global core_renderer $OUTPUT
* @param core_backup_renderer $renderer
*/
public function display(core_backup_renderer $renderer) {
global $OUTPUT;
echo $OUTPUT->box_start();
echo $OUTPUT->notification(get_string('restoreexecutionsuccess', 'backup'), 'notifysuccess');
echo $renderer->continue_button(new moodle_url('/course/view.php', array('id'=>$this->get_ui()->get_controller()->get_courseid())), 'get');
echo $OUTPUT->box_end();

$html = '';
$html .= $renderer->box_start();
$html .= $renderer->notification(get_string('restoreexecutionsuccess', 'backup'), 'notifysuccess');
$html .= $renderer->continue_button(new moodle_url('/course/view.php', array(
'id' => $this->get_ui()->get_controller()->get_courseid())), 'get');
$html .= $renderer->box_end();

return $html;
}
}
}
17 changes: 10 additions & 7 deletions lang/en/backup.php
Expand Up @@ -42,11 +42,19 @@
$string['backupcoursesections'] = 'Course sections';
$string['backupdate'] = 'Date taken';
$string['backupdetails'] = 'Backup details';
$string['backupdetailsnonstandardinfo'] = 'The selected file is not a standard Moodle backup file. The format "{$a}" has been detected. The restore process will try to convert the backup file into the standard format and then restore it.';
$string['backupformat'] = 'Format';
$string['backupformatmoodle1'] = 'Moodle 1';
$string['backupformatmoodle2'] = 'Moodle 2';
$string['backupformatimscc'] = 'IMS Common Cartridge';
$string['backupformatunknown'] = 'Unknown format';
$string['backupmode'] = 'Mode';
$string['backupmode10'] = 'General';
$string['backupmode20'] = 'Import';
$string['backupmode30'] = 'Hub';
$string['backupmode40'] = 'Same site';
$string['backupmode50'] = 'Automated';
$string['backupmode60'] = 'Converted';
$string['backupsection'] = 'Backup course section: {$a}';
$string['backupsettings'] = 'Backup settings';
$string['backupsitedetails'] = 'Site details';
Expand Down Expand Up @@ -99,13 +107,8 @@
$string['errorfilenamemustbezip'] = 'The filename you enter must be a ZIP file and have the .mbz extension';
$string['errorminbackup20version'] = 'This backup file has been created with one development version of Moodle backup ({$a->backup}). Minimum required is {$a->min}. Cannot be restored.';
$string['errorrestorefrontpage'] = 'Restoring over front page is not allowed.';
$string['errorinvalidformat'] = 'Invalid backup format.';
$string['errorinvalidformatdesc'] = 'The uploaded file is not a valid Moodle backup file and could not be restored.';
$string['errormoodle1formatdesc'] = 'The backup file was created with Moodle 1.x and can not currently be restored in Moodle 2. This functionality is coming in a future update.';
$string['errormoodle1format'] = 'Restoring Moodle 1.9 backups';
$string['errormoodle1format_help'] = 'Moodle 2 currently doesn\'t support restoring Moodle 1.x backups.
A temporary work around to this is to restore your Moodle 1.x backup onto a Moodle 1.9 site, and then upgrade it to Moodle 2.
Once the upgrade is complete you will be able to make new backups which will be restorable on other Moodle 2.0 sites.';
$string['errorinvalidformat'] = 'Unknown backup format';
$string['errorinvalidformatinfo'] = 'The selected file is not a valid Moodle backup file and can\'t be restored.';
$string['executionsuccess'] = 'The backup file was successfully created.';
$string['filename'] = 'Filename';
$string['generalactivities'] = 'Include activities';
Expand Down

0 comments on commit f666f14

Please sign in to comment.