Pull merge.
[yaffs-website] / vendor / consolidation / robo / src / Result.php
1 <?php
2 namespace Robo;
3
4 use Robo\Contract\TaskInterface;
5 use Robo\Exception\TaskExitException;
6 use Robo\State\Data;
7
8 class Result extends ResultData
9 {
10     /**
11      * @var bool
12      */
13     public static $stopOnFail = false;
14
15     /**
16      * @var \Robo\Contract\TaskInterface
17      */
18     protected $task;
19
20     /**
21      * @param \Robo\Contract\TaskInterface $task
22      * @param string $exitCode
23      * @param string $message
24      * @param array $data
25      */
26     public function __construct(TaskInterface $task, $exitCode, $message = '', $data = [])
27     {
28         parent::__construct($exitCode, $message, $data);
29         $this->task = $task;
30         $this->printResult();
31
32         if (self::$stopOnFail) {
33             $this->stopOnFail();
34         }
35     }
36
37     /**
38      * Tasks should always return a Result. However, they are also
39      * allowed to return NULL or an array to indicate success.
40      */
41     public static function ensureResult($task, $result)
42     {
43         if ($result instanceof Result) {
44             return $result;
45         }
46         if (!isset($result)) {
47             return static::success($task);
48         }
49         if ($result instanceof Data) {
50             return static::success($task, $result->getMessage(), $result->getData());
51         }
52         if ($result instanceof ResultData) {
53             return new Result($task, $result->getExitCode(), $result->getMessage(), $result->getData());
54         }
55         if (is_array($result)) {
56             return static::success($task, '', $result);
57         }
58         throw new \Exception(sprintf('Task %s returned a %s instead of a \Robo\Result.', get_class($task), get_class($result)));
59     }
60
61     protected function printResult()
62     {
63         // For historic reasons, the Result constructor is responsible
64         // for printing task results.
65         // TODO: Make IO the responsibility of some other class. Maintaining
66         // existing behavior for backwards compatibility. This is undesirable
67         // in the long run, though, as it can result in unwanted repeated input
68         // in task collections et. al.
69         $resultPrinter = Robo::resultPrinter();
70         if ($resultPrinter) {
71             if ($resultPrinter->printResult($this)) {
72                 $this->alreadyPrinted();
73             }
74         }
75     }
76
77     /**
78      * @param \Robo\Contract\TaskInterface $task
79      * @param string $extension
80      * @param string $service
81      *
82      * @return \Robo\Result
83      */
84     public static function errorMissingExtension(TaskInterface $task, $extension, $service)
85     {
86         $messageTpl = 'PHP extension required for %s. Please enable %s';
87         $message = sprintf($messageTpl, $service, $extension);
88
89         return self::error($task, $message);
90     }
91
92     /**
93      * @param \Robo\Contract\TaskInterface $task
94      * @param string $class
95      * @param string $package
96      *
97      * @return \Robo\Result
98      */
99     public static function errorMissingPackage(TaskInterface $task, $class, $package)
100     {
101         $messageTpl = 'Class %s not found. Please install %s Composer package';
102         $message = sprintf($messageTpl, $class, $package);
103
104         return self::error($task, $message);
105     }
106
107     /**
108      * @param \Robo\Contract\TaskInterface $task
109      * @param string $message
110      * @param array $data
111      *
112      * @return \Robo\Result
113      */
114     public static function error(TaskInterface $task, $message, $data = [])
115     {
116         return new self($task, self::EXITCODE_ERROR, $message, $data);
117     }
118
119     /**
120      * @param \Robo\Contract\TaskInterface $task
121      * @param \Exception $e
122      * @param array $data
123      *
124      * @return \Robo\Result
125      */
126     public static function fromException(TaskInterface $task, \Exception $e, $data = [])
127     {
128         $exitCode = $e->getCode();
129         if (!$exitCode) {
130             $exitCode = self::EXITCODE_ERROR;
131         }
132         return new self($task, $exitCode, $e->getMessage(), $data);
133     }
134
135     /**
136      * @param \Robo\Contract\TaskInterface $task
137      * @param string $message
138      * @param array $data
139      *
140      * @return \Robo\Result
141      */
142     public static function success(TaskInterface $task, $message = '', $data = [])
143     {
144         return new self($task, self::EXITCODE_OK, $message, $data);
145     }
146
147     /**
148      * Return a context useful for logging messages.
149      *
150      * @return array
151      */
152     public function getContext()
153     {
154         $task = $this->getTask();
155
156         return TaskInfo::getTaskContext($task) + [
157             'code' => $this->getExitCode(),
158             'data' => $this->getArrayCopy(),
159             'time' => $this->getExecutionTime(),
160             'message' => $this->getMessage(),
161         ];
162     }
163
164     /**
165      * Add the results from the most recent task to the accumulated
166      * results from all tasks that have run so far, merging data
167      * as necessary.
168      *
169      * @param int|string $key
170      * @param \Robo\Result $taskResult
171      */
172     public function accumulate($key, Result $taskResult)
173     {
174         // If the task is unnamed, then all of its data elements
175         // just get merged in at the top-level of the final Result object.
176         if (static::isUnnamed($key)) {
177             $this->merge($taskResult);
178         } elseif (isset($this[$key])) {
179             // There can only be one task with a given name; however, if
180             // there are tasks added 'before' or 'after' the named task,
181             // then the results from these will be stored under the same
182             // name unless they are given a name of their own when added.
183             $current = $this[$key];
184             $this[$key] = $taskResult->merge($current);
185         } else {
186             $this[$key] = $taskResult;
187         }
188     }
189
190     /**
191      * We assume that named values (e.g. for associative array keys)
192      * are non-numeric; numeric keys are presumed to simply be the
193      * index of an array, and therefore insignificant.
194      *
195      * @param int|string $key
196      *
197      * @return bool
198      */
199     public static function isUnnamed($key)
200     {
201         return is_numeric($key);
202     }
203
204     /**
205      * @return \Robo\Contract\TaskInterface
206      */
207     public function getTask()
208     {
209         return $this->task;
210     }
211
212     /**
213      * @return \Robo\Contract\TaskInterface
214      */
215     public function cloneTask()
216     {
217         $reflect  = new \ReflectionClass(get_class($this->task));
218         return $reflect->newInstanceArgs(func_get_args());
219     }
220
221     /**
222      * @return bool
223      *
224      * @deprecated since 1.0.
225      *
226      * @see wasSuccessful()
227      */
228     public function __invoke()
229     {
230         trigger_error(__METHOD__ . ' is deprecated: use wasSuccessful() instead.', E_USER_DEPRECATED);
231         return $this->wasSuccessful();
232     }
233
234     /**
235      * @return $this
236      */
237     public function stopOnFail()
238     {
239         if (!$this->wasSuccessful()) {
240             $resultPrinter = Robo::resultPrinter();
241             if ($resultPrinter) {
242                 $resultPrinter->printStopOnFail($this);
243             }
244             $this->exitEarly($this->getExitCode());
245         }
246         return $this;
247     }
248
249     /**
250      * @param int $status
251      *
252      * @throws \Robo\Exception\TaskExitException
253      */
254     private function exitEarly($status)
255     {
256         throw new TaskExitException($this->getTask(), $this->getMessage(), $status);
257     }
258 }