--- /dev/null
+<?php
+
+/*
+ * This file is part of Zippy.
+ *
+ * (c) Alchemy <info@alchemy.fr>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ */
+
+namespace Alchemy\Zippy\Adapter;
+
+use Alchemy\Zippy\Adapter\Resource\FileResource;
+use Alchemy\Zippy\Archive\MemberInterface;
+use Alchemy\Zippy\Exception\RuntimeException;
+use Alchemy\Zippy\Exception\InvalidArgumentException;
+use Alchemy\Zippy\Parser\ParserFactory;
+use Alchemy\Zippy\Parser\ParserInterface;
+use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactory;
+use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactoryInterface;
+use Alchemy\Zippy\Resource\ResourceManager;
+use Symfony\Component\Process\ExecutableFinder;
+use Symfony\Component\Process\ProcessBuilder;
+
+abstract class AbstractBinaryAdapter extends AbstractAdapter implements BinaryAdapterInterface
+{
+ /**
+ * The parser to use to parse command output
+ *
+ * @var ParserInterface
+ */
+ protected $parser;
+
+ /**
+ * The deflator process builder factory to use to build binary command line
+ *
+ * @var ProcessBuilderFactoryInterface
+ */
+ protected $deflator;
+
+ /**
+ * The inflator process builder factory to use to build binary command line
+ *
+ * @var ProcessBuilderFactoryInterface
+ */
+ protected $inflator;
+
+ /**
+ * Constructor
+ *
+ * @param ParserInterface $parser An output parser
+ * @param ResourceManager $manager A resource manager
+ * @param ProcessBuilderFactoryInterface $inflator A process builder factory for the inflator binary
+ * @param ProcessBuilderFactoryInterface $deflator A process builder factory for the deflator binary
+ */
+ public function __construct(
+ ParserInterface $parser,
+ ResourceManager $manager,
+ ProcessBuilderFactoryInterface $inflator,
+ ProcessBuilderFactoryInterface $deflator
+ ) {
+ $this->parser = $parser;
+ parent::__construct($manager);
+ $this->deflator = $deflator;
+ $this->inflator = $inflator;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getParser()
+ {
+ return $this->parser;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setParser(ParserInterface $parser)
+ {
+ $this->parser = $parser;
+
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getDeflator()
+ {
+ return $this->deflator;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getInflator()
+ {
+ return $this->inflator;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setDeflator(ProcessBuilderFactoryInterface $processBuilder)
+ {
+ $this->deflator = $processBuilder;
+
+ return $this;
+ }
+
+ public function setInflator(ProcessBuilderFactoryInterface $processBuilder)
+ {
+ $this->inflator = $processBuilder;
+
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getInflatorVersion()
+ {
+ $this->requireSupport();
+
+ return $this->doGetInflatorVersion();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getDeflatorVersion()
+ {
+ $this->requireSupport();
+
+ return $this->doGetDeflatorVersion();
+ }
+
+ /**
+ * Returns a new instance of the invoked adapter
+ *
+ * @param ExecutableFinder $finder
+ * @param ResourceManager $manager
+ * @param string|null $inflatorBinaryName The inflator binary name to use
+ * @param string|null $deflatorBinaryName The deflator binary name to use
+ *
+ * @return AbstractBinaryAdapter
+ */
+ public static function newInstance(
+ ExecutableFinder $finder,
+ ResourceManager $manager,
+ $inflatorBinaryName = null,
+ $deflatorBinaryName = null
+ ) {
+ $inflator = $inflatorBinaryName instanceof ProcessBuilderFactoryInterface ? $inflatorBinaryName : self::findABinary($inflatorBinaryName,
+ static::getDefaultInflatorBinaryName(), $finder);
+ $deflator = $deflatorBinaryName instanceof ProcessBuilderFactoryInterface ? $deflatorBinaryName : self::findABinary($deflatorBinaryName,
+ static::getDefaultDeflatorBinaryName(), $finder);
+
+ try {
+ $outputParser = ParserFactory::create(static::getName());
+ } catch (InvalidArgumentException $e) {
+ throw new RuntimeException(sprintf(
+ 'Failed to get a new instance of %s',
+ get_called_class()), $e->getCode(), $e
+ );
+ }
+
+ if (null === $inflator) {
+ throw new RuntimeException(sprintf('Unable to create the inflator'));
+ }
+
+ if (null === $deflator) {
+ throw new RuntimeException(sprintf('Unable to create the deflator'));
+ }
+
+ return new static($outputParser, $manager, $inflator, $deflator);
+ }
+
+ private static function findABinary($wish, array $defaults, ExecutableFinder $finder)
+ {
+ $possibles = $wish ? (array) $wish : $defaults;
+
+ $binary = null;
+
+ foreach ($possibles as $possible) {
+ if (null !== $found = $finder->find($possible)) {
+ $binary = new ProcessBuilderFactory($found);
+ break;
+ }
+ }
+
+ return $binary;
+ }
+
+ /**
+ * Adds files to argument list
+ *
+ * @param MemberInterface[]|\SplFileInfo[]|string[] $files An array of files
+ * @param ProcessBuilder $builder A Builder instance
+ *
+ * @return bool
+ */
+ protected function addBuilderFileArgument(array $files, ProcessBuilder $builder)
+ {
+ $iterations = 0;
+
+ array_walk($files, function($file) use ($builder, &$iterations) {
+ $builder->add(
+ $file instanceof \SplFileInfo ?
+ $file->getRealPath() : ($file instanceof MemberInterface ? $file->getLocation() : $file)
+ );
+
+ $iterations++;
+ });
+
+ return 0 !== $iterations;
+ }
+
+ protected function createResource($path)
+ {
+ return new FileResource($path);
+ }
+
+ /**
+ * Fetch the inflator version after having check that the current adapter is supported
+ *
+ * @return string
+ */
+ abstract protected function doGetInflatorVersion();
+
+ /**
+ * Fetch the Deflator version after having check that the current adapter is supported
+ *
+ * @return string
+ */
+ abstract protected function doGetDeflatorVersion();
+}