| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- <?php
- namespace Dcat\Admin\Support;
- /**
- * Zip helper.
- *
- * @author Alexey Bobkov, Samuel Georges
- *
- * Usage:
- *
- * Zip::make('file.zip', '/some/path/*.php');
- *
- * Zip::make('file.zip', function($zip) {
- *
- * // Add all PHP files and directories
- * $zip->add('/some/path/*.php');
- *
- * // Do not include subdirectories, one level only
- * $zip->add('/non/recursive/*', ['recursive' => false]);
- *
- * // Add multiple paths
- * $zip->add([
- * '/collection/of/paths/*',
- * '/a/single/file.php'
- * ]);
- *
- * // Add all INI files to a zip folder "config"
- * $zip->folder('/config', '/path/to/config/*.ini');
- *
- * // Add multiple paths to a zip folder "images"
- * $zip->folder('/images', function($zip) {
- * $zip->add('/my/gifs/*.gif', );
- * $zip->add('/photo/reel/*.{png,jpg}', );
- * });
- *
- * // Remove these files/folders from the zip
- * $zip->remove([
- * '.htaccess',
- * 'config.php',
- * 'some/folder'
- * ]);
- *
- * });
- *
- * Zip::extract('file.zip', '/destination/path');
- */
- use ZipArchive;
- class Zip extends ZipArchive
- {
- /**
- * @var string Folder prefix
- */
- protected $folderPrefix = '';
- /**
- * Extract an existing zip file.
- * @param string $source Path for the existing zip
- * @param string $destination Path to extract the zip files
- * @param array $options
- * @return bool
- */
- public static function extract($source, $destination, $options = [])
- {
- extract(array_merge([
- 'mask' => 0777,
- ], $options));
- if (file_exists($destination) || mkdir($destination, $mask, true)) {
- $zip = new ZipArchive;
- if ($zip->open($source) === true) {
- $zip->extractTo($destination);
- $zip->close();
- return true;
- }
- }
- return false;
- }
- /**
- * Creates a new empty zip file.
- * @param string $destination Path for the new zip
- * @param mixed $source
- * @param array $options
- * @return self
- */
- public static function make($destination, $source, $options = [])
- {
- $zip = new self;
- $zip->open($destination, ZIPARCHIVE::CREATE | ZipArchive::OVERWRITE);
- if (is_string($source)) {
- $zip->add($source, $options);
- } elseif (is_callable($source)) {
- $source($zip);
- } elseif (is_array($source)) {
- foreach ($source as $_source) {
- $zip->add($_source, $options);
- }
- }
- $zip->close();
- return $zip;
- }
- /**
- * Includes a source to the Zip.
- * @param mixed $source
- * @param array $options
- * @return self
- */
- public function add($source, $options = [])
- {
- /*
- * A directory has been supplied, convert it to a useful glob
- *
- * The wildcard for including hidden files:
- * - isn't hidden with an '.'
- * - is hidden with a '.' but is followed by a non '.' character
- * - starts with '..' but has at least one character after it
- */
- if (is_dir($source)) {
- $includeHidden = isset($options['includeHidden']) && $options['includeHidden'];
- $wildcard = $includeHidden ? '{*,.[!.]*,..?*}' : '*';
- $source = implode('/', [dirname($source), basename($source), $wildcard]);
- }
- extract(array_merge([
- 'recursive' => true,
- 'includeHidden' => false,
- 'basedir' => dirname($source),
- 'baseglob' => basename($source),
- ], $options));
- if (is_file($source)) {
- $files = [$source];
- $recursive = false;
- } else {
- $files = glob($source, GLOB_BRACE);
- $folders = glob(dirname($source).'/*', GLOB_ONLYDIR);
- }
- foreach ($files as $file) {
- if (! is_file($file)) {
- continue;
- }
- $localpath = $this->removePathPrefix($basedir.'/', dirname($file).'/');
- $localfile = $this->folderPrefix.$localpath.basename($file);
- $this->addFile($file, $localfile);
- }
- if (! $recursive) {
- return $this;
- }
- foreach ($folders as $folder) {
- if (! is_dir($folder)) {
- continue;
- }
- $localpath = $this->folderPrefix.$this->removePathPrefix($basedir.'/', $folder.'/');
- $this->addEmptyDir($localpath);
- $this->add($folder.'/'.$baseglob, array_merge($options, ['basedir' => $basedir]));
- }
- return $this;
- }
- /**
- * Creates a new folder inside the Zip and adds source files (optional).
- * @param string $name Folder name
- * @param mixed $source
- * @return self
- */
- public function folder($name, $source = null)
- {
- $prefix = $this->folderPrefix;
- $this->addEmptyDir($prefix.$name);
- if ($source === null) {
- return $this;
- }
- $this->folderPrefix = $prefix.$name.'/';
- if (is_string($source)) {
- $this->add($source);
- } elseif (is_callable($source)) {
- $source($this);
- } elseif (is_array($source)) {
- foreach ($source as $_source) {
- $this->add($_source);
- }
- }
- $this->folderPrefix = $prefix;
- return $this;
- }
- /**
- * Removes a file or folder from the zip collection.
- * Does not support wildcards.
- * @param string $source
- * @return self
- */
- public function remove($source)
- {
- if (is_array($source)) {
- foreach ($source as $_source) {
- $this->remove($_source);
- }
- }
- if (! is_string($source)) {
- return $this;
- }
- if (substr($source, 0, 1) == '/') {
- $source = substr($source, 1);
- }
- for ($i = 0; $i < $this->numFiles; $i++) {
- $stats = $this->statIndex($i);
- if (substr($stats['name'], 0, strlen($source)) == $source) {
- $this->deleteIndex($i);
- }
- }
- return $this;
- }
- /**
- * Removes a prefix from a path.
- * @param string $prefix /var/sites/
- * @param string $path /var/sites/moo/cow/
- * @return string moo/cow/
- */
- protected function removePathPrefix($prefix, $path)
- {
- return (strpos($path, $prefix) === 0)
- ? substr($path, strlen($prefix))
- : $path;
- }
- }
|