diff --git a/backup/restore.php b/backup/restore.php index a31501c75f7..6040d4b7639 100644 --- a/backup/restore.php +++ b/backup/restore.php @@ -43,7 +43,6 @@ if ($stage & restore_ui::STAGE_CONFIRM + restore_ui::STAGE_DESTINATION) { } } -$outcome = $restore->process(); $heading = $course->fullname; $PAGE->set_title($heading.': '.$restore->get_stage_name()); @@ -52,6 +51,15 @@ $PAGE->navbar->add($restore->get_stage_name()); $renderer = $PAGE->get_renderer('core','backup'); echo $OUTPUT->header(); + +// Prepare a progress bar which can display optionally during long-running +// operations while setting up the UI. +$slowprogress = new core_backup_display_progress_if_slow(); +// Depending on the code branch above, $restore may be a restore_ui or it may +// be a restore_ui_independent_stage. Either way, this function exists. +$restore->set_progress_reporter($slowprogress); +$outcome = $restore->process(); + if (!$restore->is_independent() && $restore->enforce_changed_dependencies()) { debugging('Your settings have been altered due to unmet dependencies', DEBUG_DEVELOPER); } diff --git a/backup/util/includes/restore_includes.php b/backup/util/includes/restore_includes.php index 78cd24be54f..c22faef4d5a 100644 --- a/backup/util/includes/restore_includes.php +++ b/backup/util/includes/restore_includes.php @@ -63,6 +63,7 @@ require_once($CFG->dirroot . '/backup/util/loggers/output_indented_logger.class. require_once($CFG->dirroot . '/backup/util/progress/core_backup_progress.class.php'); require_once($CFG->dirroot . '/backup/util/progress/core_backup_null_progress.class.php'); require_once($CFG->dirroot . '/backup/util/progress/core_backup_display_progress.class.php'); +require_once($CFG->dirroot . '/backup/util/progress/core_backup_display_progress_if_slow.class.php'); require_once($CFG->dirroot . '/backup/util/factories/backup_factory.class.php'); require_once($CFG->dirroot . '/backup/util/factories/restore_factory.class.php'); require_once($CFG->dirroot . '/backup/util/helper/backup_helper.class.php'); diff --git a/backup/util/progress/core_backup_display_progress.class.php b/backup/util/progress/core_backup_display_progress.class.php index 62696cb6bc9..f893b431053 100644 --- a/backup/util/progress/core_backup_display_progress.class.php +++ b/backup/util/progress/core_backup_display_progress.class.php @@ -95,6 +95,11 @@ class core_backup_display_progress extends core_backup_progress { echo html_writer::end_div(); } + /** + * When progress is updated, updates the bar. + * + * @see core_backup_progress::update_progress() + */ public function update_progress() { // If finished... if (!$this->is_in_progress_section()) { diff --git a/backup/util/progress/core_backup_display_progress_if_slow.class.php b/backup/util/progress/core_backup_display_progress_if_slow.class.php new file mode 100644 index 00000000000..ee9511e75ff --- /dev/null +++ b/backup/util/progress/core_backup_display_progress_if_slow.class.php @@ -0,0 +1,107 @@ +. + +/** + * Progress handler that uses a standard Moodle progress bar to display + * progress. Same as core_backup_display_progress, but the bar does not + * appear until a certain time has elapsed, and disappears automatically + * after it finishes. + * + * The bar can be re-used, i.e. if you end all sections it will disappear, + * but if you start all sections, a new bar will be output. + * + * @package core_backup + * @copyright 2013 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_backup_display_progress_if_slow extends core_backup_display_progress { + /** + * @var int Waits this many seconds before displaying progress bar + */ + const DEFAULT_DISPLAY_DELAY = 5; + + /** + * @var int Number in the next id to use + */ + private static $nextid = 1; + + /** + * @var string HTML id for containing div + */ + protected $id; + + /** + * @var int Time at which the progress bar should display (if it isn't yet) + */ + protected $starttime; + + /** + * Constructs the progress reporter. This will not output HTML just yet, + * until the required delay time expires. + * + * @param int $delay Delay time (default 5 seconds) + */ + public function __construct($delay = self::DEFAULT_DISPLAY_DELAY) { + // Set start time based on delay. + $this->starttime = time() + $delay; + parent::__construct(false); + } + + /** + * Adds a div around the parent display so it can be hidden. + * + * @see core_backup_display_progress::start_html() + */ + public function start_html() { + $this->id = 'core_backup_display_progress_if_slow' . self::$nextid; + self::$nextid++; + echo html_writer::start_div('', array('id' => $this->id)); + parent::start_html(); + } + + /** + * When progress is updated, after a certain time, starts actually displaying + * the progress bar. + * + * @see core_backup_progress::update_progress() + */ + public function update_progress() { + // If we haven't started yet, consider starting. + if ($this->starttime) { + if (time() > $this->starttime) { + $this->starttime = 0; + } else { + // Do nothing until start time. + return; + } + } + + // We have started, so handle as default. + parent::update_progress(); + } + + /** + * Finishes parent display then closes div and hides it. + * + * @see core_backup_display_progress::end_html() + */ + public function end_html() { + parent::end_html(); + echo html_writer::end_div(); + echo html_writer::script('document.getElementById("' . $this->id . + '").style.display = "none"'); + } +} diff --git a/backup/util/ui/restore_ui.class.php b/backup/util/ui/restore_ui.class.php index bf80a96f91b..251cbc17e07 100644 --- a/backup/util/ui/restore_ui.class.php +++ b/backup/util/ui/restore_ui.class.php @@ -50,6 +50,11 @@ class restore_ui extends base_ui { */ protected $stage = null; + /** + * @var core_backup_progress Progress indicator (where there is no controller) + */ + protected $progressreporter = null; + /** * String mappings to the above stages * @var array @@ -127,6 +132,38 @@ class restore_ui extends base_ui { public function get_restoreid() { return $this->controller->get_restoreid(); } + + /** + * Gets the progress reporter object in use for this restore UI. + * + * IMPORTANT: This progress reporter is used only for UI progress that is + * outside the restore controller. The restore controller has its own + * progress reporter which is used for progress during the main restore. + * Use the restore controller's progress reporter to report progress during + * a restore operation, not this one. + * + * This extra reporter is necessary because on some restore UI screens, + * there are long-running tasks even though there is no restore controller + * in use. + * + * @return core_backup_null_progress + */ + public function get_progress_reporter() { + if (!$this->progressreporter) { + $this->progressreporter = new core_backup_null_progress(); + } + return $this->progressreporter; + } + + /** + * Sets the progress reporter that will be returned by get_progress_reporter. + * + * @param core_backup_progress $progressreporter Progress reporter + */ + public function set_progress_reporter(core_backup_progress $progressreporter) { + $this->progressreporter = $progressreporter; + } + /** * Executes the restore plan * @return bool diff --git a/backup/util/ui/restore_ui_stage.class.php b/backup/util/ui/restore_ui_stage.class.php index a7464bf49ae..142b763494c 100644 --- a/backup/util/ui/restore_ui_stage.class.php +++ b/backup/util/ui/restore_ui_stage.class.php @@ -93,10 +93,48 @@ abstract class restore_ui_stage extends base_ui_stage { * no use for the restore controller. */ abstract class restore_ui_independent_stage { + /** + * @var core_backup_progress Optional progress reporter + */ + private $progressreporter; + abstract public function __construct($contextid); abstract public function process(); abstract public function display(core_backup_renderer $renderer); abstract public function get_stage(); + + /** + * Gets the progress reporter object in use for this restore UI stage. + * + * IMPORTANT: This progress reporter is used only for UI progress that is + * outside the restore controller. The restore controller has its own + * progress reporter which is used for progress during the main restore. + * Use the restore controller's progress reporter to report progress during + * a restore operation, not this one. + * + * This extra reporter is necessary because on some restore UI screens, + * there are long-running tasks even though there is no restore controller + * in use. There is a similar function in restore_ui. but that class is not + * used on some stages. + * + * @return core_backup_null_progress + */ + public function get_progress_reporter() { + if (!$this->progressreporter) { + $this->progressreporter = new core_backup_null_progress(); + } + return $this->progressreporter; + } + + /** + * Sets the progress reporter that will be returned by get_progress_reporter. + * + * @param core_backup_progress $progressreporter Progress reporter + */ + public function set_progress_reporter(core_backup_progress $progressreporter) { + $this->progressreporter = $progressreporter; + } + /** * Gets an array of progress bar items that can be displayed through the restore renderer. * @return array Array of items for the progress bar