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

ForeachTask::main()   F

Complexity

Conditions 22
Paths 131

Size

Total Lines 103
Code Lines 69

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 58
CRAP Score 23.5405

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 22
eloc 69
c 1
b 0
f 0
nc 131
nop 0
dl 0
loc 103
ccs 58
cts 68
cp 0.8529
crap 23.5405
rs 3.9083

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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