Passed
Push — main ( c05734...58efd0 )
by Siad
08:27
created

Target::getUnless()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
c 1
b 0
f 0
cc 1
nc 1
nop 0
crap 2
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
namespace Phing;
21
22
use Phing\Exception\BuildException;
23
use Phing\Parser\Location;
24
use function array_search;
25
26
/**
27
 * The Target component. Carries all required target data. Implements the
28
 * abstract class {@link TaskContainer}
29
 *
30
 * @author    Andreas Aderhold <[email protected]>
31
 * @copyright 2001,2002 THYRELL. All rights reserved
32
 * @see       TaskContainer
33
 */
34
class Target implements TaskContainer
35
{
36
    /**
37
     * Name of target
38
     *
39
     * @var string
40
     */
41
    private $name;
42
43
    /**
44
     * Dependencies
45
     *
46
     * @var array
47
     */
48
    private $dependencies = [];
49
50
    /**
51
     * Holds objects of children of this target
52
     *
53
     * @var array
54
     */
55
    private $children = [];
56
57
    /**
58
     * The if condition from xml
59
     *
60
     * @var string
61
     */
62
    private $ifCondition = "";
63
64
    /**
65
     * The unless condition from xml
66
     *
67
     * @var string
68
     */
69
    private $unlessCondition = "";
70
71
    /**
72
     * Description of this target
73
     *
74
     * @var string
75
     */
76
    private $description;
77
78
    /**
79
     * Whether to hide target in targets list (-list -p switches)
80
     *
81
     * @var boolean
82
     */
83
    private $hidden = false;
84
85
    /**
86
     * Whether to log message as INFO or VERBOSE if target skipped
87
     *
88
     * @var boolean
89
     */
90
    private $logSkipped = false;
91
92
    /**
93
     * Rreference to project
94
     *
95
     * @var Project
96
     */
97
    private $project;
98
    private $location;
99
100 855
    public function __construct(Target $other = null)
101
    {
102 855
        if ($other !== null) {
103
            $this->name = $other->name;
104
            $this->ifCondition = $other->ifCondition;
105
            $this->unlessCondition = $other->unlessCondition;
106
            $this->dependencies = $other->dependencies;
107
            $this->location = $other->location;
108
            $this->project = $other->project;
109
            $this->description = $other->description;
110
            // The children are added to after this cloning
111
            $this->children = $other->children;
112
        }
113 855
    }
114
115
    /**
116
     * References the project to the current component.
117
     *
118
     * @param Project $project The reference to the current project
119
     */
120 854
    public function setProject(Project $project)
121
    {
122 854
        $this->project = $project;
123 854
    }
124
125
    /**
126
     * Returns reference to current project
127
     *
128
     * @return Project Reference to current porject object
129
     */
130 669
    public function getProject()
131
    {
132 669
        return $this->project;
133
    }
134
135
    /**
136
     * Sets the location of this target's definition.
137
     *
138
     * @param location location
139
     */
140 854
    public function setLocation(Location $location): void
141
    {
142 854
        $this->location = $location;
143 854
    }
144
145
    /**
146
     * Get the location of this target's definition.
147
     *
148
     */
149 1
    public function getLocation(): Location
150
    {
151 1
        return $this->location;
152
    }
153
154
    /**
155
     * Sets the target dependencies from xml
156
     *
157
     * @param string $depends Comma separated list of targetnames that depend on
158
     *                         this target
159
     * @throws BuildException
160
     */
161 261
    public function setDepends($depends)
162
    {
163
        // explode should be faster than strtok
164 261
        $deps = explode(',', $depends);
165 261
        for ($i = 0, $size = count($deps); $i < $size; $i++) {
166 261
            $trimmed = trim($deps[$i]);
167 261
            if ($trimmed === "") {
168 2
                throw new BuildException(
169 2
                    "Syntax Error: Depend attribute for target " . $this->getName() . " is malformed."
170
                );
171
            }
172 260
            $this->addDependency($trimmed);
173
        }
174 259
    }
175
176
    /**
177
     * Adds a singular dependent target name to the list
178
     *
179
     * @param string $dependency The dependency target to add
180
     */
181 260
    public function addDependency($dependency)
182
    {
183 260
        $this->dependencies[] = (string) $dependency;
184 260
    }
185
186
    /**
187
     * Returns reference to indexed array of the dependencies this target has.
188
     *
189
     * @return array Reference to target dependencoes
190
     */
191 854
    public function getDependencies()
192
    {
193 854
        return $this->dependencies;
194
    }
195
196
    /**
197
     * @param string $targetName Name of the target to search for
198
     * @return false|int|string
199
     */
200 7
    public function dependsOn($targetName)
201
    {
202 7
        return array_search($targetName, $this->dependencies);
203
    }
204
205
    /**
206
     * Sets the name of the target
207
     *
208
     * @param string $name Name of this target
209
     */
210 854
    public function setName($name)
211
    {
212 854
        $this->name = (string) $name;
213 854
    }
214
215
    /**
216
     * Returns name of this target.
217
     *
218
     * @return string The name of the target
219
     */
220 637
    public function getName()
221
    {
222 637
        return (string) $this->name;
223
    }
224
225
    /**
226
     * Set target status. If true, target does not come in phing -list
227
     *
228
     * @param bool $flag
229
     * @return Target
230
     */
231 854
    public function setHidden($flag)
232
    {
233 854
        $this->hidden = (bool) $flag;
234
235 854
        return $this;
236
    }
237
238
    /**
239
     * Get target status. If true, target does not come in phing -list
240
     *
241
     * @return bool
242
     */
243
    public function getHidden()
244
    {
245
        return $this->hidden;
246
    }
247
248
    /**
249
     * Alias for getHidden()
250
     *
251
     * @return bool
252
     */
253
    public function isHidden()
254
    {
255
        return $this->getHidden();
256
    }
257
258
    /**
259
     * Adds a task element to the list of this targets child elements
260
     *
261
     * @param Task $task The task object to add
262
     */
263 852
    public function addTask(Task $task)
264
    {
265 852
        $this->children[] = $task;
266 852
    }
267
268
    /**
269
     * Adds a runtime configurable element to the list of this targets child
270
     * elements.
271
     *
272
     * @param RuntimeConfigurable $rtc The RuntimeConfigurable object
273
     */
274 4
    public function addDataType($rtc)
275
    {
276 4
        $this->children[] = $rtc;
277 4
    }
278
279
    /**
280
     * Returns an array of all tasks this target has as childrens.
281
     *
282
     * The task objects are copied here. Don't use this method to modify
283
     * task objects.
284
     *
285
     * @return array Task[]
286
     */
287 854
    public function getTasks()
288
    {
289 854
        $tasks = [];
290 854
        for ($i = 0, $size = count($this->children); $i < $size; $i++) {
291 847
            $tsk = $this->children[$i];
292 847
            if ($tsk instanceof Task) {
293
                // note: we're copying objects here!
294 847
                $tasks[] = clone $tsk;
295
            }
296
        }
297
298 854
        return $tasks;
299
    }
300
301
    /**
302
     * Set the if-condition from the XML tag, if any. The property name given
303
     * as parameter must be present so the if condition evaluates to true
304
     *
305
     * @param string $property The property name that has to be present
306
     */
307 854
    public function setIf($property)
308
    {
309 854
        $this->ifCondition = $property ?? "";
310 854
    }
311
312
    public function getIf()
313
    {
314
        return $this->ifCondition;
315
    }
316
317
    /**
318
     * Set the unless-condition from the XML tag, if any. The property name
319
     * given as parameter must be present so the unless condition evaluates
320
     * to true
321
     *
322
     * @param string $property The property name that has to be present
323
     */
324 854
    public function setUnless($property)
325
    {
326 854
        $this->unlessCondition = $property ?? "";
327 854
    }
328
329
    public function getUnless()
330
    {
331
        return $this->unlessCondition;
332
    }
333
334
    /**
335
     * Sets a textual description of this target.
336
     *
337
     * @param string $description The description text
338
     */
339 854
    public function setDescription($description)
340
    {
341 854
        $this->description = $description;
342 854
    }
343
344
    /**
345
     * Returns the description of this target.
346
     *
347
     * @return string The description text of this target
348
     */
349
    public function getDescription()
350
    {
351
        return $this->description;
352
    }
353
354 854
    public function setLogSkipped(bool $log)
355
    {
356 854
        $this->logSkipped = $log;
357 854
    }
358
359
    /**
360
     * @return bool|null
361
     */
362 10
    public function getLogSkipped()
363
    {
364 10
        if ($this->logSkipped === null) {
365
            $this->setLogSkipped(false);
366
        }
367
368 10
        return $this->logSkipped;
369
    }
370
371
    /**
372
     * Returns a string representation of this target. In our case it
373
     * simply returns the target name field
374
     *
375
     * @return string The string representation of this target
376
     */
377 665
    public function __toString()
378
    {
379 665
        return (string) $this->name;
380
    }
381
382
    /**
383
     * The entry point for this class. Does some checking, then processes and
384
     * performs the tasks for this target.
385
     */
386 854
    public function main()
387
    {
388 854
        if ($this->testIfCondition() && $this->testUnlessCondition()) {
389 854
            foreach ($this->children as $o) {
390 718
                if ($o instanceof Task) {
391
                    // child is a task
392 718
                    $o->perform();
393 1
                } elseif ($o instanceof RuntimeConfigurable) {
394
                    // child is a RuntimeConfigurable
395 1
                    $o->maybeConfigure($this->project);
396
                }
397
            }
398 10
        } elseif (!$this->testIfCondition()) {
399 2
            $this->project->log(
400 2
                "Skipped target '" . $this->name . "' because property '" . $this->ifCondition . "' not set.",
401 2
                $this->getLogSkipped() ? Project::MSG_INFO : Project::MSG_VERBOSE
402
            );
403
        } else {
404 8
            $this->project->log(
405 8
                "Skipped target '" . $this->name . "' because property '" . $this->unlessCondition . "' set.",
406 8
                $this->getLogSkipped() ? Project::MSG_INFO : Project::MSG_VERBOSE
407
            );
408
        }
409 854
    }
410
411
    /**
412
     * Performs the tasks by calling the main method of this target that
413
     * actually executes the tasks.
414
     *
415
     * This method is for ZE2 and used for proper exception handling of
416
     * task exceptions.
417
     */
418 665
    public function performTasks()
419
    {
420
        try { // try to execute this target
421 665
            $this->project->fireTargetStarted($this);
422 665
            $this->main();
423 546
            $this->project->fireTargetFinished($this, $null = null);
424 174
        } catch (BuildException $exc) {
425
            // log here and rethrow
426 174
            $this->project->fireTargetFinished($this, $exc);
427 174
            throw $exc;
428
        }
429 546
    }
430
431
    /**
432
     * Tests if the property set in ifConfiditon exists.
433
     *
434
     * @return bool <code>true</code> if the property specified
435
     *                 in <code>$this->ifCondition</code> exists;
436
     *                 <code>false</code> otherwise
437
     */
438 854
    private function testIfCondition()
439
    {
440 854
        if ($this->ifCondition === "") {
441 854
            return true;
442
        }
443
444 3
        $properties = explode(",", $this->ifCondition);
445
446 3
        $result = true;
447 3
        foreach ($properties as $property) {
448 3
            $test = $this->getProject()->replaceProperties($property);
449 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...
450
        }
451
452 3
        return $result;
453
    }
454
455
    /**
456
     * Tests if the property set in unlessCondition exists.
457
     *
458
     * @return bool <code>true</code> if the property specified
459
     *                 in <code>$this->unlessCondition</code> exists;
460
     *                 <code>false</code> otherwise
461
     */
462 854
    private function testUnlessCondition()
463
    {
464 854
        if ($this->unlessCondition === "") {
465 854
            return true;
466
        }
467
468 8
        $properties = explode(",", $this->unlessCondition);
469
470 8
        $result = true;
471 8
        foreach ($properties as $property) {
472 8
            $test = $this->getProject()->replaceProperties($property);
473 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...
474
        }
475
476 8
        return $result;
477
    }
478
479
    /**
480
     * Replaces all occurrences of the given task in the list
481
     * of children with the replacement data type wrapper.
482
     * @param RuntimeConfigurable|Task $o
483
     */
484 11
    public function replaceChild(Task $task, $o)
485
    {
486 11
        $keys = array_keys($this->children, $task);
487 11
        foreach ($keys as $index) {
488 11
            $this->children[$index] = $o;
489
        }
490 11
    }
491
492
    /**
493
     * @param string $depends
494
     * @param string $targetName
495
     * @param string $attributeName
496
     * @return string[]
497
     * @throws BuildException
498
     */
499 7
    public static function parseDepends($depends, $targetName, $attributeName)
500
    {
501 7
        $list = [];
502 7
        if ($depends !== '') {
503 7
            $list = explode(',', $depends);
504 7
            array_walk($list, 'trim');
505 7
            if (count($list) === 0) {
506
                throw new BuildException("Syntax Error: "
507
                    . $attributeName
508
                    . " attribute of target \""
509
                    . $targetName
510
                    . "\" contains an empty string.");
511
            }
512
        }
513 7
        return $list;
514
    }
515
}
516