Passed
Push — master ( a0b722...864342 )
by Michiel
11:10
created

Target   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 399
Duplicated Lines 0 %

Test Coverage

Coverage 93.46%

Importance

Changes 0
Metric Value
eloc 82
dl 0
loc 399
ccs 100
cts 107
cp 0.9346
rs 8.8
c 0
b 0
f 0
wmc 45

25 Methods

Rating   Name   Duplication   Size   Complexity  
A getProject() 0 3 1
A setDepends() 0 12 3
A getDependencies() 0 3 1
A setProject() 0 3 1
A addDependency() 0 3 1
A setHidden() 0 5 1
A getDescription() 0 3 1
A getTasks() 0 12 3
A isHidden() 0 3 1
A testUnlessCondition() 0 15 4
A getHidden() 0 3 1
A setIf() 0 3 1
A performTasks() 0 10 2
A getLogSkipped() 0 7 2
A testIfCondition() 0 15 4
A setDescription() 0 3 1
A dependsOn() 0 3 1
A __toString() 0 3 1
A addTask() 0 3 1
A getName() 0 3 1
A addDataType() 0 3 1
A setUnless() 0 3 1
A setName() 0 3 1
B main() 0 21 9
A setLogSkipped() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Target often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Target, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19
20
/**
21
 * The Target component. Carries all required target data. Implements the
22
 * abstract class {@link TaskContainer}
23
 *
24
 * @author    Andreas Aderhold <[email protected]>
25
 * @copyright 2001,2002 THYRELL. All rights reserved
26
 * @see       TaskContainer
27
 * @package   phing
28
 */
29
class Target implements TaskContainer
30
{
31
32
    /**
33
     * Name of target
34
     *
35
     * @var string
36
     */
37
    private $name;
38
39
    /**
40
     * Dependencies
41
     *
42
     * @var array
43
     */
44
    private $dependencies = [];
45
46
    /**
47
     * Holds objects of children of this target
48
     *
49
     * @var array
50
     */
51
    private $children = [];
52
53
    /**
54
     * The if condition from xml
55
     *
56
     * @var string
57
     */
58
    private $ifCondition = "";
59
60
    /**
61
     * The unless condition from xml
62
     *
63
     * @var string
64
     */
65
    private $unlessCondition = "";
66
67
    /**
68
     * Description of this target
69
     *
70
     * @var string
71
     */
72
    private $description;
73
74
    /**
75
     * Whether to hide target in targets list (-list -p switches)
76
     *
77
     * @var boolean
78
     */
79
    private $hidden = false;
80
81
    /**
82
     * Whether to log message as INFO or VERBOSE if target skipped
83
     *
84
     * @var boolean
85
     */
86
    private $logSkipped = false;
87
88
    /**
89
     * Rreference to project
90
     *
91
     * @var Project
92
     */
93
    private $project;
94
95
    /**
96
     * References the project to the current component.
97
     *
98
     * @param Project $project The reference to the current project
99
     */
100 791
    public function setProject(Project $project)
101
    {
102 791
        $this->project = $project;
103 791
    }
104
105
    /**
106
     * Returns reference to current project
107
     *
108
     * @return Project Reference to current porject object
109
     */
110 603
    public function getProject()
111
    {
112 603
        return $this->project;
113
    }
114
115
    /**
116
     * Sets the target dependencies from xml
117
     *
118
     * @param  string $depends Comma separated list of targetnames that depend on
119
     *                         this target
120
     * @throws BuildException
121
     */
122 239
    public function setDepends($depends)
123
    {
124
        // explode should be faster than strtok
125 239
        $deps = explode(',', $depends);
126 239
        for ($i = 0, $size = count($deps); $i < $size; $i++) {
127 239
            $trimmed = trim($deps[$i]);
128 239
            if ($trimmed === "") {
129 2
                throw new BuildException(
130 2
                    "Syntax Error: Depend attribute for target " . $this->getName() . " is malformed."
131
                );
132
            }
133 238
            $this->addDependency($trimmed);
134
        }
135 237
    }
136
137
    /**
138
     * Adds a singular dependent target name to the list
139
     *
140
     * @param string $dependency The dependency target to add
141
     */
142 238
    public function addDependency($dependency)
143
    {
144 238
        $this->dependencies[] = (string) $dependency;
145 238
    }
146
147
    /**
148
     * Returns reference to indexed array of the dependencies this target has.
149
     *
150
     * @return array Reference to target dependencoes
151
     */
152 791
    public function getDependencies()
153
    {
154 791
        return $this->dependencies;
155
    }
156
157
    /**
158
     * @param string $targetName Name of the target to search for
159
     * @return false|int|string
160
     */
161 7
    public function dependsOn($targetName)
162
    {
163 7
        return \array_search($targetName, $this->dependencies);
164
    }
165
166
    /**
167
     * Sets the name of the target
168
     *
169
     * @param string $name Name of this target
170
     */
171 791
    public function setName($name)
172
    {
173 791
        $this->name = (string) $name;
174 791
    }
175
176
    /**
177
     * Returns name of this target.
178
     *
179
     * @return string The name of the target
180
     */
181 559
    public function getName()
182
    {
183 559
        return (string) $this->name;
184
    }
185
186
    /**
187
     * Set target status. If true, target does not come in phing -list
188
     *
189
     * @param  boolean $flag
190
     * @return Target
191
     */
192 791
    public function setHidden($flag)
193
    {
194 791
        $this->hidden = (bool) $flag;
195
196 791
        return $this;
197
    }
198
199
    /**
200
     * Get target status. If true, target does not come in phing -list
201
     *
202
     * @return boolean
203
     */
204
    public function getHidden()
205
    {
206
        return $this->hidden;
207
    }
208
209
    /**
210
     * Alias for getHidden()
211
     *
212
     * @return boolean
213
     */
214
    public function isHidden()
215
    {
216
        return $this->getHidden();
217
    }
218
219
    /**
220
     * Adds a task element to the list of this targets child elements
221
     *
222
     * @param Task $task The task object to add
223
     */
224 789
    public function addTask(Task $task)
225
    {
226 789
        $this->children[] = $task;
227 789
    }
228
229
    /**
230
     * Adds a runtime configurable element to the list of this targets child
231
     * elements.
232
     *
233
     * @param RuntimeConfigurable $rtc The RuntimeConfigurable object
234
     */
235 4
    public function addDataType($rtc)
236
    {
237 4
        $this->children[] = $rtc;
238 4
    }
239
240
    /**
241
     * Returns an array of all tasks this target has as childrens.
242
     *
243
     * The task objects are copied here. Don't use this method to modify
244
     * task objects.
245
     *
246
     * @return array Task[]
247
     */
248 791
    public function getTasks()
249
    {
250 791
        $tasks = [];
251 791
        for ($i = 0, $size = count($this->children); $i < $size; $i++) {
252 784
            $tsk = $this->children[$i];
253 784
            if ($tsk instanceof Task) {
254
                // note: we're copying objects here!
255 784
                $tasks[] = clone $tsk;
256
            }
257
        }
258
259 791
        return $tasks;
260
    }
261
262
    /**
263
     * Set the if-condition from the XML tag, if any. The property name given
264
     * as parameter must be present so the if condition evaluates to true
265
     *
266
     * @param string $property The property name that has to be present
267
     */
268 791
    public function setIf($property)
269
    {
270 791
        $this->ifCondition = $property ?? "";
271 791
    }
272
273
    /**
274
     * Set the unless-condition from the XML tag, if any. The property name
275
     * given as parameter must be present so the unless condition evaluates
276
     * to true
277
     *
278
     * @param string $property The property name that has to be present
279
     */
280 791
    public function setUnless($property)
281
    {
282 791
        $this->unlessCondition = $property ?? "";
283 791
    }
284
285
    /**
286
     * Sets a textual description of this target.
287
     *
288
     * @param string $description The description text
289
     */
290 791
    public function setDescription($description)
291
    {
292 791
        $this->description = $description;
293 791
    }
294
295
    /**
296
     * Returns the description of this target.
297
     *
298
     * @return string The description text of this target
299
     */
300
    public function getDescription()
301
    {
302
        return $this->description;
303
    }
304
305 791
    public function setLogSkipped(bool $log)
306
    {
307 791
        $this->logSkipped = $log;
308 791
    }
309
310
    /**
311
     * @return bool|null
312
     */
313 10
    public function getLogSkipped()
314
    {
315 10
        if ($this->logSkipped === null) {
316
            $this->setLogSkipped(false);
317
        }
318
319 10
        return $this->logSkipped;
320
    }
321
322
    /**
323
     * Returns a string representation of this target. In our case it
324
     * simply returns the target name field
325
     *
326
     * @return string The string representation of this target
327
     */
328 599
    public function __toString()
329
    {
330 599
        return (string) $this->name;
331
    }
332
333
    /**
334
     * The entry point for this class. Does some checking, then processes and
335
     * performs the tasks for this target.
336
     */
337 791
    public function main()
338
    {
339 791
        if ($this->testIfCondition() && $this->testUnlessCondition()) {
340 791
            foreach ($this->children as $o) {
341 652
                if ($o instanceof Task) {
342
                    // child is a task
343 652
                    $o->perform();
344 1
                } elseif ($o instanceof RuntimeConfigurable) {
345
                    // child is a RuntimeConfigurable
346 1
                    $o->maybeConfigure($this->project);
347
                }
348
            }
349 10
        } elseif (!$this->testIfCondition()) {
350 2
            $this->project->log(
351 2
                "Skipped target '" . $this->name . "' because property '" . $this->ifCondition . "' not set.",
352 2
                $this->getLogSkipped() ? Project::MSG_INFO : Project::MSG_VERBOSE
353
            );
354
        } else {
355 8
            $this->project->log(
356 8
                "Skipped target '" . $this->name . "' because property '" . $this->unlessCondition . "' set.",
357 8
                $this->getLogSkipped() ? Project::MSG_INFO : Project::MSG_VERBOSE
358
            );
359
        }
360 791
    }
361
362
    /**
363
     * Performs the tasks by calling the main method of this target that
364
     * actually executes the tasks.
365
     *
366
     * This method is for ZE2 and used for proper exception handling of
367
     * task exceptions.
368
     */
369 599
    public function performTasks()
370
    {
371
        try { // try to execute this target
372 599
            $this->project->fireTargetStarted($this);
373 599
            $this->main();
374 471
            $this->project->fireTargetFinished($this, $null = null);
375 158
        } catch (BuildException $exc) {
376
            // log here and rethrow
377 158
            $this->project->fireTargetFinished($this, $exc);
378 158
            throw $exc;
379
        }
380 471
    }
381
382
    /**
383
     * Tests if the property set in ifConfiditon exists.
384
     *
385
     * @return boolean <code>true</code> if the property specified
386
     *                 in <code>$this->ifCondition</code> exists;
387
     *                 <code>false</code> otherwise
388
     */
389 791
    private function testIfCondition()
390
    {
391 791
        if ($this->ifCondition === "") {
392 791
            return true;
393
        }
394
395 3
        $properties = explode(",", $this->ifCondition);
396
397 3
        $result = true;
398 3
        foreach ($properties as $property) {
399 3
            $test = $this->getProject()->replaceProperties($property);
400 3
            $result = $result && ($this->project->getProperty($test) !== null);
0 ignored issues
show
introduced by
The condition $this->project->getProperty($test) !== null is always true.
Loading history...
401
        }
402
403 3
        return $result;
404
    }
405
406
    /**
407
     * Tests if the property set in unlessCondition exists.
408
     *
409
     * @return boolean <code>true</code> if the property specified
410
     *                 in <code>$this->unlessCondition</code> exists;
411
     *                 <code>false</code> otherwise
412
     */
413 791
    private function testUnlessCondition()
414
    {
415 791
        if ($this->unlessCondition === "") {
416 791
            return true;
417
        }
418
419 8
        $properties = explode(",", $this->unlessCondition);
420
421 8
        $result = true;
422 8
        foreach ($properties as $property) {
423 8
            $test = $this->getProject()->replaceProperties($property);
424 8
            $result = $result && ($this->project->getProperty($test) === null);
0 ignored issues
show
introduced by
The condition $this->project->getProperty($test) === null is always false.
Loading history...
425
        }
426
427 8
        return $result;
428
    }
429
}
430