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 <jason@greenhell.com>
40
 * @author  Hans Lellelid <hans@xmpl.org>
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
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 1
    public function main()
142
    {
143
        if (
144 1
            $this->list === null
145 1
            && $this->currPath === null
146 1
            && count($this->dirsets) === 0
147 1
            && 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 1
        if ($this->param === null) {
155 1
            throw new BuildException("You must supply a property name to set on each iteration in param");
156
        }
157 1
        if ($this->calleeTarget === null) {
158 0
            throw new BuildException("You must supply a target to perform");
159
        }
160

161 1
        $callee = $this->createCallTarget();
162 1
        $mapper = null;
163

164 1
        if ($this->mapperElement !== null) {
165 0
            $mapper = $this->mapperElement->getImplementation();
166
        }
167

168 1
        if ($this->list !== null) {
169 1
            $arr = explode($this->delimiter, $this->list);
170 1
            $total_entries = 0;
171

172 1
            foreach ($arr as $index => $value) {
173 1
                if ($this->trim) {
174 0
                    $value = trim($value);
175
                }
176 1
                $premapped = '';
177 1
                if ($mapper !== null) {
178 0
                    $premapped = $value;
179 0
                    $value = $mapper->main($value);
180 0
                    if ($value === null) {
181 0
                        continue;
182
                    }
183 0
                    $value = array_shift($value);
184
                }
185 1
                $this->log(
186 1
                    "Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''),
187 1
                    Project::MSG_VERBOSE
188
                );
189 1
                $prop = $callee->createProperty();
190 1
                $prop->setName($this->param);
191 1
                $prop->setValue($value);
192 1
                $prop = $callee->createProperty();
193 1
                $prop->setName($this->index);
194 1
                $prop->setValue($index);
195 1
                $callee->main();
196 1
                $total_entries++;
197
            }
198
        }
199

200 1
        if ($this->currPath !== null) {
201 1
            $pathElements = $this->currPath->listPaths();
202 1
            foreach ($pathElements as $pathElement) {
203 1
                $ds = new DirectoryScanner();
204 1
                $ds->setBasedir($pathElement);
205 1
                $ds->scan();
206 1
                $this->process($callee, new PhingFile($pathElement), $ds->getIncludedFiles(), array());
207
            }
208
        }
209

210
        // filelists
211 1
        foreach ($this->filelists as $fl) {
212 0
            $srcFiles = $fl->getFiles($this->project);
213

214 0
            $this->process($callee, $fl->getDir($this->project), $srcFiles, []);
215
        }
216

217
        // filesets
218 1
        foreach ($this->filesets as $fs) {
219 1
            $ds = $fs->getDirectoryScanner($this->project);
220 1
            $srcFiles = $ds->getIncludedFiles();
221 1
            $srcDirs = $ds->getIncludedDirectories();
222

223 1
            $this->process($callee, $fs->getDir($this->project), $srcFiles, $srcDirs);
224
        }
225

226 1
        foreach ($this->dirsets as $dirset) {
227 1
            $ds = $dirset->getDirectoryScanner($this->project);
228 1
            $srcDirs = $ds->getIncludedDirectories();
229

230 1
            $this->process($callee, $dirset->getDir($this->project), [], $srcDirs);
231
        }
232

233 1
        if ($this->list === null) {
234 1
            $this->log(
235 1
                "Processed {$this->total_dirs} directories and {$this->total_files} files",
236 1
                Project::MSG_VERBOSE
237
            );
238
        } else {
239 1
            $this->log(
240 1
                "Processed $total_entries entr" . ($total_entries > 1 ? 'ies' : 'y') . " in list",
241 1
                Project::MSG_VERBOSE
242
            );
243
        }
244
    }
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 1
    protected function process(Task $callee, PhingFile $fromDir, $srcFiles, $srcDirs)
255
    {
256 1
        $mapper = null;
257

258 1
        if ($this->mapperElement !== null) {
259 0
            $mapper = $this->mapperElement->getImplementation();
260
        }
261

262 1
        $filecount = count($srcFiles);
263 1
        $this->total_files += $filecount;
264

265 1
        $this->processResources($filecount, $srcFiles, $callee, $fromDir, $mapper);
266

267 1
        $dircount = count($srcDirs);
268 1
        $this->total_dirs += $dircount;
269

270 1
        $this->processResources($dircount, $srcDirs, $callee, $fromDir, $mapper);
271
    }
272

273
    /**
274
     * @param int $rescount
275
     * @param array $srcRes
276
     * @param $callee
277
     * @param $fromDir
278
     * @param $mapper
279
     * @throws IOException
280
     */
281 1
    private function processResources(int $rescount, array $srcRes, $callee, $fromDir, $mapper)
282
    {
283 1
        for ($j = 0; $j < $rescount; $j++) {
284 1
            $value = $srcRes[$j];
285 1
            $premapped = "";
286

287 1
            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 1
            if ($mapper !== null) {
294 0
                $premapped = $value;
295 0
                $value = $mapper->main($value);
296 0
                if ($value === null) {
297 0
                    continue;
298
                }
299 0
                $value = array_shift($value);
300
            }
301

302 1
            if ($this->param) {
303 1
                $this->log(
304 1
                    "Setting param '$this->param' to value '$value'" . ($premapped ? " (mapped from '$premapped')" : ''),
305 1
                    Project::MSG_VERBOSE
306
                );
307 1
                $prop = $callee->createProperty();
308 1
                $prop->setName($this->param);
309 1
                $prop->setValue($value);
310
            }
311

312 1
            $callee->main();
313
        }
314
    }
315

316 0
    public function setTrim($trim)
317
    {
318 0
        $this->trim = $trim;
319
    }
320

321
    /**
322
     * @param $list
323
     */
324 1
    public function setList($list)
325
    {
326 1
        $this->list = (string) $list;
327
    }
328

329
    /**
330
     * @param $target
331
     */
332 1
    public function setTarget($target)
333
    {
334 1
        $this->calleeTarget = (string) $target;
335
    }
336

337
    /**
338
     * @param PropertyTask $param
339
     */
340 0
    public function addParam(PropertyTask $param)
341
    {
342 0
        $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
    }
353

354
    /**
355
     * @param $absparam
356
     */
357 1
    public function setAbsparam($absparam)
358
    {
359 1
        $this->absparam = (string) $absparam;
360
    }
361

362
    /**
363
     * @param $delimiter
364
     */
365 0
    public function setDelimiter($delimiter)
366
    {
367 0
        $this->delimiter = (string) $delimiter;
368
    }
369

370 0
    public function setIndex($index)
371
    {
372 0
        $this->index = $index;
373
    }
374

375 1
    public function createPath()
376
    {
377 1
        if ($this->currPath === null) {
378 1
            $this->currPath = new Path($this->getProject());
379
        }
380

381 1
        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 0
    public function createMapper()
391
    {
392 0
        if ($this->mapperElement !== null) {
393 0
            throw new BuildException("Cannot define more than one mapper", $this->getLocation());
394
        }
395 0
        $this->mapperElement = new Mapper($this->project);
396

397 0
        return $this->mapperElement;
398
    }
399

400
    /**
401
     * @return PropertyTask
402
     */
403 0
    public function createProperty()
404
    {
405 0
        return $this->callee->createProperty();
406
    }
407

408
    /**
409
     * @return PropertyTask
410
     */
411 0
    public function createParam()
412
    {
413 0
        return $this->callee->createProperty();
414
    }
415

416
    /**
417
     * @param string $param
418
     */
419 1
    public function setParam($param)
420
    {
421 1
        $this->param = $param;
422
    }
423

424
    /**
425
     * Corresponds to <code>&lt;antcall&gt;</code>'s <code>inheritall</code>
426
     * attribute.
427
     */
428 0
    public function setInheritall($b)
429
    {
430 0
        $this->inheritAll = $b;
431
    }
432

433
    /**
434
     * Corresponds to <code>&lt;antcall&gt;</code>'s <code>inheritrefs</code>
435
     * attribute.
436
     */
437 0
    public function setInheritrefs($b)
438
    {
439 0
        $this->inheritRefs = $b;
440
    }
441

442 1
    private function createCallTarget()
443
    {
444
        /**
445
         * @var PhingCallTask $ct
446
         */
447 1
        $ct = $this->getProject()->createTask("phingcall");
448 1
        $ct->setOwningTarget($this->getOwningTarget());
449 1
        $ct->setTaskName($this->getTaskName());
450 1
        $ct->setLocation($this->getLocation());
451 1
        $ct->init();
452 1
        $ct->setTarget($this->calleeTarget);
453 1
        $ct->setInheritAll($this->inheritAll);
454 1
        $ct->setInheritRefs($this->inheritRefs);
455 1
        foreach ($this->params as $param) {
456 0
            $toSet = $ct->createParam();
457 0
            $toSet->setName($param->getName());
458 0
            if ($param->getValue() !== null) {
459 0
                $toSet->setValue($param->getValue());
460
            }
461

462 0
            if ($param->getFile() != null) {
463 0
                $toSet->setFile($param->getFile());
464
            }
465 0
            if ($param->getPrefix() != null) {
466 0
                $toSet->setPrefix($param->getPrefix());
467
            }
468 0
            if ($param->getRefid() != null) {
469 0
                $toSet->setRefid($param->getRefid());
470
            }
471 0
            if ($param->getEnvironment() != null) {
472 0
                $toSet->setEnvironment($param->getEnvironment());
473
            }
474
        }
475

476 1
        foreach ($this->references as $ref) {
477 1
            $ct->addReference($ref);
478
        }
479

480 1
        return $ct;
481
    }
482
}

Read our documentation on viewing source code .

Loading