Initial Drupal 11 with DDEV setup
This commit is contained in:
31
vendor/consolidation/site-process/src/Factory/DockerComposeTransportFactory.php
vendored
Normal file
31
vendor/consolidation/site-process/src/Factory/DockerComposeTransportFactory.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Factory;
|
||||
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Transport\DockerComposeTransport;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* DockerComposeTransportFactory will create an DockerComposeTransport for
|
||||
* applicable site aliases.
|
||||
*/
|
||||
class DockerComposeTransportFactory implements TransportFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function check(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
// TODO: deprecate and eventually remove 'isContainer()', and move the logic here.
|
||||
return $siteAlias->isContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function create(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
return new DockerComposeTransport($siteAlias);
|
||||
}
|
||||
}
|
||||
28
vendor/consolidation/site-process/src/Factory/KubectlTransportFactory.php
vendored
Normal file
28
vendor/consolidation/site-process/src/Factory/KubectlTransportFactory.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Factory;
|
||||
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Transport\KubectlTransport;
|
||||
|
||||
/**
|
||||
* KubectlTransportFactory will create an KubectlTransport for applicable site aliases.
|
||||
*/
|
||||
class KubectlTransportFactory implements TransportFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function check(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
return $siteAlias->has('kubectl');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function create(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
return new KubectlTransport($siteAlias);
|
||||
}
|
||||
}
|
||||
28
vendor/consolidation/site-process/src/Factory/SkprTransportFactory.php
vendored
Normal file
28
vendor/consolidation/site-process/src/Factory/SkprTransportFactory.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Factory;
|
||||
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Transport\SkprTransport;
|
||||
|
||||
/**
|
||||
* SkprTransportFactory will create an SkprTransport for applicable site aliases.
|
||||
*/
|
||||
class SkprTransportFactory implements TransportFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function check(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
return $siteAlias->has('skpr');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function create(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
return new SkprTransport($siteAlias);
|
||||
}
|
||||
}
|
||||
30
vendor/consolidation/site-process/src/Factory/SshTransportFactory.php
vendored
Normal file
30
vendor/consolidation/site-process/src/Factory/SshTransportFactory.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Factory;
|
||||
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Transport\SshTransport;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* SshTransportFactory will create an SshTransport for applicable site aliases.
|
||||
*/
|
||||
class SshTransportFactory implements TransportFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function check(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
// TODO: deprecate and eventually remove 'isRemote()', and move the logic here.
|
||||
return $siteAlias->isRemote();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function create(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
return new SshTransport($siteAlias);
|
||||
}
|
||||
}
|
||||
34
vendor/consolidation/site-process/src/Factory/TransportFactoryInterface.php
vendored
Normal file
34
vendor/consolidation/site-process/src/Factory/TransportFactoryInterface.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Factory;
|
||||
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Transport\TransportInterface;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* TransportFactoryInterface defines a transport factory that is responsible
|
||||
* for:
|
||||
*
|
||||
* - Determining whether a provided site alias is applicable to this transport
|
||||
* - Creating an instance of a transport for an applicable site alias.
|
||||
*
|
||||
* There is always a transport for every factory, and visa-versa.
|
||||
* @see Consolidation\SiteProcess\Transport\TransportInterface
|
||||
*/
|
||||
interface TransportFactoryInterface
|
||||
{
|
||||
/**
|
||||
* Check to see if a provided site alias is applicable to this transport type.
|
||||
* @param SiteAliasInterface $siteAlias
|
||||
* @return bool
|
||||
*/
|
||||
public function check(SiteAliasInterface $siteAlias);
|
||||
|
||||
/**
|
||||
* Create a transport instance for an applicable site alias.
|
||||
* @param SiteAliasInterface $siteAlias
|
||||
* @return TransportInterface
|
||||
*/
|
||||
public function create(SiteAliasInterface $siteAlias);
|
||||
}
|
||||
28
vendor/consolidation/site-process/src/Factory/VagrantTransportFactory.php
vendored
Normal file
28
vendor/consolidation/site-process/src/Factory/VagrantTransportFactory.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Factory;
|
||||
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Transport\VagrantTransport;
|
||||
|
||||
/**
|
||||
* VagrantTransportFactory will create a VagrantTransport for applicable site aliases.
|
||||
*/
|
||||
class VagrantTransportFactory implements TransportFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function check(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
return $siteAlias->has('vagrant');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function create(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
return new VagrantTransport($siteAlias);
|
||||
}
|
||||
}
|
||||
235
vendor/consolidation/site-process/src/ProcessBase.php
vendored
Normal file
235
vendor/consolidation/site-process/src/ProcessBase.php
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* 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, array $env = []): void
|
||||
{
|
||||
$cmd = $this->getCommandLine();
|
||||
if ($this->isSimulated()) {
|
||||
$this->getLogger()->notice('Simulating: ' . $cmd);
|
||||
// Run a command that always succeeds (on Linux and Windows).
|
||||
$this->overrideCommandLine('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->overrideCommandLine($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);
|
||||
}
|
||||
$sanitizedOutput = $this->removeNonJsonJunk($output);
|
||||
$json = json_decode($sanitizedOutput, true);
|
||||
if (!isset($json)) {
|
||||
$msg = 'Unable to decode output into JSON: ' . json_last_error_msg();
|
||||
if (json_last_error() == JSON_ERROR_SYNTAX) {
|
||||
$msg .= "\n\n$output";
|
||||
}
|
||||
throw new \InvalidArgumentException($msg);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the command line to be executed.
|
||||
*
|
||||
* @param string|array $commandline The command to execute
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @todo refactor library so this hack to get around changes in
|
||||
* symfony/process 5 is unnecessary.
|
||||
*/
|
||||
private function overrideCommandLine($commandline)
|
||||
{
|
||||
$commandlineSetter = function ($commandline) {
|
||||
$this->commandline = $commandline;
|
||||
};
|
||||
$commandlineSetter->bindTo($this, Process::class)($commandline);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
180
vendor/consolidation/site-process/src/ProcessManager.php
vendored
Normal file
180
vendor/consolidation/site-process/src/ProcessManager.php
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess;
|
||||
|
||||
use Consolidation\SiteProcess\Factory\KubectlTransportFactory;
|
||||
use Consolidation\SiteProcess\Factory\SkprTransportFactory;
|
||||
use Consolidation\SiteProcess\Factory\VagrantTransportFactory;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Factory\SshTransportFactory;
|
||||
use Consolidation\SiteProcess\Factory\DockerComposeTransportFactory;
|
||||
use Consolidation\SiteProcess\Factory\TransportFactoryInterface;
|
||||
use Consolidation\SiteProcess\Transport\LocalTransport;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
use Consolidation\Config\ConfigAwareInterface;
|
||||
use Consolidation\Config\ConfigAwareTrait;
|
||||
use Consolidation\SiteAlias\SiteAliasWithConfig;
|
||||
|
||||
/**
|
||||
* ProcessManager will create a SiteProcess to run a command on a given
|
||||
* site as indicated by a SiteAlias.
|
||||
*
|
||||
* ProcessManager also manages a collection of transport factories, and
|
||||
* will produce transport instances as needed for provided site aliases.
|
||||
*/
|
||||
class ProcessManager implements ConfigAwareInterface
|
||||
{
|
||||
use ConfigAwareTrait;
|
||||
|
||||
/** @var ConfigInterface */
|
||||
protected $configRuntime;
|
||||
|
||||
protected $transportFactories = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = new Config();
|
||||
$this->configRuntime = new Config();
|
||||
}
|
||||
|
||||
/**
|
||||
* setConfigRuntime sets the config object that holds runtime config
|
||||
* items, i.e. config set from the commandline rather than a config file.
|
||||
* Configuration priority (highest to lowest) is:
|
||||
* - config runtime
|
||||
* - site alias
|
||||
* - config files
|
||||
*/
|
||||
public function setConfigRuntime(ConfigInterface $configRuntime)
|
||||
{
|
||||
$this->configRuntime = $configRuntime;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* createDefault creates a Transport manager and add the default transports to it.
|
||||
*/
|
||||
public static function createDefault()
|
||||
{
|
||||
$processManager = new self();
|
||||
return static::addTransports($processManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* addTransports adds the avaiable transports to the
|
||||
* provided process manager.
|
||||
*/
|
||||
public static function addTransports(ProcessManager $processManager)
|
||||
{
|
||||
$processManager->add(new SshTransportFactory());
|
||||
$processManager->add(new KubectlTransportFactory());
|
||||
$processManager->add(new SkprTransportFactory());
|
||||
$processManager->add(new DockerComposeTransportFactory());
|
||||
$processManager->add(new VagrantTransportFactory());
|
||||
|
||||
return $processManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a site process configured with an appropriate transport
|
||||
*
|
||||
* @param SiteAliasInterface $siteAlias Target for command
|
||||
* @param array $args Command arguments
|
||||
* @param array $options Associative array of command options
|
||||
* @param array $optionsPassedAsArgs Associtive array of options to be passed as arguments (after double-dash)
|
||||
* @return Process
|
||||
*/
|
||||
public function siteProcess(SiteAliasInterface $siteAlias, $args = [], $options = [], $optionsPassedAsArgs = [])
|
||||
{
|
||||
$transport = $this->getTransport($siteAlias);
|
||||
$process = new SiteProcess($siteAlias, $transport, $args, $options, $optionsPassedAsArgs);
|
||||
return $process;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Process instance from a commandline string.
|
||||
* @param array $command The command to run and its arguments listed as separate entries
|
||||
* @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 function process($command, $cwd = null, ?array $env = null, $input = null, $timeout = 60)
|
||||
{
|
||||
return new ProcessBase($command, $cwd, $env, $input, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Process instance from a commandline string.
|
||||
* @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 function shell($command, $cwd = null, ?array $env = null, $input = null, $timeout = 60)
|
||||
{
|
||||
return ProcessBase::fromShellCommandline($command, $cwd, $env, $input, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a transport factory to our factory list
|
||||
* @param TransportFactoryInterface $factory
|
||||
*/
|
||||
public function add(TransportFactoryInterface $factory)
|
||||
{
|
||||
$this->transportFactories[] = $factory;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* hasTransport determines if there is a transport that handles the
|
||||
* provided site alias.
|
||||
*
|
||||
* @param SiteAliasInterface $siteAlias
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasTransport(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
return $this->getTransportFactory($siteAlias) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* getTransport returns a transport that is applicable to the provided site alias.
|
||||
*
|
||||
* @param SiteAliasInterface $siteAlias
|
||||
* @return TransportInterface
|
||||
*/
|
||||
public function getTransport(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
$factory = $this->getTransportFactory($siteAlias);
|
||||
|
||||
$siteAliasWithConfig = SiteAliasWithConfig::create($siteAlias, $this->config, $this->configRuntime);
|
||||
|
||||
if ($factory) {
|
||||
return $factory->create($siteAliasWithConfig);
|
||||
}
|
||||
return new LocalTransport();
|
||||
}
|
||||
|
||||
/**
|
||||
* getTransportFactory returns a factory for the provided site alias.
|
||||
*
|
||||
* @param SiteAliasInterface $siteAlias
|
||||
* @return TransportFactoryInterface
|
||||
*/
|
||||
protected function getTransportFactory(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
foreach ($this->transportFactories as $factory) {
|
||||
if ($factory->check($siteAlias)) {
|
||||
return $factory;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
23
vendor/consolidation/site-process/src/ProcessManagerAwareInterface.php
vendored
Normal file
23
vendor/consolidation/site-process/src/ProcessManagerAwareInterface.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace Consolidation\SiteProcess;
|
||||
|
||||
/**
|
||||
* Inflection interface for the site alias manager.
|
||||
*/
|
||||
interface ProcessManagerAwareInterface
|
||||
{
|
||||
/**
|
||||
* @param ProcessManager $processManager
|
||||
*/
|
||||
public function setProcessManager(ProcessManager $processManager);
|
||||
|
||||
/**
|
||||
* @return ProcessManager
|
||||
*/
|
||||
public function processManager();
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasProcessManager();
|
||||
}
|
||||
34
vendor/consolidation/site-process/src/ProcessManagerAwareTrait.php
vendored
Normal file
34
vendor/consolidation/site-process/src/ProcessManagerAwareTrait.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace Consolidation\SiteProcess;
|
||||
|
||||
/**
|
||||
* Inflection trait for the site alias manager.
|
||||
*/
|
||||
trait ProcessManagerAwareTrait
|
||||
{
|
||||
protected $processManager;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function setProcessManager(ProcessManager $processManager)
|
||||
{
|
||||
$this->processManager = $processManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ProcessManager
|
||||
*/
|
||||
public function processManager()
|
||||
{
|
||||
return $this->processManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function hasProcessManager()
|
||||
{
|
||||
return isset($this->processManager);
|
||||
}
|
||||
}
|
||||
278
vendor/consolidation/site-process/src/SiteProcess.php
vendored
Normal file
278
vendor/consolidation/site-process/src/SiteProcess.php
vendored
Normal file
@ -0,0 +1,278 @@
|
||||
<?php
|
||||
namespace Consolidation\SiteProcess;
|
||||
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Transport\DockerComposeTransport;
|
||||
use Consolidation\SiteProcess\Util\ArgumentProcessor;
|
||||
use Consolidation\SiteProcess\Transport\LocalTransport;
|
||||
use Consolidation\SiteProcess\Transport\SshTransport;
|
||||
use Consolidation\SiteProcess\Transport\TransportInterface;
|
||||
use Consolidation\Config\Util\Interpolator;
|
||||
use Consolidation\SiteProcess\Util\Shell;
|
||||
use Consolidation\SiteProcess\Util\ShellOperatorInterface;
|
||||
use Consolidation\SiteProcess\Util\Escape;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
/**
|
||||
* A wrapper around Symfony Process that uses site aliases
|
||||
* (https://github.com/consolidation/site-alias)
|
||||
*
|
||||
* - Interpolate arguments using values from the alias
|
||||
* e.g. `$process = new SiteProcess($alias, ['git', '-C', '{{root}}']);`
|
||||
* - Make remote calls via ssh as if they were local.
|
||||
*/
|
||||
class SiteProcess extends ProcessBase
|
||||
{
|
||||
/** @var SiteAliasInterface */
|
||||
protected $siteAlias;
|
||||
/** @var string[] */
|
||||
protected $args;
|
||||
/** @var string[] */
|
||||
protected $options;
|
||||
/** @var string[] */
|
||||
protected $optionsPassedAsArgs;
|
||||
/** @var string */
|
||||
protected $cd_remote;
|
||||
/** @var TransportInterface */
|
||||
protected $transport;
|
||||
|
||||
/**
|
||||
* Process arguments and options per the site alias and build the
|
||||
* actual command to run.
|
||||
*/
|
||||
public function __construct(SiteAliasInterface $siteAlias, TransportInterface $transport, $args, $options = [], $optionsPassedAsArgs = [])
|
||||
{
|
||||
$this->siteAlias = $siteAlias;
|
||||
$this->transport = $transport;
|
||||
$this->args = $args;
|
||||
$this->options = $options;
|
||||
$this->optionsPassedAsArgs = $optionsPassedAsArgs;
|
||||
|
||||
parent::__construct([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a starting directory for the remote process.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getWorkingDirectory(): ?string
|
||||
{
|
||||
return $this->cd_remote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a starting directory for the remote process.
|
||||
*
|
||||
* @param string $cd_remote
|
||||
*
|
||||
* @return \Consolidation\SiteProcess\SiteProcess
|
||||
*/
|
||||
public function setWorkingDirectory($cd_remote): static
|
||||
{
|
||||
$this->cd_remote = $cd_remote;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a starting directory for the initial/local process.
|
||||
*
|
||||
* @param string $cd
|
||||
*
|
||||
* @return \Consolidation\SiteProcess\SiteProcess
|
||||
*/
|
||||
public function setWorkingDirectoryLocal($cd)
|
||||
{
|
||||
// Symfony 4 REQUIRES that there be a directory set, and defaults
|
||||
// it to the cwd if it is not set. We will maintain that pattern here.
|
||||
if (!$cd) {
|
||||
$cd = getcwd();
|
||||
}
|
||||
return parent::setWorkingDirectory($cd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the starting directory for the initial/local process.
|
||||
*
|
||||
* @return string|null;
|
||||
*/
|
||||
public function getWorkingDirectoryLocal()
|
||||
{
|
||||
return parent::getWorkingDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param bool $shouldUseSiteRoot
|
||||
* @return $this|\Symfony\Component\Process\Process
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function chdirToSiteRoot($shouldUseSiteRoot = true)
|
||||
{
|
||||
if (!$shouldUseSiteRoot || !$this->siteAlias->hasRoot()) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this->setWorkingDirectory($this->siteAlias->root());
|
||||
}
|
||||
|
||||
/**
|
||||
* Take all of our individual arguments and process them for use.
|
||||
*/
|
||||
protected function processArgs()
|
||||
{
|
||||
$transport = $this->getTransport($this->siteAlias);
|
||||
$transport->configure($this);
|
||||
|
||||
$processor = new ArgumentProcessor();
|
||||
$selectedArgs = $processor->selectArgs(
|
||||
$this->siteAlias,
|
||||
$this->args,
|
||||
$this->options,
|
||||
$this->optionsPassedAsArgs
|
||||
);
|
||||
|
||||
// Set environment variables if needed.
|
||||
if ($this->siteAlias->has('env-vars')) {
|
||||
$selectedArgs = $this->addEnvVars($this->siteAlias->get('env-vars'), $selectedArgs);
|
||||
}
|
||||
|
||||
// Ask the transport to drop in a 'cd' if needed.
|
||||
if ($this->getWorkingDirectory()) {
|
||||
$selectedArgs = $transport->addChdir($this->getWorkingDirectory(), $selectedArgs);
|
||||
}
|
||||
|
||||
// Do any necessary interpolation on the selected arguments.
|
||||
$processedArgs = $this->interpolate($selectedArgs);
|
||||
|
||||
// Wrap the command with 'ssh' or some other transport if this is
|
||||
// a remote command; otherwise, leave it as-is.
|
||||
return $transport->wrap($processedArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the command/args in an env call.
|
||||
* @todo Check if this needs to depend on linux/win.
|
||||
* @todo Check if this needs to be delegated to transport.
|
||||
*/
|
||||
public function addEnvVars($envVars, $args)
|
||||
{
|
||||
$envArgs = ['env'];
|
||||
foreach ($envVars as $key => $value) {
|
||||
$envArgs[] = Escape::forSite($this->siteAlias, $key) . '='
|
||||
. Escape::forSite($this->siteAlias, $value);
|
||||
}
|
||||
return array_merge($envArgs, $args);
|
||||
}
|
||||
|
||||
public function setTransport($transport)
|
||||
{
|
||||
$this->transport = $transport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the transport manager for the correct transport for the
|
||||
* provided alias.
|
||||
*/
|
||||
protected function getTransport(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
return $this->transport;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getCommandLine(): string
|
||||
{
|
||||
$commandLine = parent::getCommandLine();
|
||||
if (empty($commandLine)) {
|
||||
$processedArgs = $this->processArgs();
|
||||
$commandLine = Escape::argsForSite($this->siteAlias, $processedArgs);
|
||||
$commandLine = implode(' ', $commandLine);
|
||||
$this->overrideCommandLine($commandLine);
|
||||
}
|
||||
return $commandLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function start(?callable $callback = null, array $env = []): void
|
||||
{
|
||||
$cmd = $this->getCommandLine();
|
||||
parent::start($callback, $env);
|
||||
}
|
||||
|
||||
public function mustRun(?callable $callback = null, array $env = []): static
|
||||
{
|
||||
if (0 !== $this->run($callback, $env)) {
|
||||
// Be less verbose when there is nothing in stdout or stderr.
|
||||
if (empty($this->getOutput()) && empty($this->getErrorOutput())) {
|
||||
$this->disableOutput();
|
||||
}
|
||||
throw new ProcessFailedException($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function wait(?callable $callback = null): int
|
||||
{
|
||||
$return = parent::wait($callback);
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* interpolate examines each of the arguments in the provided argument list
|
||||
* and replaces any token found therein with the value for that key as
|
||||
* pulled from the given site alias.
|
||||
*
|
||||
* Example: "git -C {{root}} status"
|
||||
*
|
||||
* The token "{{root}}" will be converted to a value via $siteAlias->get('root').
|
||||
* The result will replace the token.
|
||||
*
|
||||
* It is possible to use dot notation in the keys to access nested elements
|
||||
* within the site alias record.
|
||||
*
|
||||
* @param SiteAliasInterface $siteAlias
|
||||
* @param type $args
|
||||
* @return type
|
||||
*/
|
||||
protected function interpolate($args)
|
||||
{
|
||||
$interpolator = new Interpolator();
|
||||
return array_map(
|
||||
function ($arg) use ($interpolator) {
|
||||
if ($arg instanceof ShellOperatorInterface) {
|
||||
return $arg;
|
||||
}
|
||||
return $interpolator->interpolate($this->siteAlias, $arg, false);
|
||||
},
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the command line to be executed.
|
||||
*
|
||||
* @param string|array $commandline The command to execute
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @todo refactor library so this hack to get around changes in
|
||||
* symfony/process 5 is unnecessary.
|
||||
*/
|
||||
private function overrideCommandLine($commandline)
|
||||
{
|
||||
$commandlineSetter = function ($commandline) {
|
||||
$this->commandline = $commandline;
|
||||
};
|
||||
$commandlineSetter->bindTo($this, Process::class)($commandline);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
113
vendor/consolidation/site-process/src/Transport/DockerComposeTransport.php
vendored
Normal file
113
vendor/consolidation/site-process/src/Transport/DockerComposeTransport.php
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Transport;
|
||||
|
||||
use Consolidation\SiteProcess\SiteProcess;
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Util\Shell;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* DockerComposeTransport knows how to wrap a command such that it executes
|
||||
* on a Docker Compose service.
|
||||
*/
|
||||
class DockerComposeTransport implements TransportInterface
|
||||
{
|
||||
protected $tty;
|
||||
protected $siteAlias;
|
||||
protected $cd_remote;
|
||||
|
||||
public function __construct(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
$this->siteAlias = $siteAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function configure(SiteProcess $process)
|
||||
{
|
||||
$this->tty = $process->isTty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function wrap($args)
|
||||
{
|
||||
$transport = $this->getTransport();
|
||||
$transportOptions = $this->getTransportOptions();
|
||||
$commandToExecute = $this->getCommandToExecute($args);
|
||||
|
||||
return array_merge(
|
||||
$transport,
|
||||
$transportOptions,
|
||||
$commandToExecute
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function addChdir($cd, $args)
|
||||
{
|
||||
$this->cd_remote = $cd;
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* getTransport returns the transport along with the docker-compose
|
||||
* project in case it is defined.
|
||||
*/
|
||||
protected function getTransport()
|
||||
{
|
||||
$version = $this->siteAlias->get('docker.compose.version', '1');
|
||||
if ($version == 2) {
|
||||
$transport = ['docker', 'compose'];
|
||||
} else {
|
||||
$transport = ['docker-compose'];
|
||||
}
|
||||
$project = $this->siteAlias->get('docker.project', '');
|
||||
$options = $this->siteAlias->get('docker.compose.options', '');
|
||||
$command = $this->siteAlias->get('docker.compose.command', 'exec');
|
||||
if ($project && (strpos($options, '-p') === false || strpos($options, '--project') === false)) {
|
||||
$transport = array_merge($transport, ['-p', $project]);
|
||||
}
|
||||
if ($options) {
|
||||
$transport[] = Shell::preEscaped($options);
|
||||
}
|
||||
return array_merge($transport, [$command]);
|
||||
}
|
||||
|
||||
/**
|
||||
* getTransportOptions returns the transport options for the tranport
|
||||
* mechanism itself
|
||||
*/
|
||||
protected function getTransportOptions()
|
||||
{
|
||||
$transportOptions = [
|
||||
$this->siteAlias->get('docker.service', ''),
|
||||
];
|
||||
if ($options = $this->siteAlias->get('docker.exec.options', '')) {
|
||||
array_unshift($transportOptions, Shell::preEscaped($options));
|
||||
}
|
||||
if (!$this->tty) {
|
||||
array_unshift($transportOptions, '-T');
|
||||
}
|
||||
if ($this->cd_remote) {
|
||||
$transportOptions = array_merge(['--workdir', $this->cd_remote], $transportOptions);
|
||||
}
|
||||
return array_filter($transportOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* getCommandToExecute processes the arguments for the command to
|
||||
* be executed such that they are appropriate for the transport mechanism.
|
||||
*
|
||||
* Nothing to do for this transport.
|
||||
*/
|
||||
protected function getCommandToExecute($args)
|
||||
{
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
84
vendor/consolidation/site-process/src/Transport/KubectlTransport.php
vendored
Normal file
84
vendor/consolidation/site-process/src/Transport/KubectlTransport.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Transport;
|
||||
|
||||
use Consolidation\SiteProcess\SiteProcess;
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Util\Shell;
|
||||
|
||||
/**
|
||||
* KubectlTransport knows how to wrap a command such that it runs in a container
|
||||
* on Kubernetes via kubectl.
|
||||
*/
|
||||
class KubectlTransport implements TransportInterface
|
||||
{
|
||||
/** @var bool */
|
||||
protected $tty;
|
||||
|
||||
/** @var \Consolidation\SiteAlias\SiteAliasInterface */
|
||||
protected $siteAlias;
|
||||
|
||||
public function __construct(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
$this->siteAlias = $siteAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function configure(SiteProcess $process)
|
||||
{
|
||||
$this->tty = $process->isTty();
|
||||
}
|
||||
|
||||
/**
|
||||
* inheritdoc
|
||||
*/
|
||||
public function wrap($args)
|
||||
{
|
||||
# TODO: How/where do we complain if a required argument is not available?
|
||||
$namespace = $this->siteAlias->get('kubectl.namespace');
|
||||
$tty = $this->tty && $this->siteAlias->get('kubectl.tty', false) ? "true" : "false";
|
||||
$interactive = $this->tty && $this->siteAlias->get('kubectl.interactive', false) ? "true" : "false";
|
||||
$resource = $this->siteAlias->get('kubectl.resource');
|
||||
$container = $this->siteAlias->get('kubectl.container');
|
||||
$kubeconfig = $this->siteAlias->get('kubectl.kubeconfig');
|
||||
$entrypoint = $this->siteAlias->get('kubectl.entrypoint');
|
||||
|
||||
$transport = [
|
||||
'kubectl',
|
||||
"--namespace=$namespace",
|
||||
'exec',
|
||||
"--tty=$tty",
|
||||
"--stdin=$interactive",
|
||||
$resource,
|
||||
];
|
||||
if ($container) {
|
||||
$transport[] = "--container=$container";
|
||||
}
|
||||
if ($kubeconfig) {
|
||||
$transport[] = "--kubeconfig=$kubeconfig";
|
||||
}
|
||||
$transport[] = "--";
|
||||
if ($entrypoint) {
|
||||
$transport = is_array($entrypoint) ? [...$transport, ...$entrypoint] : [...$transport, $entrypoint];
|
||||
}
|
||||
|
||||
return array_merge($transport, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function addChdir($cd_remote, $args)
|
||||
{
|
||||
return array_merge(
|
||||
[
|
||||
'cd',
|
||||
$cd_remote,
|
||||
Shell::op('&&'),
|
||||
],
|
||||
$args
|
||||
);
|
||||
}
|
||||
}
|
||||
35
vendor/consolidation/site-process/src/Transport/LocalTransport.php
vendored
Normal file
35
vendor/consolidation/site-process/src/Transport/LocalTransport.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Transport;
|
||||
|
||||
use Consolidation\SiteProcess\SiteProcess;
|
||||
|
||||
/**
|
||||
* LocalTransport just runs the command on the local system.
|
||||
*/
|
||||
class LocalTransport implements TransportInterface
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function configure(SiteProcess $process)
|
||||
{
|
||||
$process->setWorkingDirectoryLocal($process->getWorkingDirectory());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function wrap($args)
|
||||
{
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function addChdir($cd, $args)
|
||||
{
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
66
vendor/consolidation/site-process/src/Transport/SkprTransport.php
vendored
Normal file
66
vendor/consolidation/site-process/src/Transport/SkprTransport.php
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Transport;
|
||||
|
||||
use Consolidation\SiteProcess\SiteProcess;
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Util\Shell;
|
||||
|
||||
/**
|
||||
* SkprTransport knows how to wrap a command to run on a site hosted
|
||||
* on the Skpr platform.
|
||||
*/
|
||||
class SkprTransport implements TransportInterface
|
||||
{
|
||||
|
||||
/** @var \Consolidation\SiteAlias\SiteAliasInterface */
|
||||
protected $siteAlias;
|
||||
|
||||
public function __construct(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
$this->siteAlias = $siteAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function configure(SiteProcess $process)
|
||||
{
|
||||
$path = $this->siteAlias->getDefault('skpr.path', getcwd());
|
||||
if ($path) {
|
||||
$process->chdirToSiteRoot($path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* inheritdoc
|
||||
*/
|
||||
public function wrap($args)
|
||||
{
|
||||
$environment = $this->siteAlias->get('skpr.env');
|
||||
|
||||
$transport = [
|
||||
'skpr',
|
||||
'exec',
|
||||
"$environment",
|
||||
];
|
||||
$transport[] = "--";
|
||||
|
||||
return array_merge($transport, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function addChdir($cd_remote, $args)
|
||||
{
|
||||
return array_merge(
|
||||
[
|
||||
'cd',
|
||||
$cd_remote,
|
||||
Shell::op('&&'),
|
||||
],
|
||||
$args
|
||||
);
|
||||
}
|
||||
}
|
||||
92
vendor/consolidation/site-process/src/Transport/SshTransport.php
vendored
Normal file
92
vendor/consolidation/site-process/src/Transport/SshTransport.php
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Transport;
|
||||
|
||||
use Consolidation\SiteProcess\SiteProcess;
|
||||
use Consolidation\SiteProcess\Util\Escape;
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Util\Shell;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* SshTransport knows how to wrap a command such that it runs on a remote
|
||||
* system via the ssh cli.
|
||||
*/
|
||||
class SshTransport implements TransportInterface
|
||||
{
|
||||
protected $tty;
|
||||
protected $siteAlias;
|
||||
|
||||
public function __construct(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
$this->siteAlias = $siteAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function configure(SiteProcess $process)
|
||||
{
|
||||
$this->tty = $process->isTty();
|
||||
}
|
||||
|
||||
/**
|
||||
* inheritdoc
|
||||
*/
|
||||
public function wrap($args)
|
||||
{
|
||||
$transport = ['ssh'];
|
||||
$transportOptions = $this->getTransportOptions();
|
||||
$commandToExecute = $this->getCommandToExecute($args);
|
||||
|
||||
return array_merge(
|
||||
$transport,
|
||||
$transportOptions,
|
||||
$commandToExecute
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function addChdir($cd_remote, $args)
|
||||
{
|
||||
return array_merge(
|
||||
[
|
||||
'cd',
|
||||
$cd_remote,
|
||||
Shell::op('&&'),
|
||||
],
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* getTransportOptions returns the transport options for the tranport
|
||||
* mechanism itself
|
||||
*/
|
||||
protected function getTransportOptions()
|
||||
{
|
||||
$transportOptions = [
|
||||
Shell::preEscaped($this->siteAlias->get('ssh.options', '-o PasswordAuthentication=no')),
|
||||
$this->siteAlias->remoteHostWithUser(),
|
||||
];
|
||||
if ($this->tty) {
|
||||
array_unshift($transportOptions, '-t');
|
||||
}
|
||||
return $transportOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* getCommandToExecute processes the arguments for the command to
|
||||
* be executed such that they are appropriate for the transport mechanism.
|
||||
*/
|
||||
protected function getCommandToExecute($args)
|
||||
{
|
||||
// Escape each argument for the target system and then join
|
||||
$args = Escape::argsForSite($this->siteAlias, $args);
|
||||
$commandToExecute = implode(' ', $args);
|
||||
|
||||
return [$commandToExecute];
|
||||
}
|
||||
}
|
||||
40
vendor/consolidation/site-process/src/Transport/TransportInterface.php
vendored
Normal file
40
vendor/consolidation/site-process/src/Transport/TransportInterface.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Transport;
|
||||
|
||||
use Consolidation\SiteProcess\SiteProcess;
|
||||
|
||||
/**
|
||||
* Transports know how to wrap a command such that it runs on a remote system
|
||||
* via some other command.
|
||||
*
|
||||
* There is always a transport for every factory, and visa-versa.
|
||||
*
|
||||
* @see Consolidation\SiteProcess\Factory\TransportFactoryInterface
|
||||
*/
|
||||
interface TransportInterface
|
||||
{
|
||||
/**
|
||||
* Configure ourselves based on the settings of the process object
|
||||
* (e.g. isTty()).
|
||||
*
|
||||
* @param \Consolidation\SiteProcess\SiteProcess $process
|
||||
*/
|
||||
public function configure(SiteProcess $process);
|
||||
|
||||
/**
|
||||
* wrapWithTransport examines the provided site alias; if it is a local
|
||||
* alias, then the provided arguments are returned unmodified. If the
|
||||
* alias points at a remote system, though, then the arguments are
|
||||
* escaped and wrapped in an appropriate ssh command.
|
||||
*
|
||||
* @param array $args arguments provided by caller.
|
||||
* @return array command and arguments to execute.
|
||||
*/
|
||||
public function wrap($args);
|
||||
|
||||
/**
|
||||
* addChdir adds an appropriate 'chdir' / 'cd' command for the transport.
|
||||
*/
|
||||
public function addChdir($cd, $args);
|
||||
}
|
||||
85
vendor/consolidation/site-process/src/Transport/VagrantTransport.php
vendored
Normal file
85
vendor/consolidation/site-process/src/Transport/VagrantTransport.php
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\SiteProcess\Transport;
|
||||
|
||||
use Consolidation\SiteProcess\SiteProcess;
|
||||
use Consolidation\SiteProcess\Util\Escape;
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Consolidation\SiteProcess\Util\Shell;
|
||||
|
||||
/**
|
||||
* VagrantTransport knows how to wrap a command such that it runs on a remote
|
||||
* system via the vagrant cli.
|
||||
*/
|
||||
class VagrantTransport implements TransportInterface
|
||||
{
|
||||
protected $tty;
|
||||
protected $siteAlias;
|
||||
|
||||
public function __construct(SiteAliasInterface $siteAlias)
|
||||
{
|
||||
$this->siteAlias = $siteAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function configure(SiteProcess $process)
|
||||
{
|
||||
$this->tty = $process->isTty();
|
||||
}
|
||||
|
||||
/**
|
||||
* inheritdoc
|
||||
*/
|
||||
public function wrap($args)
|
||||
{
|
||||
$transport = ['vagrant', 'ssh'];
|
||||
$transportOptions = $this->getTransportOptions();
|
||||
$commandToExecute = $this->getCommandToExecute($args);
|
||||
|
||||
return array_merge(
|
||||
$transport,
|
||||
$transportOptions,
|
||||
['-c'],
|
||||
$commandToExecute
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function addChdir($cd_remote, $args)
|
||||
{
|
||||
return array_merge(
|
||||
[
|
||||
'cd',
|
||||
$cd_remote,
|
||||
Shell::op('&&'),
|
||||
],
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* getTransportOptions returns the transport options for the tranport
|
||||
* mechanism itself
|
||||
*/
|
||||
protected function getTransportOptions()
|
||||
{
|
||||
return $this->tty ? ['-t'] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* getCommandToExecute processes the arguments for the command to
|
||||
* be executed such that they are appropriate for the transport mechanism.
|
||||
*/
|
||||
protected function getCommandToExecute($args)
|
||||
{
|
||||
// Escape each argument for the target system and then join
|
||||
$args = Escape::argsForSite($this->siteAlias, $args);
|
||||
$commandToExecute = implode(' ', $args);
|
||||
|
||||
return [$commandToExecute];
|
||||
}
|
||||
}
|
||||
113
vendor/consolidation/site-process/src/Util/ArgumentProcessor.php
vendored
Normal file
113
vendor/consolidation/site-process/src/Util/ArgumentProcessor.php
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
namespace Consolidation\SiteProcess\Util;
|
||||
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Consolidation\SiteProcess\Transport\TransportInterface;
|
||||
|
||||
/**
|
||||
* ArgumentProcessor takes a set of arguments and options from the caller
|
||||
* and processes them with the provided site alias to produce a final
|
||||
* executable command that will run either locally or on a remote system,
|
||||
* as applicable.
|
||||
*/
|
||||
class ArgumentProcessor
|
||||
{
|
||||
private $short_options = ['vv', 'vvv'];
|
||||
|
||||
public function getShortOptions(): array
|
||||
{
|
||||
return $this->short_options;
|
||||
}
|
||||
|
||||
public function setShortOptions(array $short_options): void
|
||||
{
|
||||
$this->short_options = $short_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* selectArgs selects the appropriate set of arguments for the command
|
||||
* to be executed and orders them as needed.
|
||||
*
|
||||
* @param SiteAliasInterface $siteAlias Description of
|
||||
* @param array $args Command and arguments to execute (source)
|
||||
* @param array $options key / value pair of option and value in include
|
||||
* in final arguments
|
||||
* @param array $optionsPassedAsArgs key / value pair of option and value
|
||||
* to include in final arguments after the '--' argument.
|
||||
* @return array Command and arguments to execute
|
||||
*/
|
||||
public function selectArgs(SiteAliasInterface $siteAlias, $args, $options = [], $optionsPassedAsArgs = [])
|
||||
{
|
||||
// Split args into three arrays separated by the `--`
|
||||
list($leadingArgs, $dashDash, $remaingingArgs) = $this->findArgSeparator($args);
|
||||
$convertedOptions = $this->convertOptions($options);
|
||||
$convertedOptionsPassedAsArgs = $this->convertOptions($optionsPassedAsArgs);
|
||||
|
||||
// If the caller provided options that should be passed as args, then we
|
||||
// always need a `--`, whether or not one existed to begin with in $args
|
||||
if (!empty($convertedOptionsPassedAsArgs)) {
|
||||
$dashDash = ['--'];
|
||||
}
|
||||
|
||||
// Combine our separated args in the correct order. $dashDash will
|
||||
// always be `['--']` if $optionsPassedAsArgs or $remaingingArgs are
|
||||
// not empty, and otherwise will usually be empty.
|
||||
return array_merge(
|
||||
$leadingArgs,
|
||||
$convertedOptions,
|
||||
$dashDash,
|
||||
$convertedOptionsPassedAsArgs,
|
||||
$remaingingArgs
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* findArgSeparator finds the "--" argument in the provided arguments list,
|
||||
* if present, and returns the arguments in three sets.
|
||||
*
|
||||
* @return array of three arrays, leading, "--" and trailing
|
||||
*/
|
||||
protected function findArgSeparator($args)
|
||||
{
|
||||
$pos = array_search('--', $args);
|
||||
if ($pos === false) {
|
||||
return [$args, [], []];
|
||||
}
|
||||
|
||||
return [
|
||||
array_slice($args, 0, $pos),
|
||||
['--'],
|
||||
array_slice($args, $pos + 1),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* convertOptions takes an associative array of options (key / value) and
|
||||
* converts it to an array of strings in the form --key=value.
|
||||
*
|
||||
* @param array $options in key => value form
|
||||
* @return array options in --option=value form
|
||||
*/
|
||||
protected function convertOptions($options)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($options as $option => $value) {
|
||||
$dashes = str_repeat('-', $this->dashCount($option));
|
||||
if ($value === true || $value === null) {
|
||||
$result[] = $dashes . $option;
|
||||
} elseif ($value === false) {
|
||||
// Ignore this option.
|
||||
} else {
|
||||
$result[] = "{$dashes}{$option}={$value}";
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function dashCount($name): int
|
||||
{
|
||||
return in_array($name, $this->getShortOptions()) ? 1 : 2;
|
||||
}
|
||||
}
|
||||
145
vendor/consolidation/site-process/src/Util/Escape.php
vendored
Normal file
145
vendor/consolidation/site-process/src/Util/Escape.php
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
namespace Consolidation\SiteProcess\Util;
|
||||
|
||||
use Consolidation\SiteAlias\SiteAliasInterface;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Consolidation\Config\Util\Interpolator;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Consolidation\SiteProcess\Util\ShellOperatorInterface;
|
||||
|
||||
/**
|
||||
* Escape will shell-escape commandline arguments for different platforms.
|
||||
*/
|
||||
class Escape
|
||||
{
|
||||
/**
|
||||
* argsForSite escapes each argument in an array for the given site.
|
||||
*/
|
||||
public static function argsForSite(SiteAliasInterface $siteAlias, $args)
|
||||
{
|
||||
return array_map(
|
||||
function ($arg) use ($siteAlias) {
|
||||
return Escape::forSite($siteAlias, $arg);
|
||||
},
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* forSite escapes the provided argument for the specified alias record.
|
||||
*/
|
||||
public static function forSite(SiteAliasInterface $siteAlias, $arg)
|
||||
{
|
||||
return static::shellArg($arg, $siteAlias->os());
|
||||
}
|
||||
|
||||
/**
|
||||
* shellArg escapes the provided argument for the specified OS
|
||||
*
|
||||
* @param string|ShellOperatorInterface $arg The argument to escape
|
||||
* @param string|null $os The OS to escape for. Optional; defaults to LINUX
|
||||
*
|
||||
* @return string The escaped string
|
||||
*/
|
||||
public static function shellArg($arg, $os = null)
|
||||
{
|
||||
// Short-circuit escaping for simple params (keep stuff readable);
|
||||
// also skip escaping for shell operators (e.g. &&), which must not
|
||||
// be escaped.
|
||||
if (($arg instanceof ShellOperatorInterface) || preg_match('|^[a-zA-Z0-9@=.:/_-]*$|', $arg)) {
|
||||
return (string) $arg;
|
||||
}
|
||||
|
||||
if (static::isWindows($os)) {
|
||||
return static::windowsArg($arg);
|
||||
}
|
||||
return static::linuxArg($arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* isWindows determines whether the provided OS is Windows.
|
||||
*
|
||||
* @param string|null $os The OS to escape for.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isWindows($os = null)
|
||||
{
|
||||
// In most cases, $os will be NULL and PHP_OS will be returned. However,
|
||||
// if an OS is specified in $os, return that instead.
|
||||
$os = $os ?: PHP_OS;
|
||||
return strtoupper(substr($os, 0, 3)) === 'WIN';
|
||||
}
|
||||
|
||||
/**
|
||||
* linuxArg is the Linux version of escapeshellarg().
|
||||
*
|
||||
* This is intended to work the same way that escapeshellarg() does on
|
||||
* Linux. If we need to escape a string that will be used remotely on
|
||||
* a Linux system, then we need our own implementation of escapeshellarg,
|
||||
* because the Windows version behaves differently.
|
||||
*
|
||||
* Note that we behave somewhat differently than the built-in escapeshellarg()
|
||||
* with respect to whitespace replacement in order
|
||||
*
|
||||
* @param string $arg The argument to escape
|
||||
*
|
||||
* @return string The escaped string
|
||||
*/
|
||||
public static function linuxArg($arg)
|
||||
{
|
||||
// For single quotes existing in the string, we will "exit"
|
||||
// single-quote mode, add a \' and then "re-enter"
|
||||
// single-quote mode. The result of this is that
|
||||
// 'quote' becomes '\''quote'\''
|
||||
$arg = preg_replace('/\'/', '\'\\\'\'', $arg);
|
||||
|
||||
// Replace "\t", "\n", "\r", "\0", "\x0B" with a whitespace.
|
||||
// Note that this replacement makes Drush's escapeshellarg work differently
|
||||
// than the built-in escapeshellarg in PHP on Linux, as these characters
|
||||
// usually are NOT replaced. However, this was done deliberately to be more
|
||||
// conservative when running _drush_escapeshellarg_linux on Windows
|
||||
// (this can happen when generating a command to run on a remote Linux server.)
|
||||
//
|
||||
// TODO: Perhaps we should only do this if the local system is Windows?
|
||||
// n.b. that would be a little more complicated to test.
|
||||
$arg = str_replace(["\t", "\n", "\r", "\0", "\x0B"], ' ', $arg);
|
||||
|
||||
// Add surrounding quotes.
|
||||
$arg = "'" . $arg . "'";
|
||||
|
||||
return $arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* windowsArg is the Windows version of escapeshellarg().
|
||||
*
|
||||
* @param string $arg The argument to escape
|
||||
*
|
||||
* @return string The escaped string
|
||||
*/
|
||||
public static function windowsArg($arg)
|
||||
{
|
||||
if ('' === $arg || null === $arg) {
|
||||
return '""';
|
||||
}
|
||||
if (false !== strpos($arg, "\0")) {
|
||||
$arg = str_replace("\0", '?', $arg);
|
||||
}
|
||||
if (!preg_match('/[\/()%!^"<>&|\s]/', $arg)) {
|
||||
return $arg;
|
||||
}
|
||||
// Double up existing backslashes
|
||||
$arg = preg_replace('/(\\\\+)$/', '$1$1', $arg);
|
||||
|
||||
// Replacing whitespace for good measure (see comment above).
|
||||
$arg = str_replace(["\t", "\n", "\r", "\0", "\x0B"], ' ', $arg);
|
||||
|
||||
$arg = str_replace(['"', '^', '%', '!'], ['""', '"^^"', '"^%"', '"^!"'], $arg);
|
||||
|
||||
// Add surrounding quotes.
|
||||
$arg = '"' . $arg . '"';
|
||||
|
||||
return $arg;
|
||||
}
|
||||
}
|
||||
123
vendor/consolidation/site-process/src/Util/RealtimeOutputHandler.php
vendored
Normal file
123
vendor/consolidation/site-process/src/Util/RealtimeOutputHandler.php
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
namespace Consolidation\SiteProcess\Util;
|
||||
|
||||
use Symfony\Component\Process\Process;
|
||||
use Consolidation\Config\Util\Interpolator;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\NullOutput;
|
||||
|
||||
/**
|
||||
* RealtimeOutput can be provided to a process object when you want
|
||||
* to display the output of the running command as it is being produced.
|
||||
*/
|
||||
class RealtimeOutputHandler
|
||||
{
|
||||
protected $stdout;
|
||||
protected $stderr;
|
||||
protected $stdoutMarker = '';
|
||||
protected $stderrMarker = '';
|
||||
|
||||
/**
|
||||
* Provide the output streams to use for stdout and stderr
|
||||
*/
|
||||
const MARKER_ERR = '> ';
|
||||
|
||||
public function __construct(OutputInterface $stdout, OutputInterface $stderr)
|
||||
{
|
||||
$this->stdout = $stdout;
|
||||
$this->stderr = $stderr;
|
||||
|
||||
$this->stdoutMarker = '';
|
||||
$this->stderrMarker = self::MARKER_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* This gives us an opportunity to adapt to the settings of the
|
||||
* process object (e.g. do we need to do anything differently if
|
||||
* it is in tty mode, etc.)
|
||||
*/
|
||||
public function configure(Process $process)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* setStderrMarker defines the string that should be added at
|
||||
* the beginning of every line of stderr that is printed.
|
||||
*/
|
||||
public function setStderrMarker($marker)
|
||||
{
|
||||
$this->stderrMarker = $marker;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* setStdoutMarker defines the string that should be added at
|
||||
* the beginning of every line of stdout that is printed.
|
||||
*/
|
||||
public function setStdoutMarker($marker)
|
||||
{
|
||||
$this->stdoutMarker = $marker;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* hideStdout overrides whatever was formerly stored in $this->stdout
|
||||
* with a null output buffer so that none of the standard output data
|
||||
* is visible.
|
||||
*/
|
||||
public function hideStdout()
|
||||
{
|
||||
$this->stdout = new NullOutput();
|
||||
$this->stdoutMarker = '';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* hideStderr serves the same function as hideStdout, but for the
|
||||
* standard error stream. Note that it is not useful to unconditionally
|
||||
* call both hideStdout and hideStderr; if no output is desired, then
|
||||
* the RealtimeOutputHandler should not be used.
|
||||
*/
|
||||
public function hideStderr()
|
||||
{
|
||||
$this->stderr = new NullOutput();
|
||||
$this->stderrMarker = '';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this object is used as a callable, then run 'handleOutput'.
|
||||
*/
|
||||
public function __invoke($type, $buffer)
|
||||
{
|
||||
$this->handleOutput($type, $buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method when you want real-time output from a Process call.
|
||||
* @param string $type
|
||||
* @param string $buffer
|
||||
*/
|
||||
public function handleOutput($type, $buffer)
|
||||
{
|
||||
if (Process::ERR === $type) {
|
||||
$this->stderr->write($this->addMarker($buffer, $this->stderrMarker), false, OutputInterface::OUTPUT_RAW);
|
||||
} else {
|
||||
$this->stdout->write($this->addMarker($buffer, $this->stdoutMarker), false, OutputInterface::OUTPUT_RAW);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that every line in $buffer begins with a MARKER_ERR.
|
||||
*/
|
||||
protected function addMarker($buffer, $marker)
|
||||
{
|
||||
// Exit early if there is no marker to add
|
||||
if (empty($marker)) {
|
||||
return $buffer;
|
||||
}
|
||||
// Add a marker on the beginning of every line.
|
||||
return $marker . rtrim(implode("\n" . $marker, explode("\n", $buffer)), $marker);
|
||||
}
|
||||
}
|
||||
52
vendor/consolidation/site-process/src/Util/Shell.php
vendored
Normal file
52
vendor/consolidation/site-process/src/Util/Shell.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
namespace Consolidation\SiteProcess\Util;
|
||||
|
||||
/**
|
||||
* Shell::op is a static factory that will create shell operators for use
|
||||
* in command line arguments list. Shell operators are characters that have
|
||||
* special meaning to the shell, such as "output redirection". When a shell
|
||||
* operator object is used, it indicates that this element is intended to
|
||||
* be used as an operator, and is not simply some other parameter to be escaped.
|
||||
*/
|
||||
class Shell implements ShellOperatorInterface
|
||||
{
|
||||
protected $value;
|
||||
|
||||
public static function op($operator)
|
||||
{
|
||||
static::validateOp($operator);
|
||||
return new self($operator);
|
||||
}
|
||||
|
||||
public static function preEscaped($value)
|
||||
{
|
||||
return new self($value);
|
||||
}
|
||||
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
protected static function validateOp($operator)
|
||||
{
|
||||
$valid = [
|
||||
'&&',
|
||||
'||',
|
||||
'|',
|
||||
'<',
|
||||
'>',
|
||||
'>>',
|
||||
';',
|
||||
];
|
||||
|
||||
if (!in_array($operator, $valid)) {
|
||||
throw new \Exception($operator . ' is not a valid shell operator.');
|
||||
}
|
||||
}
|
||||
}
|
||||
10
vendor/consolidation/site-process/src/Util/ShellOperatorInterface.php
vendored
Normal file
10
vendor/consolidation/site-process/src/Util/ShellOperatorInterface.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
namespace Consolidation\SiteProcess\Util;
|
||||
|
||||
/**
|
||||
* ShellOperatorInterface is a marker interface indicating that the object
|
||||
* represents a shell operator.
|
||||
*/
|
||||
interface ShellOperatorInterface
|
||||
{
|
||||
}
|
||||
27
vendor/consolidation/site-process/src/Util/Tty.php
vendored
Normal file
27
vendor/consolidation/site-process/src/Util/Tty.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace Consolidation\SiteProcess\Util;
|
||||
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
/**
|
||||
* Wrapper for universal support of TTY-related functionality across versions of
|
||||
* Symfony Process.
|
||||
*/
|
||||
class Tty
|
||||
{
|
||||
/**
|
||||
* In Symfony Process 4+, this is simply a wrapper for Process::isTtySupported().
|
||||
* In lower versions, it mimics the same functionality.
|
||||
*/
|
||||
public static function isTtySupported()
|
||||
{
|
||||
// Start off by checking STDIN with `posix_isatty`, as that appears to be more reliable
|
||||
if (function_exists('posix_isatty')) {
|
||||
return posix_isatty(STDIN);
|
||||
}
|
||||
if (method_exists('\Symfony\Component\Process\Process', 'isTtySupported')) {
|
||||
return Process::isTtySupported();
|
||||
}
|
||||
return (bool) @proc_open('echo 1 >/dev/null', array(array('file', '/dev/tty', 'r'), array('file', '/dev/tty', 'w'), array('file', '/dev/tty', 'w')), $pipes);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user