Mercurial > hg > cmmr2012-drupal-site
diff vendor/consolidation/site-process/src/ProcessBase.php @ 5:12f9dff5fda9 tip
Update to Drupal core 8.7.1
author | Chris Cannam |
---|---|
date | Thu, 09 May 2019 15:34:47 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/consolidation/site-process/src/ProcessBase.php Thu May 09 15:34:47 2019 +0100 @@ -0,0 +1,229 @@ +<?php + +namespace Consolidation\SiteProcess; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\Style\OutputStyle; +use Symfony\Component\Process\Process; +use Consolidation\SiteProcess\Util\RealtimeOutputHandler; +use Consolidation\SiteProcess\Util\Escape; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; + +/** + * A wrapper around Symfony Process. + * + * - Supports simulated mode. Typically enabled via a --simulate option. + * - Supports verbose mode - logs all runs. + * - Can convert output json data into php array (convenience method) + * - Provides a "realtime output" helper + */ +class ProcessBase extends Process +{ + /** + * @var OutputStyle + */ + protected $output; + + /** + * @var OutputInterface + */ + protected $stderr; + + private $simulated = false; + + private $verbose = false; + + /** + * @var LoggerInterface + */ + private $logger; + + /** + * Symfony 4 style constructor for creating Process instances from strings. + * @param string $command The commandline string to run + * @param string|null $cwd The working directory or null to use the working dir of the current PHP process + * @param array|null $env The environment variables or null to use the same environment as the current PHP process + * @param mixed|null $input The input as stream resource, scalar or \Traversable, or null for no input + * @param int|float|null $timeout The timeout in seconds or null to disable + * @return Process + */ + public static function fromShellCommandline($command, $cwd = null, array $env = null, $input = null, $timeout = 60) + { + if (method_exists('\Symfony\Component\Process\Process', 'fromShellCommandline')) { + return Process::fromShellCommandline($command, $cwd, $env, $input, $timeout); + } + return new self($command, $cwd, $env, $input, $timeout); + } + + /** + * realtimeStdout returns the output stream that realtime output + * should be sent to (if applicable) + * + * @return OutputStyle $output + */ + public function realtimeStdout() + { + return $this->output; + } + + protected function realtimeStderr() + { + if ($this->stderr) { + return $this->stderr; + } + if (method_exists($this->output, 'getErrorStyle')) { + return $this->output->getErrorStyle(); + } + + return $this->realtimeStdout(); + } + + /** + * setRealtimeOutput allows the caller to inject an OutputStyle object + * that will be used to stream realtime output if applicable. + * + * @param OutputStyle $output + */ + public function setRealtimeOutput(OutputInterface $output, $stderr = null) + { + $this->output = $output; + $this->stderr = $stderr instanceof ConsoleOutputInterface ? $stderr->getErrorOutput() : $stderr; + } + + /** + * @return bool + */ + public function isVerbose() + { + return $this->verbose; + } + + /** + * @param bool $verbose + */ + public function setVerbose($verbose) + { + $this->verbose = $verbose; + } + + /** + * @return bool + */ + public function isSimulated() + { + return $this->simulated; + } + + /** + * @param bool $simulated + */ + public function setSimulated($simulated) + { + $this->simulated = $simulated; + } + + /** + * @return LoggerInterface + */ + public function getLogger() + { + return $this->logger; + } + + /** + * @param LoggerInterface $logger + */ + public function setLogger($logger) + { + $this->logger = $logger; + } + + /** + * @inheritDoc + */ + public function start(callable $callback = null, $env = array()) + { + $cmd = $this->getCommandLine(); + if ($this->isSimulated()) { + $this->getLogger()->notice('Simulating: ' . $cmd); + // Run a command that always succeeds (on Linux and Windows). + $this->setCommandLine('true'); + } elseif ($this->isVerbose()) { + $this->getLogger()->info('Executing: ' . $cmd); + } + parent::start($callback, $env); + // Set command back to original value in case anyone asks. + if ($this->isSimulated()) { + $this->setCommandLine($cmd); + } + } + + /** + * Get Process output and decode its JSON. + * + * @return array + * An associative array. + */ + public function getOutputAsJson() + { + $output = trim($this->getOutput()); + if (empty($output)) { + throw new \InvalidArgumentException('Output is empty.'); + } + if (Escape::isWindows()) { + // Doubled double quotes were converted to \\". + // Revert to double quote. + $output = str_replace('\\"', '"', $output); + // Revert of doubled backslashes. + $output = preg_replace('#\\\\{2}#', '\\', $output); + } + $output = $this->removeNonJsonJunk($output); + $json = json_decode($output, true); + if (!isset($json)) { + throw new \InvalidArgumentException('Unable to decode output into JSON.'); + } + return $json; + } + + /** + * Allow for a certain amount of resiliancy in the output received when + * json is expected. + * + * @param string $data + * @return string + */ + protected function removeNonJsonJunk($data) + { + // Exit early if we have no output. + $data = trim($data); + if (empty($data)) { + return $data; + } + // If the data is a simple quoted string, or an array, then exit. + if ((($data[0] == '"') && ($data[strlen($data) - 1] == '"')) || + (($data[0] == "[") && ($data[strlen($data) - 1] == "]")) + ) { + return $data; + } + // If the json is not a simple string or a simple array, then is must + // be an associative array. We will remove non-json garbage characters + // before and after the enclosing curley-braces. + $start = strpos($data, '{'); + $end = strrpos($data, '}') + 1; + $data = substr($data, $start, $end - $start); + return $data; + } + + /** + * Return a realTime output object. + * + * @return callable + */ + public function showRealtime() + { + $realTimeOutput = new RealtimeOutputHandler($this->realtimeStdout(), $this->realtimeStderr()); + $realTimeOutput->configure($this); + return $realTimeOutput; + } +}