diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php index e2f47f6498c..9437714206f 100644 --- a/backup/moodle2/backup_stepslib.php +++ b/backup/moodle2/backup_stepslib.php @@ -1499,10 +1499,16 @@ class move_inforef_annotations_to_final extends backup_execution_step { // Items we want to include in the inforef file $items = backup_helper::get_inforef_itemnames(); + $progress = $this->task->get_progress(); + $progress->start_progress($this->get_name(), count($items)); + $done = 1; foreach ($items as $itemname) { // Delegate to dbops - backup_structure_dbops::move_annotations_to_final($this->get_backupid(), $itemname); + backup_structure_dbops::move_annotations_to_final($this->get_backupid(), + $itemname, $progress); + $progress->progress($done++); } + $progress->end_progress(); } } @@ -1667,7 +1673,11 @@ class backup_main_structure_step extends backup_structure_step { /** * Execution step that will generate the final zip (.mbz) file with all the contents */ -class backup_zip_contents extends backup_execution_step { +class backup_zip_contents extends backup_execution_step implements file_progress { + /** + * @var bool True if we have started tracking progress + */ + protected $startedprogress; protected function define_execution() { @@ -1694,8 +1704,34 @@ class backup_zip_contents extends backup_execution_step { $zippacker = get_file_packer('application/zip'); // Zip files - $zippacker->archive_to_pathname($files, $zipfile); + $zippacker->archive_to_pathname($files, $zipfile, true, $this); + + // If any progress happened, end it. + if ($this->startedprogress) { + $this->task->get_progress()->end_progress(); + } } + + /** + * Implementation for file_progress interface to display unzip progress. + * + * @param int $progress Current progress + * @param int $max Max value + */ + public function progress($progress = file_progress::INDETERMINATE, $max = file_progress::INDETERMINATE) { + $reporter = $this->task->get_progress(); + + // Start tracking progress if necessary. + if (!$this->startedprogress) { + $reporter->start_progress('extract_file_to_dir', ($max == file_progress::INDETERMINATE) + ? core_backup_progress::INDETERMINATE : $max); + $this->startedprogress = true; + } + + // Pass progress through to whatever handles it. + $reporter->progress(($progress == file_progress::INDETERMINATE) + ? core_backup_progress::INDETERMINATE : $progress); + } } /** @@ -1955,6 +1991,8 @@ class backup_annotate_all_user_files extends backup_execution_step { // Fetch all annotated (final) users $rs = $DB->get_recordset('backup_ids_temp', array( 'backupid' => $this->get_backupid(), 'itemname' => 'userfinal')); + $progress = $this->task->get_progress(); + $progress->start_progress($this->get_name()); foreach ($rs as $record) { $userid = $record->itemid; $userctx = context_user::instance($userid, IGNORE_MISSING); @@ -1966,8 +2004,10 @@ class backup_annotate_all_user_files extends backup_execution_step { // We don't need to specify itemid ($userid - 5th param) as far as by // context we can get all the associated files. See MDL-22092 backup_structure_dbops::annotate_files($this->get_backupid(), $userctx->id, 'user', $filearea, null); + $progress->progress(); } } + $progress->end_progress(); $rs->close(); } } diff --git a/backup/util/dbops/backup_structure_dbops.class.php b/backup/util/dbops/backup_structure_dbops.class.php index 29529f0b6b6..61a903a9919 100644 --- a/backup/util/dbops/backup_structure_dbops.class.php +++ b/backup/util/dbops/backup_structure_dbops.class.php @@ -130,10 +130,16 @@ abstract class backup_structure_dbops extends backup_dbops { /** * Moves all the existing 'item' annotations to their final 'itemfinal' ones * for a given backup. + * + * @param string $backupid Backup ID + * @param string $itemname Item name + * @param core_backup_progress $progress Progress tracker */ - public static function move_annotations_to_final($backupid, $itemname) { + public static function move_annotations_to_final($backupid, $itemname, core_backup_progress $progress) { global $DB; + $progress->start_progress('move_annotations_to_final'); $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $backupid, 'itemname' => $itemname)); + $progress->progress(); foreach($rs as $annotation) { // If corresponding 'itemfinal' annotation does not exist, update 'item' to 'itemfinal' if (! $DB->record_exists('backup_ids_temp', array('backupid' => $backupid, @@ -141,10 +147,12 @@ abstract class backup_structure_dbops extends backup_dbops { 'itemid' => $annotation->itemid))) { $DB->set_field('backup_ids_temp', 'itemname', $itemname . 'final', array('id' => $annotation->id)); } + $progress->progress(); } $rs->close(); // All the remaining $itemname annotations can be safely deleted $DB->delete_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => $itemname)); + $progress->end_progress(); } /** diff --git a/backup/util/plan/backup_structure_step.class.php b/backup/util/plan/backup_structure_step.class.php index 9c3d0e719fe..5ff5d086637 100644 --- a/backup/util/plan/backup_structure_step.class.php +++ b/backup/util/plan/backup_structure_step.class.php @@ -73,7 +73,9 @@ abstract class backup_structure_step extends backup_step { // from xml_writer (blame serialized data!) } $xw = new xml_writer($xo, $xt); - $pr = new backup_structure_processor($xw); + $progress = $this->task->get_progress(); + $progress->start_progress($this->get_name()); + $pr = new backup_structure_processor($xw, $progress); // Set processor variables from settings foreach ($this->get_settings() as $setting) { @@ -105,6 +107,7 @@ abstract class backup_structure_step extends backup_step { // Close everything $xw->stop(); + $progress->end_progress(); // Destroy the structure. It helps PHP 5.2 memory a lot! $structure->destroy(); diff --git a/backup/util/structure/backup_structure_processor.class.php b/backup/util/structure/backup_structure_processor.class.php index 3c648545dd9..88cfeca3cee 100644 --- a/backup/util/structure/backup_structure_processor.class.php +++ b/backup/util/structure/backup_structure_processor.class.php @@ -37,9 +37,21 @@ class backup_structure_processor extends base_processor { protected $writer; // xml_writer where the processor is going to output data protected $vars; // array of backup::VAR_XXX => helper value pairs to be used by source specifications - public function __construct(xml_writer $writer) { + /** + * @var core_backup_progress Progress tracker (null if none) + */ + protected $progress; + + /** + * Constructor. + * + * @param xml_writer $writer XML writer to save data + * @param core_backup_progress $progress Progress tracker (optional) + */ + public function __construct(xml_writer $writer, core_backup_progress $progress = null) { $this->writer = $writer; - $this->vars = array(); + $this->progress = $progress; + $this->vars = array(); } public function set_var($key, $value) { @@ -83,6 +95,9 @@ class backup_structure_processor extends base_processor { public function post_process_nested_element(base_nested_element $nested) { // Send close tag to xml_writer $this->writer->end_tag($nested->get_name()); + if ($this->progress) { + $this->progress->progress(); + } } public function process_final_element(base_final_element $final) { @@ -93,6 +108,9 @@ class backup_structure_processor extends base_processor { $attrarr[$attribute->get_name()] = $attribute->get_value(); } $this->writer->full_tag($final->get_name(), $final->get_value(), $attrarr); + if ($this->progress) { + $this->progress->progress(); + } // Annotate current value if configured to do so $final->annotate($this->get_var(backup::VAR_BACKUPID)); }