e69d23fa39d67b8dd2442f86f8b069c503275e8e
[yaffs-website] / vendor / consolidation / robo / src / Task / Simulator.php
1 <?php
2 namespace Robo\Task;
3
4 use Robo\Contract\WrappedTaskInterface;
5 use Robo\Exception\TaskException;
6 use Robo\TaskInfo;
7 use Robo\Result;
8 use Robo\Contract\TaskInterface;
9 use Robo\Contract\SimulatedInterface;
10 use Robo\Log\RoboLogLevel;
11 use Robo\Contract\CommandInterface;
12
13 class Simulator extends BaseTask implements CommandInterface
14 {
15     /**
16      * @var \Robo\Contract\TaskInterface
17      */
18     protected $task;
19
20     /**
21      * @var array
22      */
23     protected $constructorParameters;
24
25     /**
26      * @var array
27      */
28     protected $stack = [];
29
30     /**
31      * @param \Robo\Contract\TaskInterface $task
32      * @param array $constructorParameters
33      */
34     public function __construct(TaskInterface $task, $constructorParameters)
35     {
36         // TODO: If we ever want to convert the simulated task back into
37         // an executable task, then we should save the wrapped task.
38         $this->task = ($task instanceof WrappedTaskInterface) ? $task->original() : $task;
39         $this->constructorParameters = $constructorParameters;
40     }
41
42     /**
43      * @param string $function
44      * @param array $args
45      *
46      * @return \Robo\Result|\Robo\Task\Simulator
47      */
48     public function __call($function, $args)
49     {
50         $this->stack[] = array_merge([$function], $args);
51         $result = call_user_func_array([$this->task, $function], $args);
52         return $result == $this->task ? $this : $result;
53     }
54
55     /**
56      * {@inheritdoc}
57      */
58     public function run()
59     {
60         $callchain = '';
61         foreach ($this->stack as $action) {
62             $command = array_shift($action);
63             $parameters = $this->formatParameters($action);
64             $callchain .= "\n    ->$command(<fg=green>$parameters</>)";
65         }
66         $context = $this->getTaskContext(
67             [
68                 '_level' => RoboLogLevel::SIMULATED_ACTION,
69                 'simulated' => TaskInfo::formatTaskName($this->task),
70                 'parameters' => $this->formatParameters($this->constructorParameters),
71                 '_style' => ['simulated' => 'fg=blue;options=bold'],
72             ]
73         );
74
75         // RoboLogLevel::SIMULATED_ACTION
76         $this->printTaskInfo(
77             "Simulating {simulated}({parameters})$callchain",
78             $context
79         );
80
81         $result = null;
82         if ($this->task instanceof SimulatedInterface) {
83             $result = $this->task->simulate($context);
84         }
85         if (!isset($result)) {
86             $result = Result::success($this);
87         }
88
89         return $result;
90     }
91
92     /**
93      * Danger: reach through the simulated wrapper and pull out the command
94      * to be executed.  This is used when using a simulated task with another
95      * simulated task that runs commands, e.g. the Remote\Ssh task.  Using
96      * a simulated CommandInterface task with a non-simulated task may produce
97      * unexpected results (e.g. execution!).
98      *
99      * @return string
100      *
101      * @throws \Robo\Exception\TaskException
102      */
103     public function getCommand()
104     {
105         if (!$this->task instanceof CommandInterface) {
106             throw new TaskException($this->task, 'Simulated task that is not a CommandInterface used as a CommandInterface.');
107         }
108         return $this->task->getCommand();
109     }
110
111     /**
112      * @param string $action
113      *
114      * @return string
115      */
116     protected function formatParameters($action)
117     {
118         $parameterList = array_map([$this, 'convertParameter'], $action);
119         return implode(', ', $parameterList);
120     }
121
122     /**
123      * @param mixed $item
124      *
125      * @return string
126      */
127     protected function convertParameter($item)
128     {
129         if (is_callable($item)) {
130             return 'inline_function(...)';
131         }
132         if (is_array($item)) {
133             return $this->shortenParameter(var_export($item, true));
134         }
135         if (is_object($item)) {
136             return '[' . get_class($item). ' object]';
137         }
138         if (is_string($item)) {
139             return $this->shortenParameter("'$item'");
140         }
141         if (is_null($item)) {
142             return 'null';
143         }
144         return $item;
145     }
146
147     /**
148      * @param string $item
149      * @param string $shortForm
150      *
151      * @return string
152      */
153     protected function shortenParameter($item, $shortForm = '')
154     {
155         $maxLength = 80;
156         $tailLength = 20;
157         if (strlen($item) < $maxLength) {
158             return $item;
159         }
160         if (!empty($shortForm)) {
161             return $shortForm;
162         }
163         $item = trim($item);
164         $tail = preg_replace("#.*\n#ms", '', substr($item, -$tailLength));
165         $head = preg_replace("#\n.*#ms", '', substr($item, 0, $maxLength - (strlen($tail) + 5)));
166         return "$head ... $tail";
167     }
168 }