Commit 2fb451c8 authored by Dries's avatar Dries

- Patch #604618 by Crell, JacobSingh: create a common interface for Archive...

- Patch #604618 by Crell, JacobSingh: create a common interface for Archive operations so we can handle .zip, .tar.gz.
parent 977d635b
<?php
/**
* @file
* Shared classes and interfaces for the archiver system.
*/
/**
* Common interface for all Archiver classes.
*/
interface ArchiverInterface {
/**
* Contructor for a new archiver instance.
*
* @param $file_path
* The full system path of the archive to manipulate. Only local files
* are supported. If the file does not yet exist, it will be created if
* appropriate.
*/
public function __construct($file_path);
/**
* Add the specified file or directory to the archive.
*
* @param $file_path
* The full system path of the file or directory to add. Only local files
* and directories are supported.
* @return
* The called object.
*/
public function add($file_path);
/**
* Remove the specified file from the archive.
*
* @param $path
* The file name relative to the root of the archive to remove.
* @return
* The called object.
*/
public function remove($path);
/**
* Extract multiple files in the archive to the specified path.
*
* @param $path
* A full system path of the directory to which to extract files.
* @param $files
* Optionally specify a list of files to be extracted. Files are
* relative to the root of the archive. If not specified, all files
* in the archive will be extracted
* @return
* The called object.
*/
public function extract($path, Array $files = array());
/**
* List all files in the archive.
*
* @return
* An array of file names relative to the root of the archive, or
* an iteratable object that resolves to such a list.
*/
public function listContents();
}
......@@ -5939,3 +5939,53 @@ function xmlrpc($url) {
return call_user_func_array('_xmlrpc', $args);
}
/**
* Retrieve a list of all available archivers.
*/
function archiver_get_info() {
$archiver_info = &drupal_static(__FUNCTION__, array());
if (empty($archiver_info)) {
$cache = cache_get('archiver_info');
if ($cache === FALSE) {
// Rebuild the cache and save it.
$archiver_info = module_invoke_all('archiver_info');
drupal_alter('archiver_info', $archiver_info);
uasort($archiver_info, 'drupal_sort_weight');
cache_set('archiver_info', $archiver_info);
}
else {
$archiver_info = $cache->data;
}
}
return $archiver_info;
}
/**
* Create the appropriate archiver for the specified file.
*
* @param $file
* The full path of the archive file. Note that stream wrapper
* paths are supported.
* @return
* A newly created instance of the archiver class appropriate
* for the specified file, already bound to that file.
*/
function archiver_get_archiver($file) {
$archiver_info = archiver_get_info();
foreach ($archiver_info as $implementation) {
foreach ($implementation['extensions'] as $extension) {
// Because extensions may be multi-part, such as .tar.gz,
// we cannot use simpler approaches like substr() or pathinfo().
// This method isn't quite as clean but gets the job done.
// Also note that the file may not yet exist, so we cannot rely
// on fileinfo() or other disk-level utilities.
if (strrpos($file, '.' . $extension) === strlen($file) - strlen('.' . $extension)) {
return new $implementation['class']($file);
}
}
}
}
......@@ -2398,6 +2398,34 @@ function hook_action_info_alter(&$actions) {
$actions['node_unpublish_action']['label'] = t('Unpublish and remove from public view.');
}
/**
* Declare archivers to the system.
*
* An archiver is a class that is able to package and unpackage one or more files
* into a single possibly compressed file. Common examples of such files are
* zip files and tar.gz files. All archiver classes must implement
* ArchiverInterface.
*
* When mapping a
*
* Each entry should be keyed on a unique value, and specify three
* additional keys:
* - class: The name of the PHP class for this archiver.
* - extensions: An array of file extensions that this archiver supports.
* - weight: This optional key specifies the weight of this archiver.
* When mapping file extensions to archivers, the first archiver by
* weight found that supports the requested extension will be used.
*/
function system_archiver_info() {
return array(
'tar' => array(
'class' => 'ArchiverTar',
'extensions' => array('tar', 'tar.gz', 'tar.bz2'),
),
);
}
/**
* Defines additional date types.
*
......
<?php
/**
* @file
* Archiver implementations provided by the system module.
*/
/**
* Archiver for .tar files.
*/
class ArchiverTar implements ArchiverInterface {
/**
* The underlying Archive_Tar instance that does the heavy lifting.
*
* @var Archive_Tar
*/
protected $tar;
public function __construct($file_path) {
$this->tar = new Archive_Tar($file_path);
}
public function add($file_path) {
$this->tar->add($file_path);
return $this;
}
public function remove($path) {
// @todo Archive_Tar doesn't have a remove operation
// so we'll have to simulate it somehow, probably by
// creating a new archive with everything but the removed
// file.
return $this;
}
public function extract($path, Array $files = array()) {
if ($files) {
$this->tar->extractList($files, $path);
}
else {
$this->tar->extract($path);
}
return $this;
}
public function listContents() {
return $this->tar->listContent();
}
/**
* Retrieve the tar engine itself.
*
* In some cases it may be necessary to directly access the underlying
* Archive_Tar object for implementation-specific logic. This is for advanced
* use only as it is not shared by other implementations of ArchiveInterface.
*
* @return
* The Archive_Tar object used by this object.
*/
public function getArchive() {
return $this->tar;
}
}
......@@ -6,6 +6,7 @@ version = VERSION
core = 7.x
files[] = system.module
files[] = system.admin.inc
files[] = system.archiver.inc
files[] = system.queue.inc
files[] = image.gd.inc
files[] = system.install
......
......@@ -3379,6 +3379,18 @@ function system_date_format_delete($dfid) {
->execute();
}
/**
* Implement hook_archiver_info().
*/
function system_archiver_info() {
return array(
'tar' => array(
'class' => 'ArchiverTar',
'extensions' => array('tar', 'tar.gz', 'tar.bz2'),
),
);
}
/**
* Theme confirmation forms.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment