4 * This file is part of Zippy.
6 * (c) Alchemy <info@alchemy.fr>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Alchemy\Zippy\Adapter;
14 use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
15 use Alchemy\Zippy\Adapter\VersionProbe\ZipVersionProbe;
16 use Alchemy\Zippy\Archive\Archive;
17 use Alchemy\Zippy\Archive\Member;
18 use Alchemy\Zippy\Exception\InvalidArgumentException;
19 use Alchemy\Zippy\Exception\NotSupportedException;
20 use Alchemy\Zippy\Exception\RuntimeException;
21 use Alchemy\Zippy\Parser\ParserInterface;
22 use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactoryInterface;
23 use Alchemy\Zippy\Resource\Resource as ZippyResource;
24 use Alchemy\Zippy\Resource\ResourceManager;
25 use Symfony\Component\Process\Exception\ExceptionInterface as ProcessException;
28 * ZipAdapter allows you to create and extract files from archives using Zip
30 * @see http://www.gnu.org/software/tar/manual/tar.html
32 class ZipAdapter extends AbstractBinaryAdapter
34 public function __construct(
35 ParserInterface $parser,
36 ResourceManager $manager,
37 ProcessBuilderFactoryInterface $inflator,
38 ProcessBuilderFactoryInterface $deflator
40 parent::__construct($parser, $manager, $inflator, $deflator);
42 $this->probe = new ZipVersionProbe($inflator, $deflator);
48 protected function doCreate($path, $files, $recursive)
50 $files = (array) $files;
56 if (0 === count($files)) {
57 throw new NotSupportedException('Can not create empty zip archive');
66 $collection = $this->manager->handle(getcwd(), $files);
67 $builder->setWorkingDirectory($collection->getContext());
69 $collection->forAll(function($i, ZippyResource $resource) use ($builder) {
70 return $builder->add($resource->getTarget());
73 $process = $builder->getProcess();
77 } catch (ProcessException $e) {
78 $this->manager->cleanup($collection);
82 $this->manager->cleanup($collection);
84 if (!$process->isSuccessful()) {
85 throw new RuntimeException(sprintf(
86 'Unable to execute the following command %s {output: %s}',
87 $process->getCommandLine(),
88 $process->getErrorOutput()
92 return new Archive($this->createResource($path), $this, $this->manager);
98 protected function doListMembers(ResourceInterface $resource)
104 ->add($resource->getResource())
109 if (!$process->isSuccessful()) {
110 throw new RuntimeException(sprintf(
111 'Unable to execute the following command %s {output: %s}',
112 $process->getCommandLine(),
113 $process->getErrorOutput()
119 foreach ($this->parser->parseFileListing($process->getOutput() ?: '') as $member) {
120 $members[] = new Member(
136 protected function doAdd(ResourceInterface $resource, $files, $recursive)
138 $files = (array) $files;
150 ->add($resource->getResource());
152 $collection = $this->manager->handle(getcwd(), $files);
154 $builder->setWorkingDirectory($collection->getContext());
156 $collection->forAll(function($i, ZippyResource $resource) use ($builder) {
157 return $builder->add($resource->getTarget());
160 $process = $builder->getProcess();
164 } catch (ProcessException $e) {
165 $this->manager->cleanup($collection);
169 $this->manager->cleanup($collection);
171 if (!$process->isSuccessful()) {
172 throw new RuntimeException(sprintf(
173 'Unable to execute the following command %s {output: %s}',
174 $process->getCommandLine(),
175 $process->getErrorOutput()
183 protected function doGetDeflatorVersion()
193 if (!$process->isSuccessful()) {
194 throw new RuntimeException(sprintf(
195 'Unable to execute the following command %s {output: %s}',
196 $process->getCommandLine(),
197 $process->getErrorOutput()
201 return $this->parser->parseDeflatorVersion($process->getOutput() ?: '');
207 protected function doGetInflatorVersion()
217 if (!$process->isSuccessful()) {
218 throw new RuntimeException(sprintf(
219 'Unable to execute the following command %s {output: %s}',
220 $process->getCommandLine(),
221 $process->getErrorOutput()
225 return $this->parser->parseInflatorVersion($process->getOutput() ?: '');
231 protected function doRemove(ResourceInterface $resource, $files)
233 $files = (array) $files;
241 ->add($resource->getResource());
243 if (!$this->addBuilderFileArgument($files, $builder)) {
244 throw new InvalidArgumentException('Invalid files');
247 $process = $builder->getProcess();
251 if (!$process->isSuccessful()) {
252 throw new RuntimeException(sprintf(
253 'Unable to execute the following command %s {output: %s}',
254 $process->getCommandLine(),
255 $process->getErrorOutput()
265 public static function getName()
273 public static function getDefaultDeflatorBinaryName()
275 return array('unzip');
281 public static function getDefaultInflatorBinaryName()
289 protected function doExtract(ResourceInterface $resource, $to)
291 if (null !== $to && !is_dir($to)) {
292 throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
301 ->add($resource->getResource());
309 $process = $builder->getProcess();
313 if (!$process->isSuccessful()) {
314 throw new RuntimeException(sprintf(
315 'Unable to execute the following command %s {output: %s}',
316 $process->getCommandLine(),
317 $process->getErrorOutput()
321 return new \SplFileInfo($to ?: $resource->getResource());
327 protected function doExtractMembers(ResourceInterface $resource, $members, $to, $overwrite = false)
329 if (null !== $to && !is_dir($to)) {
330 throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
333 $members = (array) $members;
339 if ((bool) $overwrite) {
344 ->add($resource->getResource());
352 if (!$this->addBuilderFileArgument($members, $builder)) {
353 throw new InvalidArgumentException('Invalid files');
356 $process = $builder->getProcess();
360 if (!$process->isSuccessful()) {
361 throw new RuntimeException(sprintf(
362 'Unable to execute the following command %s {output: %s}',
363 $process->getCommandLine(),
364 $process->getErrorOutput()