34b3c808ef02d5d3ace492551ffebf728bc74b04
[yaffs-website] / vendor / alchemy / zippy / src / Adapter / AbstractTarAdapter.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\Archive\Archive;
16 use Alchemy\Zippy\Archive\Member;
17 use Alchemy\Zippy\Exception\RuntimeException;
18 use Alchemy\Zippy\Exception\InvalidArgumentException;
19 use Alchemy\Zippy\Resource\Resource as ZippyResource;
20 use Symfony\Component\Process\Exception\ExceptionInterface as ProcessException;
21
22 abstract class AbstractTarAdapter extends AbstractBinaryAdapter
23 {
24     /**
25      * @inheritdoc
26      */
27     protected function doCreate($path, $files, $recursive)
28     {
29         return $this->doTarCreate($this->getLocalOptions(), $path, $files, $recursive);
30     }
31
32     /**
33      * @inheritdoc
34      */
35     protected function doListMembers(ResourceInterface $resource)
36     {
37         return $this->doTarListMembers($this->getLocalOptions(), $resource);
38     }
39
40     /**
41      * @inheritdoc
42      */
43     protected function doAdd(ResourceInterface $resource, $files, $recursive)
44     {
45         return $this->doTarAdd($this->getLocalOptions(), $resource, $files, $recursive);
46     }
47
48     /**
49      * @inheritdoc
50      */
51     protected function doRemove(ResourceInterface $resource, $files)
52     {
53         return $this->doTarRemove($this->getLocalOptions(), $resource, $files);
54     }
55
56     /**
57      * @inheritdoc
58      */
59     protected function doExtractMembers(ResourceInterface $resource, $members, $to, $overwrite = false)
60     {
61         return $this->doTarExtractMembers($this->getLocalOptions(), $resource, $members, $to, $overwrite);
62     }
63
64     /**
65      * @inheritdoc
66      */
67     protected function doExtract(ResourceInterface $resource, $to)
68     {
69         return $this->doTarExtract($this->getLocalOptions(), $resource, $to);
70     }
71
72     /**
73      * @inheritdoc
74      */
75     protected function doGetInflatorVersion()
76     {
77         $process = $this
78             ->inflator
79             ->create()
80             ->add('--version')
81             ->getProcess();
82
83         $process->run();
84
85         if (!$process->isSuccessful()) {
86             throw new RuntimeException(sprintf(
87                 'Unable to execute the following command %s {output: %s}',
88                 $process->getCommandLine(), $process->getErrorOutput()
89             ));
90         }
91
92         return $this->parser->parseInflatorVersion($process->getOutput() ?: '');
93     }
94
95     /**
96      * @inheritdoc
97      */
98     protected function doGetDeflatorVersion()
99     {
100         return $this->getInflatorVersion();
101     }
102
103     protected function doTarCreate($options, $path, $files = null, $recursive = true)
104     {
105         $files = (array) $files;
106
107         $builder = $this
108             ->inflator
109             ->create();
110
111         if (!$recursive) {
112             $builder->add('--no-recursion');
113         }
114
115         $builder->add('-c');
116
117         foreach ((array) $options as $option) {
118             $builder->add((string) $option);
119         }
120
121         if (0 === count($files)) {
122             $nullFile = defined('PHP_WINDOWS_VERSION_BUILD') ? 'NUL' : '/dev/null';
123
124             $builder->add('-f');
125             $builder->add($path);
126             $builder->add('-T');
127             $builder->add($nullFile);
128
129             $process = $builder->getProcess();
130             $process->run();
131
132         } else {
133
134             $builder->add(sprintf('--file=%s', $path));
135
136             if (!$recursive) {
137                 $builder->add('--no-recursion');
138             }
139
140             $collection = $this->manager->handle(getcwd(), $files);
141
142             $builder->setWorkingDirectory($collection->getContext());
143
144             $collection->forAll(function($i, ZippyResource $resource) use ($builder) {
145                 return $builder->add($resource->getTarget());
146             });
147
148             $process = $builder->getProcess();
149
150             try {
151                 $process->run();
152             } catch (ProcessException $e) {
153                 $this->manager->cleanup($collection);
154                 throw $e;
155             }
156
157             $this->manager->cleanup($collection);
158         }
159
160         if (!$process->isSuccessful()) {
161             throw new RuntimeException(sprintf(
162                 'Unable to execute the following command %s {output: %s}',
163                 $process->getCommandLine(),
164                 $process->getErrorOutput()
165             ));
166         }
167
168         return new Archive($this->createResource($path), $this, $this->manager);
169     }
170
171     protected function doTarListMembers($options, ResourceInterface $resource)
172     {
173         $builder = $this
174             ->inflator
175             ->create();
176
177         foreach ($this->getListMembersOptions() as $option) {
178             $builder->add($option);
179         }
180
181         $builder
182             ->add('--list')
183             ->add('-v')
184             ->add(sprintf('--file=%s', $resource->getResource()));
185
186         foreach ((array) $options as $option) {
187             $builder->add((string) $option);
188         }
189
190         $process = $builder->getProcess();
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         $members = array();
202
203         foreach ($this->parser->parseFileListing($process->getOutput() ?: '') as $member) {
204             $members[] = new Member(
205                     $resource,
206                     $this,
207                     $member['location'],
208                     $member['size'],
209                     $member['mtime'],
210                     $member['is_dir']
211             );
212         }
213
214         return $members;
215     }
216
217     protected function doTarAdd($options, ResourceInterface $resource, $files, $recursive = true)
218     {
219         $files = (array) $files;
220
221         $builder = $this
222             ->inflator
223             ->create();
224
225         if (!$recursive) {
226             $builder->add('--no-recursion');
227         }
228
229         $builder
230             ->add('--append')
231             ->add(sprintf('--file=%s', $resource->getResource()));
232
233         foreach ((array) $options as $option) {
234             $builder->add((string) $option);
235         }
236
237         // there will be an issue if the file starts with a dash
238         // see --add-file=FILE
239         $collection = $this->manager->handle(getcwd(), $files);
240
241         $builder->setWorkingDirectory($collection->getContext());
242
243         $collection->forAll(function($i, ZippyResource $resource) use ($builder) {
244             return $builder->add($resource->getTarget());
245         });
246
247         $process = $builder->getProcess();
248
249         try {
250             $process->run();
251         } catch (ProcessException $e) {
252             $this->manager->cleanup($collection);
253             throw $e;
254         }
255
256         $this->manager->cleanup($collection);
257
258         if (!$process->isSuccessful()) {
259             throw new RuntimeException(sprintf(
260                 'Unable to execute the following command %s {output: %s}',
261                 $process->getCommandLine(),
262                 $process->getErrorOutput()
263             ));
264         }
265
266         return $files;
267     }
268
269     protected function doTarRemove($options, ResourceInterface $resource, $files)
270     {
271         $files = (array) $files;
272
273         $builder = $this
274             ->inflator
275             ->create();
276
277         $builder
278             ->add('--delete')
279             ->add(sprintf('--file=%s', $resource->getResource()));
280
281         foreach ((array) $options as $option) {
282             $builder->add((string) $option);
283         }
284
285         if (!$this->addBuilderFileArgument($files, $builder)) {
286             throw new InvalidArgumentException('Invalid files');
287         }
288
289         $process = $builder->getProcess();
290
291         $process->run();
292
293         if (!$process->isSuccessful()) {
294             throw new RuntimeException(sprintf(
295                 'Unable to execute the following command %s {output: %s}',
296                 $process->getCommandLine(),
297                 $process->getErrorOutput()
298             ));
299         }
300
301         return $files;
302     }
303
304     protected function doTarExtract($options, ResourceInterface $resource, $to = null)
305     {
306         if (null !== $to && !is_dir($to)) {
307             throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
308         }
309
310         $builder = $this
311             ->inflator
312             ->create();
313
314         $builder
315             ->add('--extract')
316             ->add(sprintf('--file=%s', $resource->getResource()));
317
318         foreach ($this->getExtractOptions() as $option) {
319             $builder
320                 ->add($option);
321         }
322
323         foreach ((array) $options as $option) {
324             $builder->add((string) $option);
325         }
326
327         if (null !== $to) {
328             $builder
329                 ->add('--directory')
330                 ->add($to);
331         }
332
333         $process = $builder->getProcess();
334
335         $process->run();
336
337         if (!$process->isSuccessful()) {
338             throw new RuntimeException(sprintf(
339                 'Unable to execute the following command %s {output: %s}',
340                 $process->getCommandLine(),
341                 $process->getErrorOutput()
342             ));
343         }
344
345         return new \SplFileInfo($to ?: $resource->getResource());
346     }
347
348     /**
349      * @param array             $options
350      * @param ResourceInterface $resource
351      * @param array             $members
352      * @param string            $to
353      * @param bool              $overwrite
354      *
355      * @return array
356      */
357     protected function doTarExtractMembers($options, ResourceInterface $resource, $members, $to = null, $overwrite = false)
358     {
359         if (null !== $to && !is_dir($to)) {
360             throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
361         }
362
363         $members = (array) $members;
364
365         $builder = $this
366             ->inflator
367             ->create();
368
369         if ($overwrite == false) {
370             $builder->add('-k');
371         }
372
373         $builder
374             ->add('--extract')
375             ->add(sprintf('--file=%s', $resource->getResource()));
376
377         foreach ($this->getExtractMembersOptions() as $option) {
378             $builder
379                 ->add($option);
380         }
381
382         foreach ((array) $options as $option) {
383             $builder->add((string) $option);
384         }
385
386         if (null !== $to) {
387             $builder
388                 ->add('--directory')
389                 ->add($to);
390         }
391
392         if (!$this->addBuilderFileArgument($members, $builder)) {
393             throw new InvalidArgumentException('Invalid files');
394         }
395
396         $process = $builder->getProcess();
397
398         $process->run();
399
400         if (!$process->isSuccessful()) {
401             throw new RuntimeException(sprintf(
402                 'Unable to execute the following command %s {output: %s}',
403                 $process->getCommandLine(),
404                 $process->getErrorOutput()
405             ));
406         }
407
408         return $members;
409     }
410
411     /**
412      * Returns an array of option for the listMembers command
413      *
414      * @return array
415      */
416     abstract protected function getListMembersOptions();
417
418     /**
419      * Returns an array of option for the extract command
420      *
421      * @return array
422      */
423     abstract protected function getExtractOptions();
424
425     /**
426      * Returns an array of option for the extractMembers command
427      *
428      * @return array
429      */
430     abstract protected function getExtractMembersOptions();
431
432     /**
433      * Gets adapter specific additional options
434      *
435      * @return array
436      */
437     abstract protected function getLocalOptions();
438 }