* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Alchemy\BinaryDriver; use Alchemy\BinaryDriver\Exception\InvalidArgumentException; use Symfony\Component\Process\Process; use Symfony\Component\Process\ProcessBuilder; class ProcessBuilderFactory implements ProcessBuilderFactoryInterface { /** * The binary path * * @var String */ protected $binary; /** * The timeout for the generated processes * * @var integer|float */ private $timeout; /** * An internal ProcessBuilder. * * Note that this one is used only if Symfony ProcessBuilder has method * setPrefix (2.3) * * @var ProcessBuilder */ private $builder; /** * Tells whether Symfony LTS ProcessBuilder should be emulated or not. * * This symfony version provided a brand new ::setPrefix method. * * @var Boolean */ public static $emulateSfLTS; /** * Constructor * * @param String $binary The path to the binary * * @throws InvalidArgumentException In case binary path is invalid */ public function __construct($binary) { $this->detectEmulation(); if (!self::$emulateSfLTS) { $this->builder = new ProcessBuilder(); } $this->useBinary($binary); } /** * Covenient method for unit testing * * @return type */ public function getBuilder() { return $this->builder; } /** * Covenient method for unit testing * * @param ProcessBuilder $builder * @return ProcessBuilderFactory */ public function setBuilder(ProcessBuilder $builder) { $this->builder = $builder; return $this; } /** * @inheritdoc */ public function getBinary() { return $this->binary; } /** * @inheritdoc */ public function useBinary($binary) { if (!is_executable($binary)) { throw new InvalidArgumentException(sprintf('`%s` is not an executable binary', $binary)); } $this->binary = $binary; if (!static::$emulateSfLTS) { $this->builder->setPrefix($binary); } return $this; } /** * @inheritdoc */ public function setTimeout($timeout) { $this->timeout = $timeout; if (!static::$emulateSfLTS) { $this->builder->setTimeout($this->timeout); } return $this; } /** * @inheritdoc */ public function getTimeout() { return $this->timeout; } /** * @inheritdoc */ public function create($arguments = array()) { if (null === $this->binary) { throw new InvalidArgumentException('No binary set'); } if (!is_array($arguments)) { $arguments = array($arguments); } if (static::$emulateSfLTS) { array_unshift($arguments, $this->binary); if (method_exists('Symfony\Component\Process\ProcessUtils', 'escapeArgument')) { $script = implode(' ', array_map(array('Symfony\Component\Process\ProcessUtils', 'escapeArgument'), $arguments)); } else { $script = $arguments; } $env = array_replace($_ENV, $_SERVER); $env = array_filter($env, function ($value) { return !is_array($value); }); return new Process($script, null, $env, null, $this->timeout); } else { return $this->builder ->setArguments($arguments) ->getProcess(); } } private function detectEmulation() { if (null !== static::$emulateSfLTS) { return $this; } static::$emulateSfLTS = !method_exists('Symfony\Component\Process\ProcessBuilder', 'setPrefix'); return $this; } }