From 2a64b641e6075ad72b6f58afa8fd0a8975187842 Mon Sep 17 00:00:00 2001 From: Frederic Massart Date: Wed, 18 May 2016 18:01:17 +0800 Subject: [PATCH] MDL-54567 backup: Process the calculations_freeze item upon restore --- backup/moodle2/backup_stepslib.php | 12 +++-- backup/moodle2/restore_stepslib.php | 98 ++++++++++++++++++++++++++++++++++++- 2 files changed, 104 insertions(+), 6 deletions(-) diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php index da219a1c0bd..ac786ede365 100644 --- a/backup/moodle2/backup_stepslib.php +++ b/backup/moodle2/backup_stepslib.php @@ -950,8 +950,11 @@ class backup_gradebook_structure_step extends backup_structure_step { $grade_setting = new backup_nested_element('grade_setting', 'id', array( 'name', 'value')); + $gradebook_attributes = new backup_nested_element('attributes', null, array('calculations_freeze')); // Build the tree + $gradebook->add_child($gradebook_attributes); + $gradebook->add_child($grade_categories); $grade_categories->add_child($grade_category); @@ -966,14 +969,15 @@ class backup_gradebook_structure_step extends backup_structure_step { $gradebook->add_child($grade_settings); $grade_settings->add_child($grade_setting); + // Define sources + // Add attribute with gradebook calculation freeze date if needed. + $attributes = new stdClass(); $gradebookcalculationfreeze = get_config('core', 'gradebook_calculations_freeze_' . $this->get_courseid()); if ($gradebookcalculationfreeze) { - $gradebook->add_attributes(array('calculations_freeze')); - $gradebook->get_attribute('calculations_freeze')->set_value($gradebookcalculationfreeze); + $attributes->calculations_freeze = $gradebookcalculationfreeze; } - - // Define sources + $gradebook_attributes->set_source_array([$attributes]); //Include manual, category and the course grade item $grade_items_sql ="SELECT * FROM {grade_items} diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 158249b3d1a..e7e1ee29f6b 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -121,6 +121,21 @@ class restore_gradebook_structure_step extends restore_structure_step { return false; } + // Identify the backup we're dealing with. + $backuprelease = floatval($this->get_task()->get_info()->backup_release); // The major version: 2.9, 3.0, ... + $backupbuild = 0; + preg_match('/(\d{8})/', $this->get_task()->get_info()->moodle_release, $matches); + if (!empty($matches[1])) { + $backupbuild = (int) $matches[1]; // The date of Moodle build at the time of the backup. + } + + // On older versions the freeze value has to be converted. + // We do this from here as it is happening right before the file is read. + // This only targets the backup files that can contain the legacy freeze. + if ($backupbuild > 20150618 && ($backuprelease < 3.0 || $backupbuild < 20160527)) { + $this->rewrite_step_backup_file_for_legacy_freeze($fullpath); + } + // Arrived here, execute the step return true; } @@ -129,7 +144,7 @@ class restore_gradebook_structure_step extends restore_structure_step { $paths = array(); $userinfo = $this->task->get_setting_value('users'); - $paths[] = new restore_path_element('gradebook', '/gradebook'); + $paths[] = new restore_path_element('attributes', '/gradebook/attributes'); $paths[] = new restore_path_element('grade_category', '/gradebook/grade_categories/grade_category'); $paths[] = new restore_path_element('grade_item', '/gradebook/grade_items/grade_item'); if ($userinfo) { @@ -141,7 +156,7 @@ class restore_gradebook_structure_step extends restore_structure_step { return $paths; } - protected function process_gradebook($data) { + protected function process_attributes($data) { // For non-merge restore types: // Unset 'gradebook_calculations_freeze_' in the course and replace with the one from the backup. $target = $this->get_task()->get_target(); @@ -581,6 +596,85 @@ class restore_gradebook_structure_step extends restore_structure_step { } } } + + /** + * Rewrite step definition to handle the legacy freeze attribute. + * + * In previous backups the calculations_freeze property was stored as an attribute of the + * top level node . The backup API, however, do not process grandparent nodes. + * It only processes definitive children, and their parent attributes. + * + * We had: + * + * + * + * + * 1 + * ... + * + * + * ... + * + * + * And this method will convert it to: + * + * + * + * 20160511 + * + * + * + * 1 + * ... + * + * + * ... + * + * + * Note that we cannot just load the XML file in memory as it could potentially be huge. + * We can also completely ignore if the node is already in the backup + * file as it never existed before. + * + * @param string $filepath The absolute path to the XML file. + * @return void + */ + protected function rewrite_step_backup_file_for_legacy_freeze($filepath) { + $foundnode = false; + $newfile = make_request_directory(true) . DIRECTORY_SEPARATOR . 'file.xml'; + $fr = fopen($filepath, 'r'); + $fw = fopen($newfile, 'w'); + if ($fr && $fw) { + while (($line = fgets($fr, 4096)) !== false) { + if (!$foundnode && strpos($line, '