annotate vendor/consolidation/site-process/src/SiteProcess.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
rev   line source
Chris@5 1 <?php
Chris@5 2 namespace Consolidation\SiteProcess;
Chris@5 3
Chris@5 4 use Consolidation\SiteAlias\SiteAliasInterface;
Chris@5 5 use Consolidation\SiteProcess\Transport\DockerComposeTransport;
Chris@5 6 use Consolidation\SiteProcess\Util\ArgumentProcessor;
Chris@5 7 use Consolidation\SiteProcess\Transport\LocalTransport;
Chris@5 8 use Consolidation\SiteProcess\Transport\SshTransport;
Chris@5 9 use Consolidation\SiteProcess\Transport\TransportInterface;
Chris@5 10 use Consolidation\Config\Util\Interpolator;
Chris@5 11 use Consolidation\SiteProcess\Util\ShellOperatorInterface;
Chris@5 12 use Consolidation\SiteProcess\Util\Escape;
Chris@5 13
Chris@5 14 /**
Chris@5 15 * A wrapper around Symfony Process that uses site aliases
Chris@5 16 * (https://github.com/consolidation/site-alias)
Chris@5 17 *
Chris@5 18 * - Interpolate arguments using values from the alias
Chris@5 19 * e.g. `$process = new SiteProcess($alias, ['git', '-C', '{{root}}']);`
Chris@5 20 * - Make remote calls via ssh as if they were local.
Chris@5 21 */
Chris@5 22 class SiteProcess extends ProcessBase
Chris@5 23 {
Chris@5 24 /** @var SiteAliasInterface */
Chris@5 25 protected $siteAlias;
Chris@5 26 /** @var string[] */
Chris@5 27 protected $args;
Chris@5 28 /** @var string[] */
Chris@5 29 protected $options;
Chris@5 30 /** @var string[] */
Chris@5 31 protected $optionsPassedAsArgs;
Chris@5 32 /** @var string */
Chris@5 33 protected $cd_remote;
Chris@5 34 /** @var TransportInterface */
Chris@5 35 protected $transport;
Chris@5 36
Chris@5 37 /**
Chris@5 38 * Process arguments and options per the site alias and build the
Chris@5 39 * actual command to run.
Chris@5 40 */
Chris@5 41 public function __construct(SiteAliasInterface $siteAlias, TransportInterface $transport, $args, $options = [], $optionsPassedAsArgs = [])
Chris@5 42 {
Chris@5 43 $this->siteAlias = $siteAlias;
Chris@5 44 $this->transport = $transport;
Chris@5 45 $this->args = $args;
Chris@5 46 $this->options = $options;
Chris@5 47 $this->optionsPassedAsArgs = $optionsPassedAsArgs;
Chris@5 48
Chris@5 49 parent::__construct([]);
Chris@5 50 }
Chris@5 51
Chris@5 52 /**
Chris@5 53 * Get a starting directory for the remote process.
Chris@5 54 *
Chris@5 55 * @return string|null
Chris@5 56 */
Chris@5 57 public function getWorkingDirectory()
Chris@5 58 {
Chris@5 59 return $this->cd_remote;
Chris@5 60 }
Chris@5 61
Chris@5 62 /**
Chris@5 63 * Set a starting directory for the remote process.
Chris@5 64 *
Chris@5 65 * @param string $cd_remote
Chris@5 66 *
Chris@5 67 * @return \Consolidation\SiteProcess\SiteProcess
Chris@5 68 */
Chris@5 69 public function setWorkingDirectory($cd_remote)
Chris@5 70 {
Chris@5 71 $this->cd_remote = $cd_remote;
Chris@5 72 return $this;
Chris@5 73 }
Chris@5 74
Chris@5 75 /**
Chris@5 76 * Set a starting directory for the initial/local process.
Chris@5 77 *
Chris@5 78 * @param string $cd
Chris@5 79 *
Chris@5 80 * @return \Consolidation\SiteProcess\SiteProcess
Chris@5 81 */
Chris@5 82 public function setWorkingDirectoryLocal($cd)
Chris@5 83 {
Chris@5 84 return parent::setWorkingDirectory($cd);
Chris@5 85 }
Chris@5 86
Chris@5 87 /**
Chris@5 88 * Get the starting directory for the initial/local process.
Chris@5 89 *
Chris@5 90 * @return string|null;
Chris@5 91 */
Chris@5 92 public function getWorkingDirectoryLocal()
Chris@5 93 {
Chris@5 94 return parent::getWorkingDirectory();
Chris@5 95 }
Chris@5 96
Chris@5 97 /**
Chris@5 98 *
Chris@5 99 * @param bool $shouldUseSiteRoot
Chris@5 100 * @return $this|\Symfony\Component\Process\Process
Chris@5 101 * @throws \Exception
Chris@5 102 */
Chris@5 103 public function chdirToSiteRoot($shouldUseSiteRoot = true)
Chris@5 104 {
Chris@5 105 if (!$shouldUseSiteRoot || !$this->siteAlias->hasRoot()) {
Chris@5 106 return $this;
Chris@5 107 }
Chris@5 108
Chris@5 109 return $this->setWorkingDirectory($this->siteAlias->root());
Chris@5 110 }
Chris@5 111
Chris@5 112 /**
Chris@5 113 * Take all of our individual arguments and process them for use.
Chris@5 114 */
Chris@5 115 protected function processArgs()
Chris@5 116 {
Chris@5 117 $transport = $this->getTransport($this->siteAlias);
Chris@5 118 $transport->configure($this);
Chris@5 119
Chris@5 120 $processor = new ArgumentProcessor();
Chris@5 121 $selectedArgs = $processor->selectArgs(
Chris@5 122 $this->siteAlias,
Chris@5 123 $this->args,
Chris@5 124 $this->options,
Chris@5 125 $this->optionsPassedAsArgs
Chris@5 126 );
Chris@5 127
Chris@5 128 // Ask the transport to drop in a 'cd' if needed.
Chris@5 129 if ($this->getWorkingDirectory()) {
Chris@5 130 $selectedArgs = $transport->addChdir($this->getWorkingDirectory(), $selectedArgs);
Chris@5 131 }
Chris@5 132
Chris@5 133 // Do any necessary interpolation on the selected arguments.
Chris@5 134 $processedArgs = $this->interpolate($selectedArgs);
Chris@5 135
Chris@5 136 // Wrap the command with 'ssh' or some other transport if this is
Chris@5 137 // a remote command; otherwise, leave it as-is.
Chris@5 138 return $transport->wrap($processedArgs);
Chris@5 139 }
Chris@5 140
Chris@5 141 public function setTransport($transport)
Chris@5 142 {
Chris@5 143 $this->transport = $transport;
Chris@5 144 }
Chris@5 145
Chris@5 146 /**
Chris@5 147 * Ask the transport manager for the correct transport for the
Chris@5 148 * provided alias.
Chris@5 149 */
Chris@5 150 protected function getTransport(SiteAliasInterface $siteAlias)
Chris@5 151 {
Chris@5 152 return $this->transport;
Chris@5 153 }
Chris@5 154
Chris@5 155 /**
Chris@5 156 * @inheritDoc
Chris@5 157 */
Chris@5 158 public function getCommandLine()
Chris@5 159 {
Chris@5 160 $commandLine = parent::getCommandLine();
Chris@5 161 if (empty($commandLine)) {
Chris@5 162 $processedArgs = $this->processArgs();
Chris@5 163 $commandLine = Escape::argsForSite($this->siteAlias, $processedArgs);
Chris@5 164 $commandLine = implode(' ', $commandLine);
Chris@5 165 $this->setCommandLine($commandLine);
Chris@5 166 }
Chris@5 167 return $commandLine;
Chris@5 168 }
Chris@5 169
Chris@5 170 /**
Chris@5 171 * @inheritDoc
Chris@5 172 */
Chris@5 173 public function start(callable $callback = null, $env = array())
Chris@5 174 {
Chris@5 175 $cmd = $this->getCommandLine();
Chris@5 176 parent::start($callback, $env);
Chris@5 177 }
Chris@5 178
Chris@5 179 /**
Chris@5 180 * @inheritDoc
Chris@5 181 */
Chris@5 182 public function wait(callable $callback = null)
Chris@5 183 {
Chris@5 184 $return = parent::wait($callback);
Chris@5 185 return $return;
Chris@5 186 }
Chris@5 187
Chris@5 188 /**
Chris@5 189 * interpolate examines each of the arguments in the provided argument list
Chris@5 190 * and replaces any token found therein with the value for that key as
Chris@5 191 * pulled from the given site alias.
Chris@5 192 *
Chris@5 193 * Example: "git -C {{root}} status"
Chris@5 194 *
Chris@5 195 * The token "{{root}}" will be converted to a value via $siteAlias->get('root').
Chris@5 196 * The result will replace the token.
Chris@5 197 *
Chris@5 198 * It is possible to use dot notation in the keys to access nested elements
Chris@5 199 * within the site alias record.
Chris@5 200 *
Chris@5 201 * @param SiteAliasInterface $siteAlias
Chris@5 202 * @param type $args
Chris@5 203 * @return type
Chris@5 204 */
Chris@5 205 protected function interpolate($args)
Chris@5 206 {
Chris@5 207 $interpolator = new Interpolator();
Chris@5 208 return array_map(
Chris@5 209 function ($arg) use ($interpolator) {
Chris@5 210 if ($arg instanceof ShellOperatorInterface) {
Chris@5 211 return $arg;
Chris@5 212 }
Chris@5 213 return $interpolator->interpolate($this->siteAlias, $arg, false);
Chris@5 214 },
Chris@5 215 $args
Chris@5 216 );
Chris@5 217 }
Chris@5 218 }