* * For the full copyright and license information, please view the LICENSE file */ namespace Filegator\Services\Archiver\Adapters; use Filegator\Services\Archiver\ArchiverInterface; use Filegator\Services\Service; use Filegator\Services\Storage\Filesystem as Storage; use Filegator\Services\Tmpfs\TmpfsInterface; use League\Flysystem\Config as Flyconfig; use League\Flysystem\Filesystem as Flysystem; use League\Flysystem\ZipArchive\ZipArchiveAdapter; class ZipArchiver implements Service, ArchiverInterface { protected $archive; protected $storage; protected $tmpfs; protected $uniqid; protected $tmp_files = []; public function __construct(TmpfsInterface $tmpfs) { $this->tmpfs = $tmpfs; } public function init(array $config = []) { } public function createArchive(Storage $storage): string { $this->uniqid = uniqid(); $this->archive = new Flysystem( new ZipAdapter($this->tmpfs->getFileLocation($this->uniqid)) ); $this->storage = $storage; return $this->uniqid; } public function addDirectoryFromStorage(string $path) { $content = $this->storage->getDirectoryCollection($path, true); $this->archive->createDir($path); foreach ($content->all() as $item) { if ($item['type'] == 'dir') { $this->archive->createDir($item['path']); } if ($item['type'] == 'file') { $this->addFileFromStorage($item['path']); } } } public function addFileFromStorage(string $path) { $file_uniqid = uniqid(); $file = $this->storage->readStream($path); $this->tmpfs->write($file_uniqid, $file['stream']); $this->archive->write($path, $this->tmpfs->getFileLocation($file_uniqid)); $this->tmp_files[] = $file_uniqid; } public function uncompress(string $source, string $destination, Storage $storage) { $name = uniqid().'.zip'; $remote_archive = $storage->readStream($source); $this->tmpfs->write($name, $remote_archive['stream']); $archive = new Flysystem( new ZipAdapter($this->tmpfs->getFileLocation($name)) ); $contents = $archive->listContents('/', true); foreach ($contents as $item) { $stream = null; if ($item['type'] == 'dir') { $storage->createDir($destination, $item['path']); } if ($item['type'] == 'file') { $stream = $archive->readStream($item['path']); $storage->store($destination.'/'.$item['dirname'], $item['basename'], $stream); } if (is_resource($stream)) { fclose($stream); } } $this->tmpfs->remove($name); } public function closeArchive() { $this->archive->getAdapter()->getArchive()->close(); foreach ($this->tmp_files as $file) { $this->tmpfs->remove($file); } } public function storeArchive($destination, $name) { $this->closeArchive(); $file = $this->tmpfs->readStream($this->uniqid); $this->storage->store($destination, $name, $file['stream']); if (is_resource($file['stream'])) { fclose($file['stream']); } $this->tmpfs->remove($this->uniqid); } } class ZipAdapter extends ZipArchiveAdapter { public function write($path, $contents, Flyconfig $config) { $location = $this->applyPathPrefix($path); // using addFile instead of addFromString // is more memory efficient $this->archive->addFile($contents, $location); return compact('path', 'contents'); } }