0dd1a6cdfc929025c669060415d6a7cfcecd510b
[yaffs-website] / vendor / consolidation / robo / src / Common / ExecTrait.php
1 <?php
2
3 namespace Robo\Common;
4
5 use Robo\ResultData;
6 use Symfony\Component\Process\Process;
7
8 /**
9  * Class ExecTrait
10  * @package Robo\Common
11  */
12 trait ExecTrait
13 {
14     /**
15      * @var bool
16      */
17     protected $background = false;
18
19     /**
20      * @var null|int
21      */
22     protected $timeout = null;
23
24     /**
25      * @var null|int
26      */
27     protected $idleTimeout = null;
28
29     /**
30      * @var null|array
31      */
32     protected $env = null;
33
34     /**
35      * @var Process
36      */
37     protected $process;
38
39     /**
40      * @var resource|string
41      */
42     protected $input;
43
44     /**
45      * @var boolean
46      */
47     protected $interactive = null;
48
49     /**
50      * @var bool
51      */
52     protected $isPrinted = true;
53
54     /**
55      * @var bool
56      */
57     protected $isMetadataPrinted = true;
58
59     /**
60      * @var string
61      */
62     protected $workingDirectory;
63
64     /**
65      * @return string
66      */
67     abstract public function getCommandDescription();
68
69     /** Typically provided by Timer trait via ProgressIndicatorAwareTrait. */
70     abstract public function startTimer();
71     abstract public function stopTimer();
72     abstract public function getExecutionTime();
73
74     /**
75      * Typically provided by TaskIO Trait.
76      */
77     abstract public function hideTaskProgress();
78     abstract public function showTaskProgress($inProgress);
79     abstract public function printTaskInfo($text, $context = null);
80
81     /**
82      * Typically provided by VerbosityThresholdTrait.
83      */
84     abstract public function verbosityMeetsThreshold();
85     abstract public function writeMessage($message);
86
87     /**
88      * Sets $this->interactive() based on posix_isatty().
89      *
90      * @return $this
91      */
92     public function detectInteractive()
93     {
94         // If the caller did not explicity set the 'interactive' mode,
95         // and output should be produced by this task (verbosityMeetsThreshold),
96         // then we will automatically set interactive mode based on whether
97         // or not output was redirected when robo was executed.
98         if (!isset($this->interactive) && function_exists('posix_isatty') && $this->verbosityMeetsThreshold()) {
99             $this->interactive = posix_isatty(STDOUT);
100         }
101
102         return $this;
103     }
104
105     /**
106      * Executes command in background mode (asynchronously)
107      *
108      * @return $this
109      */
110     public function background($arg = true)
111     {
112         $this->background = $arg;
113         return $this;
114     }
115
116     /**
117      * Stop command if it runs longer then $timeout in seconds
118      *
119      * @param int $timeout
120      *
121      * @return $this
122      */
123     public function timeout($timeout)
124     {
125         $this->timeout = $timeout;
126         return $this;
127     }
128
129     /**
130      * Stops command if it does not output something for a while
131      *
132      * @param int $timeout
133      *
134      * @return $this
135      */
136     public function idleTimeout($timeout)
137     {
138         $this->idleTimeout = $timeout;
139         return $this;
140     }
141
142     /**
143      * Set a single environment variable, or multiple.
144      */
145     public function env($env, $value = null)
146     {
147         if (!is_array($env)) {
148             $env = [$env => ($value ? $value : true)];
149         }
150         return $this->envVars($env);
151     }
152
153     /**
154      * Sets the environment variables for the command
155      *
156      * @param array $env
157      *
158      * @return $this
159      */
160     public function envVars(array $env)
161     {
162         $this->env = $env;
163         return $this;
164     }
165
166     /**
167      * Pass an input to the process. Can be resource created with fopen() or string
168      *
169      * @param resource|string $input
170      *
171      * @return $this
172      */
173     public function setInput($input)
174     {
175         $this->input = $input;
176         return $this;
177     }
178
179     /**
180      * Attach tty to process for interactive input
181      *
182      * @param $interactive bool
183      *
184      * @return $this
185      */
186     public function interactive($interactive = true)
187     {
188         $this->interactive = $interactive;
189         return $this;
190     }
191
192
193     /**
194      * Is command printing its output to screen
195      *
196      * @return bool
197      */
198     public function getPrinted()
199     {
200         return $this->isPrinted;
201     }
202
203     /**
204      * Changes working directory of command
205      *
206      * @param string $dir
207      *
208      * @return $this
209      */
210     public function dir($dir)
211     {
212         $this->workingDirectory = $dir;
213         return $this;
214     }
215
216     /**
217      * Shortcut for setting isPrinted() and isMetadataPrinted() to false.
218      *
219      * @param bool $arg
220      *
221      * @return $this
222      */
223     public function silent($arg)
224     {
225         if (is_bool($arg)) {
226             $this->isPrinted = !$arg;
227             $this->isMetadataPrinted = !$arg;
228         }
229         return $this;
230     }
231
232     /**
233      * Should command output be printed
234      *
235      * @param bool $arg
236      *
237      * @return $this
238      *
239      * @deprecated
240      */
241     public function printed($arg)
242     {
243         $this->logger->warning("printed() is deprecated. Please use printOutput().");
244         return $this->printOutput($arg);
245     }
246
247     /**
248      * Should command output be printed
249      *
250      * @param bool $arg
251      *
252      * @return $this
253      */
254     public function printOutput($arg)
255     {
256         if (is_bool($arg)) {
257             $this->isPrinted = $arg;
258         }
259         return $this;
260     }
261
262     /**
263      * Should command metadata be printed. I,e., command and timer.
264      *
265      * @param bool $arg
266      *
267      * @return $this
268      */
269     public function printMetadata($arg)
270     {
271         if (is_bool($arg)) {
272             $this->isMetadataPrinted = $arg;
273         }
274         return $this;
275     }
276
277     /**
278      * @param Process $process
279      * @param callable $output_callback
280      *
281      * @return \Robo\ResultData
282      */
283     protected function execute($process, $output_callback = null)
284     {
285         $this->process = $process;
286
287         if (!$output_callback) {
288             $output_callback = function ($type, $buffer) {
289                 $progressWasVisible = $this->hideTaskProgress();
290                 $this->writeMessage($buffer);
291                 $this->showTaskProgress($progressWasVisible);
292             };
293         }
294
295         $this->detectInteractive();
296
297         if ($this->isMetadataPrinted) {
298             $this->printAction();
299         }
300         $this->process->setTimeout($this->timeout);
301         $this->process->setIdleTimeout($this->idleTimeout);
302         if ($this->workingDirectory) {
303             $this->process->setWorkingDirectory($this->workingDirectory);
304         }
305         if ($this->input) {
306             $this->process->setInput($this->input);
307         }
308
309         if ($this->interactive && $this->isPrinted) {
310             $this->process->setTty(true);
311         }
312
313         if (isset($this->env)) {
314             $this->process->setEnv($this->env);
315         }
316
317         if (!$this->background && !$this->isPrinted) {
318             $this->startTimer();
319             $this->process->run();
320             $this->stopTimer();
321             $output = rtrim($this->process->getOutput());
322             return new ResultData(
323                 $this->process->getExitCode(),
324                 $output,
325                 $this->getResultData()
326             );
327         }
328
329         if (!$this->background && $this->isPrinted) {
330             $this->startTimer();
331             $this->process->run($output_callback);
332             $this->stopTimer();
333             return new ResultData(
334                 $this->process->getExitCode(),
335                 $this->process->getOutput(),
336                 $this->getResultData()
337             );
338         }
339
340         try {
341             $this->process->start();
342         } catch (\Exception $e) {
343             return new ResultData(
344                 $this->process->getExitCode(),
345                 $e->getMessage(),
346                 $this->getResultData()
347             );
348         }
349         return new ResultData($this->process->getExitCode());
350     }
351
352     /**
353      *
354      */
355     protected function stop()
356     {
357         if ($this->background && isset($this->process) && $this->process->isRunning()) {
358             $this->process->stop();
359             $this->printTaskInfo(
360                 "Stopped {command}",
361                 ['command' => $this->getCommandDescription()]
362             );
363         }
364     }
365
366     /**
367      * @param array $context
368      */
369     protected function printAction($context = [])
370     {
371         $command = $this->getCommandDescription();
372         $formatted_command = $this->formatCommandDisplay($command);
373
374         $dir = $this->workingDirectory ? " in {dir}" : "";
375         $this->printTaskInfo("Running {command}$dir", [
376                 'command' => $formatted_command,
377                 'dir' => $this->workingDirectory
378             ] + $context);
379     }
380
381     /**
382      * @param $command
383      *
384      * @return mixed
385      */
386     protected function formatCommandDisplay($command)
387     {
388         $formatted_command = str_replace("&&", "&&\n", $command);
389         $formatted_command = str_replace("||", "||\n", $formatted_command);
390
391         return $formatted_command;
392     }
393
394     /**
395      * Gets the data array to be passed to Result().
396      *
397      * @return array
398      *   The data array passed to Result().
399      */
400     protected function getResultData()
401     {
402         if ($this->isMetadataPrinted) {
403             return ['time' => $this->getExecutionTime()];
404         }
405
406         return [];
407     }
408 }