Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

MDL-38509 Add new tool_installaddon_installer::extract_installfromzip…

…_file() method
  • Loading branch information...
commit 07083b230ba4bb007d22f25be374c773196ffd9d 1 parent 585b64a
@mudrd8mz mudrd8mz authored
View
91 admin/tool/installaddon/classes/installer.php
@@ -43,7 +43,7 @@ class tool_installaddon_installer {
* @return tool_installaddon_installer
*/
public static function instance() {
- return new self();
+ return new static();
}
/**
@@ -114,6 +114,37 @@ public function save_installfromzip_file(tool_installaddon_installfromzip $form,
}
/**
+ * Extracts the saved file previously saved by {self::save_installfromzip_file()}
+ *
+ * The list of files found in the ZIP is returned via $zipcontentfiles parameter
+ * by reference. The format of that list is array of (string)filerelpath => (bool|string)
+ * where the array value is either true or a string describing the problematic file.
+ *
+ * @see zip_packer::extract_to_pathname()
+ * @param string $zipfilepath full path to the saved ZIP file
+ * @param string $targetdir full path to the directory to extract the ZIP file to
+ * @param string $rootdir explicitly rename the root directory of the ZIP into this non-empty value
+ * @param array list of extracted files as returned by {@link zip_packer::extract_to_pathname()}
+ */
+ public function extract_installfromzip_file($zipfilepath, $targetdir, $rootdir = '') {
+ global $CFG;
+ require_once($CFG->libdir.'/filelib.php');
+
+ $fp = get_file_packer('application/zip');
+ $files = $fp->extract_to_pathname($zipfilepath, $targetdir);
+
+ if ($files) {
+ if (!empty($rootdir)) {
+ $files = $this->rename_extracted_rootdir($targetdir, $rootdir, $files);
+ }
+ return $files;
+
+ } else {
+ return array();
+ }
+ }
+
+ /**
* Returns localised list of available plugin types
*
* @return array (string)plugintype => (string)plugin name
@@ -186,6 +217,12 @@ public function is_plugintype_writable($plugintype) {
//// End of external API ///////////////////////////////////////////////////
/**
+ * @see self::instance()
+ */
+ protected function __construct() {
+ }
+
+ /**
* @return string this site full name
*/
protected function get_site_fullname() {
@@ -235,4 +272,56 @@ protected function encode_site_information(array $info) {
protected function should_send_site_info() {
return true;
}
+
+ /**
+ * Renames the root directory of the extracted ZIP package.
+ *
+ * This method does not validate the presence of the single root directory
+ * (the validator does it later). It just searches for the first directory
+ * under the given location and renames it.
+ *
+ * The method will not rename the root if the requested location already
+ * exists.
+ *
+ * @param string $dirname the location of the extracted ZIP package
+ * @param string $rootdir the requested name of the root directory
+ * @param array $files list of extracted files
+ * @return array eventually amended list of extracted files
+ */
+ protected function rename_extracted_rootdir($dirname, $rootdir, array $files) {
+
+ if (!is_dir($dirname)) {
+ debugging('Unable to rename rootdir of non-existing content', DEBUG_DEVELOPER);
+ return $files;
+ }
+
+ if (file_exists($dirname.'/'.$rootdir)) {
+ debugging('Unable to rename rootdir to already existing folder', DEBUG_DEVELOPER);
+ return $files;
+ }
+
+ $found = null; // The name of the first subdirectory under the $dirname.
+ foreach (scandir($dirname) as $item) {
+ if (substr($item, 0, 1) === '.') {
+ continue;
+ }
+ if (is_dir($dirname.'/'.$item)) {
+ $found = $item;
+ break;
+ }
+ }
+
+ if (!is_null($found)) {
+ if (rename($dirname.'/'.$found, $dirname.'/'.$rootdir)) {
+ $newfiles = array();
+ foreach ($files as $filepath => $status) {
+ $newpath = preg_replace('~^'.preg_quote($found.'/').'~', preg_quote($rootdir.'/'), $filepath);
+ $newfiles[$newpath] = $status;
+ }
+ return $newfiles;
+ }
+ }
+
+ return $files;
+ }
}
View
BIN  admin/tool/installaddon/tests/fixtures/zips/invalidroot.zip
Binary file not shown
View
25 admin/tool/installaddon/tests/installer_test.php
@@ -39,7 +39,7 @@
class tool_installaddon_installer_test extends advanced_testcase {
public function test_get_addons_repository_url() {
- $installer = new testable_tool_installaddon_installer();
+ $installer = testable_tool_installaddon_installer::instance();
$url = $installer->get_addons_repository_url();
$query = parse_url($url, PHP_URL_QUERY);
$this->assertEquals(1, preg_match('~^site=(.+)$~', $query, $matches));
@@ -51,6 +51,29 @@ public function test_get_addons_repository_url() {
$this->assertSame($installer->get_site_url(), $site['url']);
$this->assertSame($installer->get_site_major_version(), $site['major_version']);
}
+
+ public function test_extract_installfromzip_file() {
+ $jobid = md5(rand().uniqid('test_', true));
+ $sourcedir = make_temp_directory('tool_installaddon/'.$jobid.'/source');
+ $contentsdir = make_temp_directory('tool_installaddon/'.$jobid.'/contents');
+ copy(dirname(__FILE__).'/fixtures/zips/invalidroot.zip', $sourcedir.'/testinvalidroot.zip');
+
+ $installer = tool_installaddon_installer::instance();
+ $files = $installer->extract_installfromzip_file($sourcedir.'/testinvalidroot.zip', $contentsdir, 'fixed_root');
+ $this->assertEquals('array', gettype($files));
+ $this->assertEquals(4, count($files));
+ $this->assertSame(true, $files['fixed_root/']);
+ $this->assertSame(true, $files['fixed_root/lang/']);
+ $this->assertSame(true, $files['fixed_root/lang/en/']);
+ $this->assertSame(true, $files['fixed_root/lang/en/fixed_root.php']);
+ foreach ($files as $file => $status) {
+ if (substr($file, -1) === '/') {
+ $this->assertTrue(is_dir($contentsdir.'/'.$file));
+ } else {
+ $this->assertTrue(is_file($contentsdir.'/'.$file));
+ }
+ }
+ }
}
Please sign in to comment.
Something went wrong with that request. Please try again.