Passed
Push — master ( fd43ba...a7f15e )
by Siad
11:00
created

ForeachTask::createParam()   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 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
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
 * <foreach> task
22
 *
23
 * Task definition for the foreach task.  This task takes a list with
24
 * delimited values, and executes a target with set param.
25
 *
26
 * Usage:
27
 * <foreach list="values" target="targ" param="name" delimiter="|" />
28
 *
29
 * Attributes:
30
 * list      --> The list of values to process, with the delimiter character,
31
 *               indicated by the "delimiter" attribute, separating each value.
32
 * target    --> The target to call for each token, passing the token as the
33
 *               parameter with the name indicated by the "param" attribute.
34
 * param     --> The name of the parameter to pass the tokens in as to the
35
 *               target.
36
 * delimiter --> The delimiter string that separates the values in the "list"
37
 *               parameter.  The default is ",".
38
 *
39
 * @author  Jason Hines <[email protected]>
40
 * @author  Hans Lellelid <[email protected]>
41
 * @package phing.tasks.system
42
 */
43
class ForeachTask extends Task
44
{
45
    use ResourceAware;
46
47
    /**
48
     * Delimter-separated list of values to process.
49
     */
50
    private $list;
51
52
    /**
53
     * Name of parameter to pass to callee
54
     */
55
    private $param;
56
57
    /**
58
     * @var PropertyTask[] $params
59
     */
60
    private $params = [];
61
62
    /**
63
     * Name of absolute path parameter to pass to callee
64
     */
65
    private $absparam;
66
67
    /**
68
     * Delimiter that separates items in $list
69
     */
70
    private $delimiter = ',';
71
72
    /**
73
     * PhingCallTask that will be invoked w/ calleeTarget.
74
     *
75
     * @var PhingCallTask
76
     */
77
    private $callee;
78
79
    /**
80
     * Instance of mapper
81
     */
82
    private $mapperElement;
83
84
    /**
85
     * Target to execute.
86
     *
87
     * @var string
88
     */
89
    private $calleeTarget;
90
91
    /**
92
     * Total number of files processed
93
     *
94
     * @var integer
95
     */
96
    private $total_files = 0;
97
98
    /**
99
     * Total number of directories processed
100
     *
101
     * @var integer
102
     */
103
    private $total_dirs = 0;
104
105
    /**
106
     * @var bool $trim
107
     */
108
    private $trim = false;
109
110
    /**
111
     * @var  $inheritAll
0 ignored issues
show
Documentation Bug introduced by
The doc comment $inheritAll at position 0 could not be parsed: Unknown type name '$inheritAll' at position 0 in $inheritAll.
Loading history...
112
     */
113
    private $inheritAll = false;
114
115
    /**
116
     * @var bool $inheritRefs
117
     */
118
    private $inheritRefs = false;
119
120
    /**
121
     * @var Path $currPath
122
     */
123
    private $currPath;
124
125
    /**
126
     * @var PhingReference[] $references
127
     */
128
    private $references = [];
129
130
    /**
131
     * @var string $index
132
     */
133
    private $index = 'index';
134
135
    /**
136
     * This method does the work.
137
     *
138
     * @throws BuildException
139
     * @return void
140
     */
141 11
    public function main()
142
    {
143
        if (
144 11
            $this->list === null
145 6
            && $this->currPath === null
146 5
            && count($this->dirsets) === 0
147 4
            && count($this->filesets) === 0
148 1
            && count($this->filelists) === 0
149
        ) {
150 1
            throw new BuildException(
151 1
                'Need either list, path, nested dirset, nested fileset or nested filelist to iterate through'
152
            );
153
        }
154 10
        if ($this->param === null) {
155 2
            throw new BuildException("You must supply a property name to set on each iteration in param");
156
        }
157 8
        if ($this->calleeTarget === null) {
158
            throw new BuildException("You must supply a target to perform");
159
        }
160
161 8
        $callee = $this->createCallTarget();
162 8
        $mapper = null;
163
164 8
        if ($this->mapperElement !== null) {
165
            $mapper = $this->mapperElement->getImplementation();
166
        }
167
168 8
        if ($this->list !== null) {
169 3
            $arr = explode($this->delimiter, $this->list);
170 3
            $total_entries = 0;
171
172 3
            foreach ($arr as $index => $value) {
173 3
                if ($this->trim) {
174
                    $value = trim($value);
175
                }
176 3
                $premapped = '';
177 3
                if ($mapper !== null) {
178
                    $premapped = $value;
179
                    $value = $mapper->main($value);
180
                    if ($value === null) {
181
                        continue;
182
                    }
183
                    $value = array_shift($value);
184
                }
185 3
                $this->log(
186 3
                    "Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''),
187 3
                    Project::MSG_VERBOSE
188
                );
189 3
                $prop = $callee->createProperty();
190 3
                $prop->setOverride(true);
191 3
                $prop->setName($this->param);
192 3
                $prop->setValue($value);
193 3
                $prop = $callee->createProperty();
194 3
                $prop->setOverride(true);
195 3
                $prop->setName($this->index);
196 3
                $prop->setValue($index);
197 3
                $callee->main();
198 3
                $total_entries++;
199
            }
200
        }
201
202 8
        if ($this->currPath !== null) {
203 1
            $pathElements = $this->currPath->listPaths();
204 1
            foreach ($pathElements as $pathElement) {
205 1
                $ds = new DirectoryScanner();
206 1
                $ds->setBasedir($pathElement);
207 1
                $ds->scan();
208 1
                $this->process($callee, new PhingFile($pathElement), $ds->getIncludedFiles(), array());
209
            }
210
        }
211
212
        // filelists
213 8
        foreach ($this->filelists as $fl) {
214
            $srcFiles = $fl->getFiles($this->project);
215
216
            $this->process($callee, $fl->getDir($this->project), $srcFiles, []);
217
        }
218
219
        // filesets
220 8
        foreach ($this->filesets as $fs) {
221 3
            $ds = $fs->getDirectoryScanner($this->project);
222 3
            $srcFiles = $ds->getIncludedFiles();
223 3
            $srcDirs = $ds->getIncludedDirectories();
224
225 3
            $this->process($callee, $fs->getDir($this->project), $srcFiles, $srcDirs);
226
        }
227
228 8
        foreach ($this->dirsets as $dirset) {
229 1
            $ds = $dirset->getDirectoryScanner($this->project);
230 1
            $srcDirs = $ds->getIncludedDirectories();
231
232 1
            $this->process($callee, $dirset->getDir($this->project), [], $srcDirs);
233
        }
234
235 8
        if ($this->list === null) {
236 5
            $this->log(
237 5
                "Processed {$this->total_dirs} directories and {$this->total_files} files",
238 5
                Project::MSG_VERBOSE
239
            );
240
        } else {
241 3
            $this->log(
242 3
                "Processed $total_entries entr" . ($total_entries > 1 ? 'ies' : 'y') . " in list",
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $total_entries does not seem to be defined for all execution paths leading up to this point.
Loading history...
243 3
                Project::MSG_VERBOSE
244
            );
245
        }
246 8
    }
247
248
    /**
249
     * Processes a list of files & directories
250
     *
251
     * @param PhingCallTask $callee
252
     * @param PhingFile $fromDir
253
     * @param array $srcFiles
254
     * @param array $srcDirs
255
     */
256 5
    protected function process(Task $callee, PhingFile $fromDir, $srcFiles, $srcDirs)
257
    {
258 5
        $mapper = null;
259
260 5
        if ($this->mapperElement !== null) {
261
            $mapper = $this->mapperElement->getImplementation();
262
        }
263
264 5
        $filecount = count($srcFiles);
265 5
        $this->total_files += $filecount;
266
267 5
        $this->processResources($filecount, $srcFiles, $callee, $fromDir, $mapper);
268
269 5
        $dircount = count($srcDirs);
270 5
        $this->total_dirs += $dircount;
271
272 5
        $this->processResources($dircount, $srcDirs, $callee, $fromDir, $mapper);
273 5
    }
274
275
    /**
276
     * @param int $rescount
277
     * @param array $srcRes
278
     * @param $callee
279
     * @param $fromDir
280
     * @param $mapper
281
     * @throws IOException
282
     */
283 5
    private function processResources(int $rescount, array $srcRes, $callee, $fromDir, $mapper)
284
    {
285 5
        for ($j = 0; $j < $rescount; $j++) {
286 4
            $value = $srcRes[$j];
287 4
            $premapped = "";
288
289 4
            if ($this->absparam) {
290 3
                $prop = $callee->createProperty();
291 3
                $prop->setOverride(true);
292 3
                $prop->setName($this->absparam);
293 3
                $prop->setValue($fromDir . FileSystem::getFileSystem()->getSeparator() . $value);
294
            }
295
296 4
            if ($mapper !== null) {
297
                $premapped = $value;
298
                $value = $mapper->main($value);
299
                if ($value === null) {
300
                    continue;
301
                }
302
                $value = array_shift($value);
303
            }
304
305 4
            if ($this->param) {
306 4
                $this->log(
307 4
                    "Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''),
308 4
                    Project::MSG_VERBOSE
309
                );
310 4
                $prop = $callee->createProperty();
311 4
                $prop->setOverride(true);
312 4
                $prop->setName($this->param);
313 4
                $prop->setValue($value);
314
            }
315
316 4
            $callee->main();
317
        }
318 5
    }
319
320
    public function setTrim($trim)
321
    {
322
        $this->trim = $trim;
323
    }
324
325
    /**
326
     * @param $list
327
     */
328 5
    public function setList($list)
329
    {
330 5
        $this->list = (string) $list;
331 5
    }
332
333
    /**
334
     * @param $target
335
     */
336 9
    public function setTarget($target)
337
    {
338 9
        $this->calleeTarget = (string) $target;
339 9
    }
340
341
    /**
342
     * @param PropertyTask $param
343
     */
344
    public function addParam(PropertyTask $param)
345
    {
346
        $this->params[] = $param;
347
    }
348
349
    /**
350
     * Corresponds to <code>&lt;phingcall&gt;</code>'s nested
351
     * <code>&lt;reference&gt;</code> element.
352
     */
353 1
    public function addReference(PhingReference $r)
354
    {
355 1
        $this->references[] = $r;
356 1
    }
357
358
    /**
359
     * @param $absparam
360
     */
361 4
    public function setAbsparam($absparam)
362
    {
363 4
        $this->absparam = (string) $absparam;
364 4
    }
365
366
    /**
367
     * @param $delimiter
368
     */
369
    public function setDelimiter($delimiter)
370
    {
371
        $this->delimiter = (string) $delimiter;
372
    }
373
374
    public function setIndex($index)
375
    {
376
        $this->index = $index;
377
    }
378
379 1
    public function createPath()
380
    {
381 1
        if ($this->currPath === null) {
382 1
            $this->currPath = new Path($this->getProject());
383
        }
384
385 1
        return $this->currPath;
386
    }
387
388
    /**
389
     * Nested creator, creates one Mapper for this task
390
     *
391
     * @return object         The created Mapper type object
392
     * @throws BuildException
393
     */
394
    public function createMapper()
395
    {
396
        if ($this->mapperElement !== null) {
397
            throw new BuildException("Cannot define more than one mapper", $this->getLocation());
398
        }
399
        $this->mapperElement = new Mapper($this->project);
400
401
        return $this->mapperElement;
402
    }
403
404
    /**
405
     * @return PropertyTask
406
     */
407
    public function createProperty()
408
    {
409
        return $this->callee->createProperty();
410
    }
411
412
    /**
413
     * @return PropertyTask
414
     */
415
    public function createParam()
416
    {
417
        return $this->callee->createProperty();
418
    }
419
420
    /**
421
     * @param string $param
422
     */
423 8
    public function setParam($param)
424
    {
425 8
        $this->param = $param;
426 8
    }
427
428
    /**
429
     * Corresponds to <code>&lt;antcall&gt;</code>'s <code>inheritall</code>
430
     * attribute.
431
     */
432
    public function setInheritall($b)
433
    {
434
        $this->inheritAll = $b;
435
    }
436
437
    /**
438
     * Corresponds to <code>&lt;antcall&gt;</code>'s <code>inheritrefs</code>
439
     * attribute.
440
     */
441
    public function setInheritrefs($b)
442
    {
443
        $this->inheritRefs = $b;
444
    }
445
446 8
    private function createCallTarget()
447
    {
448
        /**
449
         * @var PhingCallTask $ct
450
         */
451 8
        $ct = $this->getProject()->createTask("phingcall");
452 8
        $ct->setOwningTarget($this->getOwningTarget());
453 8
        $ct->setTaskName($this->getTaskName());
454 8
        $ct->setLocation($this->getLocation());
455 8
        $ct->init();
456 8
        $ct->setTarget($this->calleeTarget);
457 8
        $ct->setInheritAll($this->inheritAll);
458 8
        $ct->setInheritRefs($this->inheritRefs);
459 8
        foreach ($this->params as $param) {
460
            $toSet = $ct->createParam();
461
            $toSet->setName($param->getName());
462
            if ($param->getValue() !== null) {
463
                $toSet->setValue($param->getValue());
464
            }
465
466
            if ($param->getFile() != null) {
467
                $toSet->setFile($param->getFile());
468
            }
469
            if ($param->getPrefix() != null) {
470
                $toSet->setPrefix($param->getPrefix());
471
            }
472
            if ($param->getRefid() != null) {
473
                $toSet->setRefid($param->getRefid());
474
            }
475
            if ($param->getEnvironment() != null) {
476
                $toSet->setEnvironment($param->getEnvironment());
477
            }
478
        }
479
480 8
        foreach ($this->references as $ref) {
481 1
            $ct->addReference($ref);
482
        }
483
484 8
        return $ct;
485
    }
486
}
487