4fb6ba7f178ea84f06820cf2492cb169adeed9f3
[yaffs-website] / vendor / alchemy / zippy / src / Adapter / ZipAdapter.php
1 <?php
2
3 /*
4  * This file is part of Zippy.
5  *
6  * (c) Alchemy <info@alchemy.fr>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Alchemy\Zippy\Adapter;
13
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;
26
27 /**
28  * ZipAdapter allows you to create and extract files from archives using Zip
29  *
30  * @see http://www.gnu.org/software/tar/manual/tar.html
31  */
32 class ZipAdapter extends AbstractBinaryAdapter
33 {
34     public function __construct(
35         ParserInterface $parser,
36         ResourceManager $manager,
37         ProcessBuilderFactoryInterface $inflator,
38         ProcessBuilderFactoryInterface $deflator
39     ) {
40         parent::__construct($parser, $manager, $inflator, $deflator);
41
42         $this->probe = new ZipVersionProbe($inflator, $deflator);
43     }
44
45     /**
46      * @inheritdoc
47      */
48     protected function doCreate($path, $files, $recursive)
49     {
50         $files = (array) $files;
51
52         $builder = $this
53             ->inflator
54             ->create();
55
56         if (0 === count($files)) {
57             throw new NotSupportedException('Can not create empty zip archive');
58         }
59
60         if ($recursive) {
61             $builder->add('-r');
62         }
63
64         $builder->add($path);
65
66         $collection = $this->manager->handle(getcwd(), $files);
67         $builder->setWorkingDirectory($collection->getContext());
68
69         $collection->forAll(function($i, ZippyResource $resource) use ($builder) {
70             return $builder->add($resource->getTarget());
71         });
72
73         $process = $builder->getProcess();
74
75         try {
76             $process->run();
77         } catch (ProcessException $e) {
78             $this->manager->cleanup($collection);
79             throw $e;
80         }
81
82         $this->manager->cleanup($collection);
83
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()
89             ));
90         }
91
92         return new Archive($this->createResource($path), $this, $this->manager);
93     }
94
95     /**
96      * @inheritdoc
97      */
98     protected function doListMembers(ResourceInterface $resource)
99     {
100         $process = $this
101             ->deflator
102             ->create()
103             ->add('-l')
104             ->add($resource->getResource())
105             ->getProcess();
106
107         $process->run();
108
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()
114             ));
115         }
116
117         $members = array();
118
119         foreach ($this->parser->parseFileListing($process->getOutput() ?: '') as $member) {
120             $members[] = new Member(
121                 $resource,
122                 $this,
123                 $member['location'],
124                 $member['size'],
125                 $member['mtime'],
126                 $member['is_dir']
127             );
128         }
129
130         return $members;
131     }
132
133     /**
134      * @inheritdoc
135      */
136     protected function doAdd(ResourceInterface $resource, $files, $recursive)
137     {
138         $files = (array) $files;
139
140         $builder = $this
141             ->inflator
142             ->create();
143
144         if ($recursive) {
145             $builder->add('-r');
146         }
147
148         $builder
149             ->add('-u')
150             ->add($resource->getResource());
151
152         $collection = $this->manager->handle(getcwd(), $files);
153
154         $builder->setWorkingDirectory($collection->getContext());
155
156         $collection->forAll(function($i, ZippyResource $resource) use ($builder) {
157             return $builder->add($resource->getTarget());
158         });
159
160         $process = $builder->getProcess();
161
162         try {
163             $process->run();
164         } catch (ProcessException $e) {
165             $this->manager->cleanup($collection);
166             throw $e;
167         }
168
169         $this->manager->cleanup($collection);
170
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()
176             ));
177         }
178     }
179
180     /**
181      * @inheritdoc
182      */
183     protected function doGetDeflatorVersion()
184     {
185         $process = $this
186             ->deflator
187             ->create()
188             ->add('-h')
189             ->getProcess();
190
191         $process->run();
192
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()
198             ));
199         }
200
201         return $this->parser->parseDeflatorVersion($process->getOutput() ?: '');
202     }
203
204     /**
205      * @inheritdoc
206      */
207     protected function doGetInflatorVersion()
208     {
209         $process = $this
210             ->inflator
211             ->create()
212             ->add('-h')
213             ->getProcess();
214
215         $process->run();
216
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()
222             ));
223         }
224
225         return $this->parser->parseInflatorVersion($process->getOutput() ?: '');
226     }
227
228     /**
229      * @inheritdoc
230      */
231     protected function doRemove(ResourceInterface $resource, $files)
232     {
233         $files = (array) $files;
234
235         $builder = $this
236             ->inflator
237             ->create();
238
239         $builder
240             ->add('-d')
241             ->add($resource->getResource());
242
243         if (!$this->addBuilderFileArgument($files, $builder)) {
244             throw new InvalidArgumentException('Invalid files');
245         }
246
247         $process = $builder->getProcess();
248
249         $process->run();
250
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()
256             ));
257         }
258
259         return $files;
260     }
261
262     /**
263      * @inheritdoc
264      */
265     public static function getName()
266     {
267         return 'zip';
268     }
269
270     /**
271      * @inheritdoc
272      */
273     public static function getDefaultDeflatorBinaryName()
274     {
275         return array('unzip');
276     }
277
278     /**
279      * @inheritdoc
280      */
281     public static function getDefaultInflatorBinaryName()
282     {
283         return array('zip');
284     }
285
286     /**
287      * @inheritdoc
288      */
289     protected function doExtract(ResourceInterface $resource, $to)
290     {
291         if (null !== $to && !is_dir($to)) {
292             throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
293         }
294
295         $builder = $this
296             ->deflator
297             ->create();
298
299         $builder
300             ->add('-o')
301             ->add($resource->getResource());
302
303         if (null !== $to) {
304             $builder
305                 ->add('-d')
306                 ->add($to);
307         }
308
309         $process = $builder->getProcess();
310
311         $process->run();
312
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()
318             ));
319         }
320
321         return new \SplFileInfo($to ?: $resource->getResource());
322     }
323
324     /**
325      * @inheritdoc
326      */
327     protected function doExtractMembers(ResourceInterface $resource, $members, $to, $overwrite = false)
328     {
329         if (null !== $to && !is_dir($to)) {
330             throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
331         }
332
333         $members = (array) $members;
334
335         $builder = $this
336             ->deflator
337             ->create();
338
339         if ((bool) $overwrite) {
340             $builder->add('-o');
341         }
342
343         $builder
344             ->add($resource->getResource());
345
346         if (null !== $to) {
347             $builder
348                 ->add('-d')
349                 ->add($to);
350         }
351
352         if (!$this->addBuilderFileArgument($members, $builder)) {
353             throw new InvalidArgumentException('Invalid files');
354         }
355
356         $process = $builder->getProcess();
357
358         $process->run();
359
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()
365             ));
366         }
367
368         return $members;
369     }
370 }