Merge branch 'MDL-54567-30-build' of git://github.com/FMCorz/moodle into MOODLE_30_STABLE

This commit is contained in:
Andrew Nicols
2016-05-30 14:44:35 +08:00
11 changed files with 261 additions and 6 deletions
+8 -4
View File
@@ -930,8 +930,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);
@@ -946,14 +949,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}
+96 -2
View File
@@ -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 <gradebook>. The backup API, however, do not process grandparent nodes.
* It only processes definitive children, and their parent attributes.
*
* We had:
*
* <gradebook calculations_freeze="20160511">
* <grade_categories>
* <grade_category id="10">
* <depth>1</depth>
* ...
* </grade_category>
* </grade_categories>
* ...
* </gradebook>
*
* And this method will convert it to:
*
* <gradebook >
* <attributes>
* <calculations_freeze>20160511</calculations_freeze>
* </attributes>
* <grade_categories>
* <grade_category id="10">
* <depth>1</depth>
* ...
* </grade_category>
* </grade_categories>
* ...
* </gradebook>
*
* 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 <attributes> 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, '<gradebook ') === 0) {
$foundnode = true;
$matches = array();
$pattern = '@calculations_freeze=.([0-9]+).@';
if (preg_match($pattern, $line, $matches)) {
$freeze = $matches[1];
$line = preg_replace($pattern, '', $line);
$line .= " <attributes>\n <calculations_freeze>$freeze</calculations_freeze>\n </attributes>\n";
}
}
fputs($fw, $line);
}
if (!feof($fr)) {
throw new restore_step_exception('Error while attempting to rewrite the gradebook step file.');
}
fclose($fr);
fclose($fw);
if (!rename($newfile, $filepath)) {
throw new restore_step_exception('Error while attempting to rename the gradebook step file.');
}
} else {
if ($fr) {
fclose($fr);
}
if ($fw) {
fclose($fw);
}
}
}
}
/**
@@ -0,0 +1,10 @@
<gradebook >
<attributes>
<calculations_freeze>20160511</calculations_freeze>
</attributes>
<grade_categories>
<grade_category id="10">
<depth>1</depth>
</grade_category>
</grade_categories>
</gradebook>
@@ -0,0 +1,7 @@
<gradebook calculations_freeze="20160511">
<grade_categories>
<grade_category id="10">
<depth>1</depth>
</grade_category>
</grade_categories>
</gradebook>
@@ -0,0 +1,10 @@
<gradebook some_other_value="false" >
<attributes>
<calculations_freeze>20160511</calculations_freeze>
</attributes>
<grade_categories>
<grade_category id="10">
<depth>1</depth>
</grade_category>
</grade_categories>
</gradebook>
@@ -0,0 +1,7 @@
<gradebook some_other_value="false" calculations_freeze="20160511">
<grade_categories>
<grade_category id="10">
<depth>1</depth>
</grade_category>
</grade_categories>
</gradebook>
@@ -0,0 +1,10 @@
<gradebook some_other_value="false" and_another_value="42">
<attributes>
<calculations_freeze>20160511</calculations_freeze>
</attributes>
<grade_categories>
<grade_category id="10">
<depth>1</depth>
</grade_category>
</grade_categories>
</gradebook>
@@ -0,0 +1,7 @@
<gradebook some_other_value="false" calculations_freeze="20160511" and_another_value="42">
<grade_categories>
<grade_category id="10">
<depth>1</depth>
</grade_category>
</grade_categories>
</gradebook>
@@ -0,0 +1,7 @@
<gradebookplugin some_other_value="false" calculations_freeze="20160511" and_another_value="42">
<grade_categories>
<grade_category id="10">
<depth>1</depth>
</grade_category>
</grade_categories>
</gradebookplugin>
@@ -0,0 +1,7 @@
<gradebookplugin some_other_value="false" calculations_freeze="20160511" and_another_value="42">
<grade_categories>
<grade_category id="10">
<depth>1</depth>
</grade_category>
</grade_categories>
</gradebookplugin>
@@ -0,0 +1,92 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Test for restore_stepslib.
*
* @package core_backup
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
require_once($CFG->libdir . '/completionlib.php');
/**
* Test for restore_stepslib.
*
* @package core_backup
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_backup_restore_gradebook_structure_step_testcase extends advanced_testcase {
/**
* Provide tests for rewrite_step_backup_file_for_legacy_freeze based upon fixtures.
*
* @return array
*/
public function rewrite_step_backup_file_for_legacy_freeze_provider() {
$fixturesdir = realpath(__DIR__ . '/fixtures/rewrite_step_backup_file_for_legacy_freeze/');
$tests = [];
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($fixturesdir),
\RecursiveIteratorIterator::LEAVES_ONLY);
foreach ($iterator as $sourcefile) {
$pattern = '/\.test$/';
if (!preg_match($pattern, $sourcefile)) {
continue;
}
$expectfile = preg_replace($pattern, '.expectation', $sourcefile);
$test = array($sourcefile, $expectfile);
$tests[basename($sourcefile)] = $test;
}
return $tests;
}
/**
* @dataProvider rewrite_step_backup_file_for_legacy_freeze_provider
* @param string $source The source file to test
* @param string $expected The expected result of the transformation
*/
public function test_rewrite_step_backup_file_for_legacy_freeze($source, $expected) {
$restore = $this->getMockBuilder('\restore_gradebook_structure_step')
->setMethods(null)
->disableOriginalConstructor()
->getMock()
;
// Copy the file somewhere as the rewrite_step_backup_file_for_legacy_freeze will write the file.
$dir = make_request_directory(true);
$filepath = $dir . DIRECTORY_SEPARATOR . 'file.xml';
copy($source, $filepath);
$rc = new \ReflectionClass('\restore_gradebook_structure_step');
$rcm = $rc->getMethod('rewrite_step_backup_file_for_legacy_freeze');
$rcm->setAccessible(true);
$rcm->invoke($restore, $filepath);
// Check the result.
$this->assertFileEquals($expected, $filepath);
}
}