Passed
Push — master ( d68b8d...e5c614 )
by Siad
10:45
created

ForeachTask::main()   F

Complexity

Conditions 22
Paths 131

Size

Total Lines 101
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 47
CRAP Score 33.5496

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 22
eloc 67
c 1
b 0
f 0
nc 131
nop 0
dl 0
loc 101
ccs 47
cts 66
cp 0.7121
crap 33.5496
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 9
    public function main()
142
    {
143
        if (
144 9
            $this->list === null
145 4
            && $this->currPath === null
146 4
            && 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 8
        if ($this->param === null) {
155 2
            throw new BuildException("You must supply a property name to set on each iteration in param");
156
        }
157 6
        if ($this->calleeTarget === null) {
158
            throw new BuildException("You must supply a target to perform");
159
        }
160
161 6
        $callee = $this->createCallTarget();
162 6
        $mapper = null;
163
164 6
        if ($this->mapperElement !== null) {
165
            $mapper = $this->mapperElement->getImplementation();
166
        }
167
168 6
        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->setName($this->param);
191 3
                $prop->setValue($value);
192 3
                $prop = $callee->createProperty();
193 3
                $prop->setName($this->index);
194 3
                $prop->setValue($index);
195 3
                $callee->main();
196 3
                $total_entries++;
197
            }
198
        }
199
200 6
        if ($this->currPath !== null) {
201
            $pathElements = $this->currPath->listPaths();
202
            foreach ($pathElements as $pathElement) {
203
                $ds = new DirectoryScanner();
204
                $ds->setBasedir($pathElement);
205
                $ds->scan();
206
                $this->process($callee, new PhingFile($pathElement), $ds->getIncludedFiles(), array());
207
            }
208
        }
209
210
        // filelists
211 6
        foreach ($this->filelists as $fl) {
212
            $srcFiles = $fl->getFiles($this->project);
213
214
            $this->process($callee, $fl->getDir($this->project), $srcFiles, []);
215
        }
216
217
        // filesets
218 6
        foreach ($this->filesets as $fs) {
219 3
            $ds = $fs->getDirectoryScanner($this->project);
220 3
            $srcFiles = $ds->getIncludedFiles();
221 3
            $srcDirs = $ds->getIncludedDirectories();
222
223 3
            $this->process($callee, $fs->getDir($this->project), $srcFiles, $srcDirs);
224
        }
225
226 6
        foreach ($this->dirsets as $dirset) {
227
            $ds = $dirset->getDirectoryScanner($this->project);
228
            $srcDirs = $ds->getIncludedDirectories();
229
230
            $this->process($callee, $dirset->getDir($this->project), [], $srcDirs);
231
        }
232
233 6
        if ($this->list === null) {
234 3
            $this->log(
235 3
                "Processed {$this->total_dirs} directories and {$this->total_files} files",
236 3
                Project::MSG_VERBOSE
237
            );
238
        } else {
239 3
            $this->log(
240 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...
241 3
                Project::MSG_VERBOSE
242
            );
243
        }
244 6
    }
245
246
    /**
247
     * Processes a list of files & directories
248
     *
249
     * @param PhingCallTask $callee
250
     * @param PhingFile $fromDir
251
     * @param array $srcFiles
252
     * @param array $srcDirs
253
     */
254 3
    protected function process(Task $callee, PhingFile $fromDir, $srcFiles, $srcDirs)
255
    {
256 3
        $mapper = null;
257
258 3
        if ($this->mapperElement !== null) {
259
            $mapper = $this->mapperElement->getImplementation();
260
        }
261
262 3
        $filecount = count($srcFiles);
263 3
        $this->total_files += $filecount;
264
265 3
        $this->processResources($filecount, $srcFiles, $callee, $fromDir, $mapper);
266
267 3
        $dircount = count($srcDirs);
268 3
        $this->total_dirs += $dircount;
269
270 3
        $this->processResources($dircount, $srcDirs, $callee, $fromDir, $mapper);
271 3
    }
272
273
    /**
274
     * @param int $rescount
275
     * @param array $srcRes
276
     * @param $callee
277
     * @param $fromDir
278
     * @param $mapper
279
     * @throws IOException
280
     */
281 3
    private function processResources(int $rescount, array $srcRes, $callee, $fromDir, $mapper)
282
    {
283 3
        for ($j = 0; $j < $rescount; $j++) {
284 2
            $value = $srcRes[$j];
285 2
            $premapped = "";
286
287 2
            if ($this->absparam) {
288 1
                $prop = $callee->createProperty();
289 1
                $prop->setName($this->absparam);
290 1
                $prop->setValue($fromDir . FileSystem::getFileSystem()->getSeparator() . $value);
291
            }
292
293 2
            if ($mapper !== null) {
294
                $premapped = $value;
295
                $value = $mapper->main($value);
296
                if ($value === null) {
297
                    continue;
298
                }
299
                $value = array_shift($value);
300
            }
301
302 2
            if ($this->param) {
303 2
                $this->log(
304 2
                    "Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''),
305 2
                    Project::MSG_VERBOSE
306
                );
307 2
                $prop = $callee->createProperty();
308 2
                $prop->setName($this->param);
309 2
                $prop->setValue($value);
310
            }
311
312 2
            $callee->main();
313
        }
314 3
    }
315
316
    public function setTrim($trim)
317
    {
318
        $this->trim = $trim;
319
    }
320
321
    /**
322
     * @param $list
323
     */
324 5
    public function setList($list)
325
    {
326 5
        $this->list = (string) $list;
327 5
    }
328
329
    /**
330
     * @param $target
331
     */
332 7
    public function setTarget($target)
333
    {
334 7
        $this->calleeTarget = (string) $target;
335 7
    }
336
337
    /**
338
     * @param PropertyTask $param
339
     */
340
    public function addParam(PropertyTask $param)
341
    {
342
        $this->params[] = $param;
343
    }
344
345
    /**
346
     * Corresponds to <code>&lt;phingcall&gt;</code>'s nested
347
     * <code>&lt;reference&gt;</code> element.
348
     */
349 1
    public function addReference(PhingReference $r)
350
    {
351 1
        $this->references[] = $r;
352 1
    }
353
354
    /**
355
     * @param $absparam
356
     */
357 2
    public function setAbsparam($absparam)
358
    {
359 2
        $this->absparam = (string) $absparam;
360 2
    }
361
362
    /**
363
     * @param $delimiter
364
     */
365
    public function setDelimiter($delimiter)
366
    {
367
        $this->delimiter = (string) $delimiter;
368
    }
369
370
    public function setIndex($index)
371
    {
372
        $this->index = $index;
373
    }
374
375
    public function createPath()
376
    {
377
        if ($this->currPath === null) {
378
            $this->currPath = new Path($this->getProject());
379
        }
380
381
        return $this->currPath;
382
    }
383
384
    /**
385
     * Nested creator, creates one Mapper for this task
386
     *
387
     * @return object         The created Mapper type object
388
     * @throws BuildException
389
     */
390
    public function createMapper()
391
    {
392
        if ($this->mapperElement !== null) {
393
            throw new BuildException("Cannot define more than one mapper", $this->getLocation());
394
        }
395
        $this->mapperElement = new Mapper($this->project);
396
397
        return $this->mapperElement;
398
    }
399
400
    /**
401
     * @return PropertyTask
402
     */
403
    public function createProperty()
404
    {
405
        return $this->callee->createProperty();
406
    }
407
408
    /**
409
     * @return PropertyTask
410
     */
411
    public function createParam()
412
    {
413
        return $this->callee->createProperty();
414
    }
415
416
    /**
417
     * @param string $param
418
     */
419 6
    public function setParam($param)
420
    {
421 6
        $this->param = $param;
422 6
    }
423
424
    /**
425
     * Corresponds to <code>&lt;antcall&gt;</code>'s <code>inheritall</code>
426
     * attribute.
427
     */
428
    public function setInheritall($b)
429
    {
430
        $this->inheritAll = $b;
431
    }
432
433
    /**
434
     * Corresponds to <code>&lt;antcall&gt;</code>'s <code>inheritrefs</code>
435
     * attribute.
436
     */
437
    public function setInheritrefs($b)
438
    {
439
        $this->inheritRefs = $b;
440
    }
441
442 6
    private function createCallTarget()
443
    {
444
        /**
445
         * @var PhingCallTask $ct
446
         */
447 6
        $ct = $this->getProject()->createTask("phingcall");
448 6
        $ct->setOwningTarget($this->getOwningTarget());
449 6
        $ct->setTaskName($this->getTaskName());
450 6
        $ct->setLocation($this->getLocation());
451 6
        $ct->init();
452 6
        $ct->setTarget($this->calleeTarget);
453 6
        $ct->setInheritAll($this->inheritAll);
454 6
        $ct->setInheritRefs($this->inheritRefs);
455 6
        foreach ($this->params as $param) {
456
            $toSet = $ct->createParam();
457
            $toSet->setName($param->getName());
458
            if ($param->getValue() !== null) {
459
                $toSet->setValue($param->getValue());
460
            }
461
462
            if ($param->getFile() != null) {
463
                $toSet->setFile($param->getFile());
464
            }
465
            if ($param->getPrefix() != null) {
466
                $toSet->setPrefix($param->getPrefix());
467
            }
468
            if ($param->getRefid() != null) {
469
                $toSet->setRefid($param->getRefid());
470
            }
471
            if ($param->getEnvironment() != null) {
472
                $toSet->setEnvironment($param->getEnvironment());
473
            }
474
        }
475
476 6
        foreach ($this->references as $ref) {
477 1
            $ct->addReference($ref);
478
        }
479
480 6
        return $ct;
481
    }
482
}
483