Result::success()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
1
<?php
2
3
namespace Robo;
4
5
use Robo\Contract\TaskInterface;
6
use Robo\Exception\TaskExitException;
7
use Robo\State\Data;
8
9
class Result extends ResultData
10
{
11
    /**
12
     * @var bool
13
     */
14
    public static $stopOnFail = false;
15
16
    /**
17
     * @var \Robo\Contract\TaskInterface
18
     */
19
    protected $task;
20
21
    /**
22
     * @param \Robo\Contract\TaskInterface $task
23
     * @param int $exitCode
24
     * @param string $message
25
     * @param array $data
26
     */
27
    public function __construct(TaskInterface $task, $exitCode, $message = '', $data = [])
28
    {
29
        parent::__construct($exitCode, $message, $data);
30
        $this->task = $task;
31
        $this->printResult();
32
33
        if (self::$stopOnFail) {
34
            $this->stopOnFail();
35
        }
36
    }
37
38
    /**
39
     * Tasks should always return a Result. However, they are also
40
     * allowed to return NULL or an array to indicate success.
41
     *
42
     * @param \Robo\Contract\TaskInterface $task
43
     * @param \Robo\Result|\Robo\State\Data|\Robo\ResultData|array|null
44
     *
45
     * @return static
46
     */
47
    public static function ensureResult($task, $result)
48
    {
49
        if ($result instanceof Result) {
50
            return $result;
51
        }
52
        if (!isset($result)) {
53
            return static::success($task);
54
        }
55
        if ($result instanceof Data) {
56
            return static::success($task, $result->getMessage(), $result->getData());
57
        }
58
        if ($result instanceof ResultData) {
59
            return new Result($task, $result->getExitCode(), $result->getMessage(), $result->getData());
60
        }
61
        if (is_array($result)) {
62
            return static::success($task, '', $result);
63
        }
64
        throw new \Exception(sprintf('Task %s returned a %s instead of a \Robo\Result.', get_class($task), get_class($result)));
65
    }
66
67
    protected function printResult()
68
    {
69
        // For historic reasons, the Result constructor is responsible
70
        // for printing task results.
71
        // TODO: Make IO the responsibility of some other class. Maintaining
72
        // existing behavior for backwards compatibility. This is undesirable
73
        // in the long run, though, as it can result in unwanted repeated input
74
        // in task collections et. al.
75
        $resultPrinter = Robo::resultPrinter();
76
        if ($resultPrinter) {
77
            if ($resultPrinter->printResult($this)) {
78
                $this->alreadyPrinted();
0 ignored issues
show
Unused Code introduced by
The call to the method Robo\Result::alreadyPrinted() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
79
            }
80
        }
81
    }
82
83
    /**
84
     * @param \Robo\Contract\TaskInterface $task
85
     * @param string $extension
86
     * @param string $service
87
     *
88
     * @return static
89
     */
90
    public static function errorMissingExtension(TaskInterface $task, $extension, $service)
91
    {
92
        $messageTpl = 'PHP extension required for %s. Please enable %s';
93
        $message = sprintf($messageTpl, $service, $extension);
94
95
        return self::error($task, $message);
96
    }
97
98
    /**
99
     * @param \Robo\Contract\TaskInterface $task
100
     * @param string $class
101
     * @param string $package
102
     *
103
     * @return static
104
     */
105
    public static function errorMissingPackage(TaskInterface $task, $class, $package)
106
    {
107
        $messageTpl = 'Class %s not found. Please install %s Composer package';
108
        $message = sprintf($messageTpl, $class, $package);
109
110
        return self::error($task, $message);
111
    }
112
113
    /**
114
     * @param \Robo\Contract\TaskInterface $task
115
     * @param string $message
116
     * @param array $data
117
     *
118
     * @return static
119
     */
120
    public static function error(TaskInterface $task, $message, $data = [])
121
    {
122
        return new self($task, self::EXITCODE_ERROR, $message, $data);
123
    }
124
125
    /**
126
     * @param \Robo\Contract\TaskInterface $task
127
     * @param \Exception $e
128
     * @param array $data
129
     *
130
     * @return static
131
     */
132
    public static function fromException(TaskInterface $task, \Exception $e, $data = [])
133
    {
134
        $exitCode = $e->getCode();
135
        if (!$exitCode) {
136
            $exitCode = self::EXITCODE_ERROR;
137
        }
138
        return new self($task, $exitCode, $e->getMessage(), $data);
139
    }
140
141
    /**
142
     * @param \Robo\Contract\TaskInterface $task
143
     * @param string $message
144
     * @param array $data
145
     *
146
     * @return static
147
     */
148
    public static function success(TaskInterface $task, $message = '', $data = [])
149
    {
150
        return new self($task, self::EXITCODE_OK, $message, $data);
151
    }
152
153
    /**
154
     * Return a context useful for logging messages.
155
     *
156
     * @return array
157
     */
158
    public function getContext()
159
    {
160
        $task = $this->getTask();
161
162
        return TaskInfo::getTaskContext($task) + [
163
            'code' => $this->getExitCode(),
164
            'data' => $this->getArrayCopy(),
165
            'time' => $this->getExecutionTime(),
166
            'message' => $this->getMessage(),
167
        ];
168
    }
169
170
    /**
171
     * Add the results from the most recent task to the accumulated
172
     * results from all tasks that have run so far, merging data
173
     * as necessary.
174
     *
175
     * @param int|string $key
176
     * @param \Robo\Result $taskResult
177
     */
178
    public function accumulate($key, Result $taskResult)
179
    {
180
        // If the task is unnamed, then all of its data elements
181
        // just get merged in at the top-level of the final Result object.
182
        if (static::isUnnamed($key)) {
183
            $this->merge($taskResult);
184
        } elseif (isset($this[$key])) {
185
            // There can only be one task with a given name; however, if
186
            // there are tasks added 'before' or 'after' the named task,
187
            // then the results from these will be stored under the same
188
            // name unless they are given a name of their own when added.
189
            $current = $this[$key];
190
            $this[$key] = $taskResult->merge($current);
191
        } else {
192
            $this[$key] = $taskResult;
193
        }
194
    }
195
196
    /**
197
     * We assume that named values (e.g. for associative array keys)
198
     * are non-numeric; numeric keys are presumed to simply be the
199
     * index of an array, and therefore insignificant.
200
     *
201
     * @param int|string $key
202
     *
203
     * @return bool
204
     */
205
    public static function isUnnamed($key)
206
    {
207
        return is_numeric($key);
208
    }
209
210
    /**
211
     * @return \Robo\Contract\TaskInterface
212
     */
213
    public function getTask()
214
    {
215
        return $this->task;
216
    }
217
218
    /**
219
     * @return \Robo\Contract\TaskInterface
220
     */
221
    public function cloneTask()
222
    {
223
        $reflect  = new \ReflectionClass(get_class($this->task));
224
        return $reflect->newInstanceArgs(func_get_args());
225
    }
226
227
    /**
228
     * @return bool
229
     *
230
     * @deprecated since 1.0.
231
     *
232
     * @see wasSuccessful()
233
     */
234
    public function __invoke()
235
    {
236
        trigger_error(__METHOD__ . ' is deprecated: use wasSuccessful() instead.', E_USER_DEPRECATED);
237
        return $this->wasSuccessful();
238
    }
239
240
    /**
241
     * @return $this
242
     */
243
    public function stopOnFail()
244
    {
245
        if (!$this->wasSuccessful()) {
246
            $resultPrinter = Robo::resultPrinter();
247
            if ($resultPrinter) {
248
                $resultPrinter->printStopOnFail($this);
249
            }
250
            $this->exitEarly($this->getExitCode());
251
        }
252
        return $this;
253
    }
254
255
    /**
256
     * @param int $status
257
     *
258
     * @throws \Robo\Exception\TaskExitException
259
     */
260
    private function exitEarly($status)
261
    {
262
        throw new TaskExitException($this->getTask(), $this->getMessage(), $status);
263
    }
264
}
265