AbstractTask   A
last analyzed

Complexity

Total Complexity 35

Size/Duplication

Total Lines 294
Duplicated Lines 0 %

Coupling/Cohesion

Dependencies 3

Importance

Changes 0
Metric Value
wmc 35
cbo 3
dl 0
loc 294
rs 9
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 3 1
A getName() 0 8 2
A setName() 0 6 1
A getDescription() 0 4 1
A setDescription() 0 6 1
A getEventDispatcher() 0 4 1
A setEventDispatcher() 0 6 1
A getParameterDefinition() 0 4 1
A addParameter() 0 12 1
A getParameters() 0 9 2
B getParameter() 0 20 5
A hasParameter() 0 10 3
A continueOnError() 0 4 1
A setParameter() 0 8 2
A validate() 0 12 4
A getHelperSet() 0 4 1
A hasHelperSet() 0 4 1
A setHelperSet() 0 6 1
B replaceTokens() 0 21 5
1
<?php
2
3
/**
4
 * This file is part of Bldr.io
5
 *
6
 * (c) Aaron Scherer <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE
10
 */
11
12
namespace Bldr\Block\Core\Task;
13
14
use Bldr\Exception\BldrException;
15
use Bldr\Exception\ParameterNotFoundException;
16
use Bldr\Exception\RequiredParameterException;
17
use Bldr\Task\TaskInterface;
18
use Symfony\Component\Console\Helper\HelperSet;
19
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
20
21
/**
22
 * @author Aaron Scherer <[email protected]>
23
 */
24
abstract class AbstractTask implements TaskInterface
25
{
26
    /**
27
     * @var string $name
28
     */
29
    private $name;
30
31
    /**
32
     * @var string $description
33
     */
34
    private $description;
35
36
    /**
37
     * @var EventDispatcherInterface $dispatcher
38
     */
39
    private $dispatcher;
40
41
    /**
42
     * @var array $parameters
43
     */
44
    private $parameters = [];
45
46
    /**
47
     * @type HelperSet
48
     */
49
    private $helperSet;
50
51
    /**
52
     * Returns whether or not AbstractTask will continue to the next AbstractTask when there is an error.
53
     *
54
     * @type bool
55
     */
56
    private $continueOnError;
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function configure()
62
    {
63
    }
64
65
    /**
66
     * {@inheritDoc}
67
     */
68
    public function getName()
69
    {
70
        if (!isset($this->name)) {
71
            throw new BldrException("Name is not set.");
72
        }
73
74
        return $this->name;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->name; (string) is incompatible with the return type declared by the interface Bldr\Task\TaskInterface::getName of type Bldr\Task\TaskInterface.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
75
    }
76
77
    /**
78
     * Sets the name of the task
79
     *
80
     * @param string $name
81
     *
82
     * @return AbstractTask
83
     */
84
    public function setName($name)
85
    {
86
        $this->name = $name;
87
88
        return $this;
89
    }
90
91
    /**
92
     * {@inheritDoc}
93
     */
94
    public function getDescription()
95
    {
96
        return $this->description;
97
    }
98
99
    /**
100
     * Sets the description of the AbstractTask
101
     *
102
     * @param string $description
103
     *
104
     * @return AbstractTask
105
     */
106
    public function setDescription($description)
107
    {
108
        $this->description = $description;
109
110
        return $this;
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116
    public function getEventDispatcher()
117
    {
118
        return $this->dispatcher;
119
    }
120
121
    /**
122
     * @param EventDispatcherInterface $dispatcher
123
     *
124
     * @return AbstractTask
125
     */
126
    public function setEventDispatcher(EventDispatcherInterface $dispatcher)
127
    {
128
        $this->dispatcher = $dispatcher;
129
130
        return $this;
131
    }
132
133
    /**
134
     * @return array
135
     */
136
    public function getParameterDefinition()
137
    {
138
        return $this->parameters;
139
    }
140
141
    /**
142
     * Adds a parameter to the definition of the Task
143
     *
144
     * @param string $name        Name of the task parameter
145
     * @param bool   $required    If true, task parameter is required
146
     * @param string $description Description of the task parameter
147
     * @param mixed  $default     Default value of the task parameter, null by default
148
     *
149
     * @return mixed
150
     */
151
    public function addParameter($name, $required = false, $description = '', $default = null)
152
    {
153
        $this->parameters[$name] = [
154
            'name'        => $name,
155
            'required'    => $required,
156
            'description' => $description,
157
            'default'     => $default,
158
            'value'       => null
159
        ];
160
161
        return $this;
162
    }
163
164
    /**
165
     * {@inheritDoc}
166
     */
167
    public function getParameters()
168
    {
169
        $parameters = [];
170
        foreach ($this->parameters as $name => $parameter) {
171
            $parameters[$name] = $this->getParameter($name);
172
        }
173
174
        return $parameters;
175
    }
176
177
    /**
178
     * {@inheritdoc}
179
     *
180
     * @throws ParameterNotFoundException
181
     * @throws RequiredParameterException
182
     */
183
    public function getParameter($name, $validate = true)
184
    {
185
        if ($validate && !array_key_exists($name, $this->parameters)) {
186
            throw new ParameterNotFoundException($name);
187
        }
188
189
        $param = $this->parameters[$name];
190
        $value = $param['value'];
191
        if (null === $value) {
192
            if (true === $param['required']) {
193
                throw new RequiredParameterException($name);
194
            }
195
196
            $value = $param['default'];
197
        }
198
199
        $value = $this->replaceTokens($value);
200
201
        return $value;
202
    }
203
204
    /**
205
     * Returns true if the Task has a parameter with the given name, and the value is not null.
206
     * Returns false otherwise.
207
     *
208
     * @param string $name
209
     *
210
     * @return bool
211
     */
212
    public function hasParameter($name)
213
    {
214
        if (array_key_exists($name, $this->parameters)) {
215
            if (null !== $this->parameters[$name]['value']) {
216
                return true;
217
            }
218
        }
219
220
        return false;
221
    }
222
223
    /**
224
     * @return bool
225
     */
226
    public function continueOnError()
227
    {
228
        return $this->continueOnError;
229
    }
230
231
    /**
232
     * {@inheritdoc}
233
     */
234
    public function setParameter($name, $value)
235
    {
236
        if (!array_key_exists($name, $this->parameters)) {
237
            $this->addParameter($name, false, '', null);
238
        }
239
240
        $this->parameters[$name]['value'] = $value;
241
    }
242
243
    /**
244
     * {@inheritdoc}
245
     */
246
    public function validate()
247
    {
248
        foreach ($this->parameters as $name => $parameter) {
249
            if (null === $parameter['value']) {
250
                if (true === $parameter['required']) {
251
                    throw new RequiredParameterException($name);
252
                }
253
            }
254
        }
255
256
        return true;
257
    }
258
259
    /**
260
     * {@inheritdoc}
261
     */
262
    public function getHelperSet()
263
    {
264
        return $this->helperSet;
265
    }
266
267
    /**
268
     * Returns true if the HelperSet is set
269
     *
270
     * @return bool
271
     */
272
    public function hasHelperSet()
273
    {
274
        return $this->helperSet === null;
275
    }
276
277
    /**
278
     * @param HelperSet $helperSet
279
     *
280
     * @return $this
281
     */
282
    public function setHelperSet(HelperSet $helperSet)
283
    {
284
        $this->helperSet = $helperSet;
285
286
        return $this;
287
    }
288
289
    /**
290
     * Tokenize the given option, if it is a string.
291
     *
292
     * @param mixed $option
293
     *
294
     * @return mixed
295
     */
296
    private function replaceTokens($option)
297
    {
298
        if (is_array($option)) {
299
            $tokenizedOptions = [];
300
            foreach ($option as $key => $opt) {
301
                $tokenizedOptions[$key] = $this->replaceTokens($opt);
302
            }
303
304
            return $tokenizedOptions;
305
        }
306
307
        return preg_replace_callback(
308
            '/\$(.+)\$|\$\{(.+)\}/',
309
            function ($match) {
310
                $val = isset($match[2]) ? getenv($match[2]) : getenv($match[1]);
311
312
                return $val !== false ? $val : $match[0];
313
            },
314
            $option
315
        );
316
    }
317
}
318