mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 04:22:07 +02:00
MDL-39442 Do not use native rename() when moving folders
The native rename() function does not support moving folders cross-device. See https://bugs.php.net/bug.php?id=54097 for details. So instead of trying to move the whole tree, the new installer's method moves files recursively one by one. This is consistent with what mdeploy.php already does.
This commit is contained in:
parent
cf5a3296c4
commit
ed70c74be5
@ -395,6 +395,52 @@ class tool_installaddon_installer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the given source into a new location recursively
|
||||
*
|
||||
* This is cross-device safe implementation to be used instead of the native rename() function.
|
||||
* See https://bugs.php.net/bug.php?id=54097 for more details.
|
||||
*
|
||||
* @param string $source full path to the existing directory
|
||||
* @param string $target full path to the new location of the directory
|
||||
*/
|
||||
public function move_directory($source, $target) {
|
||||
|
||||
if (file_exists($target)) {
|
||||
throw new tool_installaddon_installer_exception('err_folder_already_exists', array('path' => $target));
|
||||
}
|
||||
|
||||
if (is_dir($source)) {
|
||||
$handle = opendir($source);
|
||||
} else {
|
||||
throw new tool_installaddon_installer_exception('err_no_such_folder', array('path' => $source));
|
||||
}
|
||||
|
||||
make_writable_directory($target);
|
||||
|
||||
while ($filename = readdir($handle)) {
|
||||
$sourcepath = $source.'/'.$filename;
|
||||
$targetpath = $target.'/'.$filename;
|
||||
|
||||
if ($filename === '.' or $filename === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_dir($sourcepath)) {
|
||||
$this->move_directory($sourcepath, $targetpath);
|
||||
|
||||
} else {
|
||||
rename($sourcepath, $targetpath);
|
||||
}
|
||||
}
|
||||
|
||||
closedir($handle);
|
||||
|
||||
rmdir($source);
|
||||
|
||||
clearstatcache();
|
||||
}
|
||||
|
||||
//// End of external API ///////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
|
@ -71,6 +71,6 @@ if (file_exists($plugintypepath.'/'.$pluginname)) {
|
||||
get_string('invaliddata', 'core_error'));
|
||||
}
|
||||
|
||||
rename($zipcontentpath.'/'.$pluginname, $plugintypepath.'/'.$pluginname);
|
||||
$installer->move_directory($zipcontentpath.'/'.$pluginname, $plugintypepath.'/'.$pluginname);
|
||||
fulldelete($CFG->tempdir.'/tool_installaddon/'.$jobid);
|
||||
redirect(new moodle_url('/admin'));
|
||||
|
@ -125,6 +125,20 @@ class tool_installaddon_installer_test extends advanced_testcase {
|
||||
)));
|
||||
$this->assertSame(false, $installer->testable_decode_remote_request($request));
|
||||
}
|
||||
|
||||
public function test_move_directory() {
|
||||
$jobid = md5(rand().uniqid('test_', true));
|
||||
$jobroot = make_temp_directory('tool_installaddon/'.$jobid);
|
||||
$contentsdir = make_temp_directory('tool_installaddon/'.$jobid.'/contents/sub/folder');
|
||||
file_put_contents($contentsdir.'/readme.txt', 'Hello world!');
|
||||
|
||||
$installer = tool_installaddon_installer::instance();
|
||||
$installer->move_directory($jobroot.'/contents', $jobroot.'/moved');
|
||||
|
||||
$this->assertFalse(is_dir($jobroot.'/contents'));
|
||||
$this->assertTrue(is_file($jobroot.'/moved/sub/folder/readme.txt'));
|
||||
$this->assertSame('Hello world!', file_get_contents($jobroot.'/moved/sub/folder/readme.txt'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,4 +26,4 @@ defined('MOODLE_INTERNAL') || die();
|
||||
$plugin->component = 'tool_installaddon';
|
||||
$plugin->version = 2013031400;
|
||||
$plugin->requires = 2013031400;
|
||||
$plugin->maturity = MATURITY_BETA;
|
||||
$plugin->maturity = MATURITY_STABLE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user