Passed
Push — master ( b9bc63...f1e2bc )
by Michiel
06:23
created

PhingTask   F

Complexity

Total Complexity 102

Size/Duplication

Total Lines 724
Duplicated Lines 0 %

Test Coverage

Coverage 76.68%

Importance

Changes 0
Metric Value
wmc 102
eloc 270
dl 0
loc 724
ccs 217
cts 283
cp 0.7668
rs 2
c 0
b 0
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
A setUseNativeBasedir() 0 3 1
F processFile() 0 141 29
A setTarget() 0 7 2
A setInheritRefs() 0 3 1
B main() 0 47 8
A setDir() 0 3 1
A setOutput() 0 3 1
B reinit() 0 37 9
A setHaltOnFailure() 0 3 1
A setInheritAll() 0 3 1
A addReference() 0 3 1
A setBuildfile() 0 3 1
B addAlmostAll() 0 17 9
A createProperty() 0 9 1
A setPhingFile() 0 6 1
F initializeProject() 0 56 10
A copyReference() 0 27 5
A init() 0 5 1
A overrideProperties() 0 20 6
B addReferences() 0 45 9
A getNewProject() 0 6 2

How to fix   Complexity   

Complex Class

Complex classes like PhingTask often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PhingTask, and based on these observations, apply Extract Interface, too.

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\Task\System;
21
22
use Exception;
23
use Phing\Exception\BuildException;
24
use Phing\Io\File;
25
use Phing\Io\FileOutputStream;
26
use Phing\Io\FileUtils;
27
use Phing\Io\OutputStream;
28
use Phing\Listener\DefaultLogger;
29
use Phing\Parser\ProjectConfigurator;
30
use Phing\Phing;
31
use Phing\Project;
32
use Phing\ProjectComponent;
33
use Phing\Target;
34
use Phing\Task;
35
use Phing\Type\Element\FileSetAware;
36
use Phing\Type\Reference;
37
38
/**
39
 * Task that invokes phing on another build file.
40
 *
41
 * Use this task, for example, if you have nested buildfiles in your project. Unlike
42
 * AntTask, PhingTask can even support filesets:
43
 *
44
 * <pre>
45
 *   <phing>
46
 *    <fileset dir="${srcdir}">
47
 *      <include name="** /build.xml" /> <!-- space added after ** is there because of PHP comment syntax -->
48
 *      <exclude name="build.xml" />
49
 *    </fileset>
50
 *   </phing>
51
 * </pre>
52
 *
53
 * @author  Hans Lellelid <[email protected]>
54
 * @package phing.tasks.system
55
 */
56
class PhingTask extends Task
57
{
58
    use FileSetAware;
59
60
    /**
61
     * the basedir where is executed the build file
62
     * @var File
63
     */
64
    private $dir;
65
66
    /**
67
     * build.xml (can be absolute) in this case dir will be ignored
68
     */
69
    private $phingFile;
70
71
    /**
72
     * the target to call if any
73
     * @var Target
74
     */
75
    protected $newTarget;
76
77
    /**
78
     * should we inherit properties from the parent ?
79
     */
80
    private $inheritAll = true;
81
82
    /**
83
     * should we inherit references from the parent ?
84
     */
85
    private $inheritRefs = false;
86
87
    /**
88
     * the properties to pass to the new project
89
     */
90
    private $properties = [];
91
92
    /**
93
     * the references to pass to the new project
94
     */
95
    private $references = [];
96
97
    /**
98
     * The temporary project created to run the build file
99
     *
100
     * @var Project
101
     */
102
    private $newProject;
103
104
    /**
105
     * Fail the build process when the called build fails?
106
     */
107
    private $haltOnFailure = false;
108
109
    /**
110
     * Whether the basedir of the new project should be the same one
111
     * as it would be when running the build file directly -
112
     * independent of dir and/or inheritAll settings.
113
     */
114
    private $useNativeBasedir = false;
115
116
    /**
117
     * @var OutputStream
118
     */
119
    private $out;
120
121
    /** @var string */
122
    private $output;
123
124
    /**
125
     * @var array
126
     */
127
    private $locals;
128
129 36
    public function __construct(Task $owner = null)
130
    {
131 36
        if ($owner !== null) {
132 13
            $this->bindToOwner($owner);
133
        }
134 36
        parent::__construct();
135 36
    }
136
137
    /**
138
     *  If true, abort the build process if there is a problem with or in the target build file.
139
     *  Defaults to false.
140
     *
141
     * @param bool $hof new value
142
     */
143 17
    public function setHaltOnFailure($hof)
144
    {
145 17
        $this->haltOnFailure = (bool) $hof;
146 17
    }
147
148
    /**
149
     * Whether the basedir of the new project should be the same one
150
     * as it would be when running the build file directly -
151
     * independent of dir and/or inheritAll settings.
152
     *
153
     * @param bool $b
154
     */
155
    public function setUseNativeBasedir(bool $b)
156
    {
157
        $this->useNativeBasedir = $b;
158
    }
159
160
    /**
161
     * Creates a Project instance for the project to call.
162
     *
163
     * @return void
164
     */
165 36
    public function init()
166
    {
167 36
        $this->newProject = $this->getProject()->createSubProject();
168 36
        $tdf = $this->project->getTaskDefinitions();
169 36
        $this->newProject->addTaskDefinition("property", $tdf["property"]);
170 36
    }
171
172
    /**
173
     * Called in execute or createProperty if newProject is null.
174
     *
175
     * <p>This can happen if the same instance of this task is run
176
     * twice as newProject is set to null at the end of execute (to
177
     * save memory and help the GC).</p>
178
     *
179
     * <p>Sets all properties that have been defined as nested
180
     * property elements.</p>
181
     */
182 6
    private function reinit()
183
    {
184 6
        $this->init();
185
186 6
        $count = count($this->properties);
187 6
        for ($i = 0; $i < $count; $i++) {
188
            /**
189
             * @var PropertyTask $p
190
             */
191 6
            $p = $this->properties[$i] ?? null;
192 6
            if ($p !== null) {
193
                /** @var PropertyTask $newP */
194 6
                $newP = $this->newProject->createTask("property");
195 6
                $newP->setName($p->getName());
196 6
                if ($p->getValue() !== null) {
197 6
                    $newP->setValue($p->getValue());
198
                }
199 6
                if ($p->getFile() !== null) {
200
                    $newP->setFile($p->getFile());
201
                }
202 6
                if ($p->getPrefix() !== null) {
203
                    $newP->setPrefix($p->getPrefix());
204
                }
205 6
                if ($p->getRefid() !== null) {
206
                    $newP->setRefid($p->getRefid());
207
                }
208 6
                if ($p->getEnvironment() !== null) {
209
                    $newP->setEnvironment($p->getEnvironment());
210
                }
211 6
                if ($p->getUserProperty() !== null) {
212 6
                    $newP->setUserProperty($p->getUserProperty());
213
                }
214 6
                $newP->setOverride($p->getOverride());
215 6
                $newP->setLogoutput($p->getLogoutput());
216 6
                $newP->setQuiet($p->getQuiet());
217
218 6
                $this->properties[$i] = $newP;
219
            }
220
        }
221 6
    }
222
223
    /**
224
     * Main entry point for the task.
225
     *
226
     * @return void
227
     */
228 33
    public function main()
229
    {
230
        // Call Phing on the file set with the attribute "phingfile"
231 33
        if ($this->phingFile !== null || $this->dir !== null) {
232 33
            $this->processFile();
233
        }
234
235
        // if no filesets are given stop here; else process filesets
236 27
        if (!empty($this->filesets)) {
237
            // preserve old settings
238
            $savedDir = $this->dir;
239
            $savedPhingFile = $this->phingFile;
240
            $savedTarget = $this->newTarget;
241
242
            // set no specific target for files in filesets
243
            // [HL] I'm commenting this out; I don't know why this should not be supported!
244
            // $this->newTarget = null;
245
246
            foreach ($this->filesets as $fs) {
247
                $ds = $fs->getDirectoryScanner($this->project);
248
249
                $fromDir = $fs->getDir($this->project);
0 ignored issues
show
Unused Code introduced by
The assignment to $fromDir is dead and can be removed.
Loading history...
250
                $srcFiles = $ds->getIncludedFiles();
251
252
                foreach ($srcFiles as $fname) {
253
                    $f = new File($ds->getbasedir(), $fname);
254
                    $f = $f->getAbsoluteFile();
255
                    $this->phingFile = $f->getAbsolutePath();
256
                    $this->dir = $f->getParentFile();
257
                    $this->processFile(); // run Phing!
258
                }
259
            }
260
261
            // side effect free programming ;-)
262
            $this->dir = $savedDir;
263
            $this->phingFile = $savedPhingFile;
264
            $this->newTarget = $savedTarget;
265
266
            // [HL] change back to correct dir
267
            if ($this->dir !== null) {
268
                chdir($this->dir->getAbsolutePath());
269
            }
270
        }
271
272
        // Remove any dangling references to help the GC
273 27
        foreach ($this->properties as $property) {
274 12
            $property->setFallback(null);
275
        }
276 27
    }
277
278
    /**
279
     * Execute phing file.
280
     *
281
     * @throws BuildException
282
     */
283 33
    private function processFile(): void
284
    {
285 33
        $buildFailed = false;
286 33
        $savedDir = $this->dir;
287 33
        $savedPhingFile = $this->phingFile;
288 33
        $savedTarget = $this->newTarget;
289
290 33
        $savedBasedirAbsPath = null; // this is used to save the basedir *if* we change it
291
292
        try {
293 33
            $this->getNewProject();
294
295 33
            $this->initializeProject();
296
297 33
            if ($this->dir !== null) {
298 12
                if (!$this->useNativeBasedir) {
299 12
                    $this->newProject->setBasedir($this->dir);
300 12
                    if ($savedDir !== null) { // has been set explicitly
301 12
                        $this->newProject->setInheritedProperty('project.basedir', $this->dir->getAbsolutePath());
302
                    }
303
                }
304
            } else {
305
                // Since we're not changing the basedir here (for file resolution),
306
                // we don't need to worry about any side-effects in this scanrio.
307 22
                $this->dir = $this->getProject()->getBasedir();
308
            }
309
310 33
            $this->overrideProperties();
311 33
            $this->phingFile = $this->phingFile ?? 'build.xml';
312
313 33
            $fu = new FileUtils();
314 33
            $file = $fu->resolveFile($this->dir, $this->phingFile);
315 33
            $this->phingFile = $file->getAbsolutePath();
316 33
            $this->log('calling target(s) '
317 33
                . (empty($this->locals) ? '[default]' : implode(', ', $this->locals))
318 33
                . ' in build file ' . $this->phingFile, Project::MSG_VERBOSE);
319
320 33
            $this->newProject->setUserProperty("phing.file", $this->phingFile);
321
322 33
            if (empty($this->locals)) {
323 33
                $defaultTarget = $this->newProject->getDefaultTarget();
324 33
                if (!empty($defaultTarget)) {
325 33
                    $this->locals[] = $defaultTarget;
326
                }
327
            }
328
329 33
            $thisPhingFile = $this->getProject()->getProperty('phing.file');
330
            // Are we trying to call the target in which we are defined (or
331
            // the build file if this is a top level task)?
332
            if (
333 33
                $thisPhingFile !== null
334 33
                && $this->getOwningTarget() !== null
335 33
                && $thisPhingFile === $file->getPath()
336 33
                && $this->getOwningTarget()->getName() === ''
337
            ) {
338
                if ('phingcall' === $this->getTaskName()) {
339
                    throw new BuildException('phingcall must not be used at the top level.');
340
                }
341
                throw new BuildException(
342
                    sprintf(
343
                        '%s task at the top level must not invoke its own build file.',
344
                        $this->getTaskName()
345
                    )
346
                );
347
            }
348
349 33
            ProjectConfigurator::configureProject($this->newProject, new File($this->phingFile));
350
351 30
            if ($this->newTarget === null) {
352 3
                $this->newTarget = $this->newProject->getDefaultTarget();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->newProject->getDefaultTarget() of type string is incompatible with the declared type Phing\Target of property $newTarget.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
353
            }
354
355
            // Are we trying to call the target in which we are defined?
356
            if (
357 30
                $this->newProject->getBasedir()->equals($this->project->getBasedir())
358 30
                && $this->newProject->getProperty('phing.file') === $this->project->getProperty('phing.file')
359 30
                && $this->getOwningTarget() !== null
360
            ) {
361 17
                $owningTargetName = $this->getOwningTarget()->getName();
362 17
                if ($this->newTarget === $owningTargetName) {
363 2
                    throw new BuildException(
364 2
                        sprintf(
365 2
                            "%s task calling its own parent target",
366 2
                            $this->getTaskName()
367
                        )
368
                    );
369
                }
370
371 15
                $targets = $this->getProject()->getTargets();
372 15
                $taskName = $this->getTaskName();
373
374 15
                foreach ($this->locals as $local) {
375 15
                    if (isset($targets[$local])) {
376 7
                        if ($targets[$local]->dependsOn($owningTargetName)) {
377
                            throw new BuildException(
378
                                sprintf(
379
                                    "%s task calling a target that depends on its parent target '%s'.",
380
                                    $taskName,
381
                                    $owningTargetName
382
                                )
383
                            );
384
                        }
385
                    }
386
                }
387
            }
388
389 28
            $this->addReferences();
390 28
            $this->newProject->executeTarget($this->newTarget);
391 7
        } catch (Exception $e) {
392 7
            $buildFailed = true;
393 7
            $this->log($e->getMessage(), Project::MSG_ERR);
394 7
            if (Phing::getMsgOutputLevel() <= Project::MSG_DEBUG) {
395 7
                $lines = explode("\n", $e->getTraceAsString());
396 7
                foreach ($lines as $line) {
397 7
                    $this->log($line, Project::MSG_DEBUG);
398
                }
399
            }
400 27
        } finally {
401
            // reset environment values to prevent side-effects.
402
403 33
            $this->newProject = null;
404 33
            $pkeys = array_keys($this->properties);
405 33
            foreach ($pkeys as $k) {
406 12
                $this->properties[$k]->setProject(null);
407
            }
408
409 33
            if ($this->output !== null && $this->out !== null) {
410 1
                $this->out->close();
411
            }
412
413 33
            $this->dir = $savedDir;
414 33
            $this->phingFile = $savedPhingFile;
415 33
            $this->newTarget = $savedTarget;
416
417
            // If the basedir for any project was changed, we need to set that back here.
418 33
            if ($savedBasedirAbsPath !== null) {
0 ignored issues
show
introduced by
The condition $savedBasedirAbsPath !== null is always false.
Loading history...
419
                chdir($savedBasedirAbsPath);
420
            }
421
422 33
            if ($this->haltOnFailure && $buildFailed) {
423 33
                throw new BuildException('Execution of the target buildfile failed. Aborting.');
424
            }
425
        }
426 27
    }
427
428
    /**
429
     * Get the (sub)-Project instance currently in use.
430
     *
431
     * @return Project
432
     */
433 33
    protected function getNewProject(): Project
434
    {
435 33
        if ($this->newProject === null) {
436 6
            $this->reinit();
437
        }
438 33
        return $this->newProject;
439
    }
440
441
    /**
442
     * Configure the Project, i.e. make intance, attach build listeners
443
     * (copy from father project), add Task and Datatype definitions,
444
     * copy properties and references from old project if these options
445
     * are set via the attributes of the XML tag.
446
     *
447
     * Developer note:
448
     * This function replaces the old methods "init", "_reinit" and
449
     * "_initializeProject".
450
     */
451 33
    private function initializeProject()
452
    {
453 33
        $this->newProject->setInputHandler($this->project->getInputHandler());
454
455 33
        foreach ($this->project->getBuildListeners() as $listener) {
456 33
            $this->newProject->addBuildListener($listener);
457
        }
458
459
        /* Copy things from old project. Datatypes and Tasks are always
460
         * copied, properties and references only if specified so/not
461
         * specified otherwise in the XML definition.
462
         */
463
        // Add Datatype definitions
464 33
        foreach ($this->project->getDataTypeDefinitions() as $typeName => $typeClass) {
465 33
            $this->newProject->addDataTypeDefinition($typeName, $typeClass);
466
        }
467
468
        // Add Task definitions
469 33
        foreach ($this->project->getTaskDefinitions() as $taskName => $taskClass) {
470 33
            if ($taskClass === 'phing.tasks.system.PropertyTask') {
471
                // we have already added this taskdef in init()
472
                continue;
473
            }
474 33
            $this->newProject->addTaskDefinition($taskName, $taskClass);
475
        }
476
477 33
        if ($this->output !== null) {
478
            try {
479 1
                if ($this->dir !== null) {
480 1
                    $outfile = (new FileUtils())->resolveFile($this->dir, $this->output);
481
                } else {
482 1
                    $outfile = $this->getProject()->resolveFile($this->output);
483
                }
484 1
                $this->out = new FileOutputStream($outfile);
485 1
                $logger = new DefaultLogger();
486 1
                $logger->setMessageOutputLevel(Project::MSG_INFO);
487 1
                $logger->setOutputStream($this->out);
488 1
                $logger->setErrorStream($this->out);
489 1
                $this->newProject->addBuildListener($logger);
490
            } catch (Exception $ex) {
491
                $this->log("Phing: Can't set output to " . $this->output);
492
            }
493
        }
494
495 33
        if ($this->useNativeBasedir) {
496
            $this->addAlmostAll($this->getProject()->getUserProperties(), 'user');
497
        } else {
498 33
            $this->project->copyUserProperties($this->newProject);
499
        }
500
501 33
        if (!$this->inheritAll) {
502
            // set System built-in properties separately,
503
            // b/c we won't inherit them.
504 13
            $this->newProject->setSystemProperties();
505
        } else {
506 21
            $this->addAlmostAll($this->getProject()->getProperties(), 'plain');
507
        }
508 33
    }
509
510
    /**
511
     * Copies all properties from the given table to the new project -
512
     * omitting those that have already been set in the new project as
513
     * well as properties named basedir or phing.file.
514
     * @param array $props properties <code>Hashtable</code> to copy to the
515
     * new project.
516
     * @param string $type the type of property to set (a plain Phing property, a
517
     * user property or an inherited property).
518
     */
519 21
    private function addAlmostAll(array $props, string $type): void
520
    {
521 21
        foreach ($props as $name => $value) {
522 21
            if ($name === 'basedir' || $name === 'phing.file' || $name === 'phing.version') {
523
                // basedir and phing.file get special treatment in main()
524 21
                continue;
525
            }
526 21
            if ($type === 'plain') {
527
                // don't re-set user properties, avoid the warning message
528 21
                if ($this->newProject->getProperty($name) === null) {
529
                    // no user property
530 21
                    $this->newProject->setNewProperty($name, $value);
531
                }
532
            } elseif ($type === 'user') {
533
                $this->newProject->setUserProperty($name, $value);
534
            } elseif ($type === 'inherited') {
535
                $this->newProject->setInheritedProperty($name, $value);
536
            }
537
        }
538 21
    }
539
540
    /**
541
     * Override the properties in the new project with the one
542
     * explicitly defined as nested elements here.
543
     *
544
     * @return void
545
     * @throws BuildException
546
     */
547 33
    private function overrideProperties()
548
    {
549
        // remove duplicate properties - last property wins
550 33
        $properties = array_reverse($this->properties);
551 33
        $set = [];
552 33
        foreach ($properties as $i => $p) {
553 12
            if ($p->getName() !== null && $p->getName() !== '') {
554 12
                if (in_array($p->getName(), $set)) {
555 7
                    unset($this->properties[$i]);
556
                } else {
557 12
                    $set[] = $p->getName();
558
                }
559
            }
560 12
            $p->setProject($this->newProject);
561 12
            $p->main();
562
        }
563 33
        if ($this->useNativeBasedir) {
564
            $this->addAlmostAll($this->getProject()->getInheritedProperties(), 'inherited');
565
        } else {
566 33
            $this->project->copyInheritedProperties($this->newProject);
567
        }
568 33
    }
569
570
    /**
571
     * Add the references explicitly defined as nested elements to the
572
     * new project.  Also copy over all references that don't override
573
     * existing references in the new project if inheritrefs has been
574
     * requested.
575
     *
576
     * @return void
577
     * @throws BuildException
578
     */
579 28
    private function addReferences()
580
    {
581
582
        // parent project references
583 28
        $projReferences = $this->project->getReferences();
584
585 28
        $newReferences = $this->newProject->getReferences();
586
587 28
        $subprojRefKeys = [];
588
589 28
        if (count($this->references) > 0) {
590
            for ($i = 0, $count = count($this->references); $i < $count; $i++) {
591
                /** @var Reference $ref */
592
                $ref = $this->references[$i];
593
                $refid = $ref->getRefId();
594
595
                if ($refid === null) {
596
                    throw new BuildException('the refid attribute is required for reference elements');
597
                }
598
                if (!isset($projReferences[$refid])) {
599
                    $this->log("Parent project doesn't contain any reference '" . $refid . "'", Project::MSG_WARN);
600
                    continue;
601
                }
602
603
                $subprojRefKeys[] = $refid;
604
                unset($this->references[$i]);//thisReferences.remove(refid);
605
                $toRefid = $ref->getToRefid();
0 ignored issues
show
Bug introduced by
The method getToRefid() does not exist on Phing\Type\Reference. Did you maybe mean getRefId()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

605
                /** @scrutinizer ignore-call */ 
606
                $toRefid = $ref->getToRefid();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
606
                if ($toRefid === null) {
607
                    $toRefid = $refid;
608
                }
609
                $this->copyReference($refid, $toRefid);
610
            }
611
        }
612
613
        // Now add all references that are not defined in the
614
        // subproject, if inheritRefs is true
615 28
        if ($this->inheritRefs) {
616
            // get the keys that are were not used by the subproject
617 2
            $unusedRefKeys = array_diff(array_keys($projReferences), $subprojRefKeys);
618
619 2
            foreach ($unusedRefKeys as $key) {
620 2
                if (isset($newReferences[$key])) {
621 2
                    continue;
622
                }
623 2
                $this->copyReference($key, $key);
624
            }
625
        }
626 28
    }
627
628
    /**
629
     * Try to clone and reconfigure the object referenced by oldkey in
630
     * the parent project and add it to the new project with the key
631
     * newkey.
632
     *
633
     * <p>If we cannot clone it, copy the referenced object itself and
634
     * keep our fingers crossed.</p>
635
     *
636
     * @param  string $oldKey
637
     * @param  string $newKey
638
     * @throws BuildException
639
     * @return void
640
     */
641 2
    private function copyReference($oldKey, $newKey)
642
    {
643 2
        $orig = $this->project->getReference($oldKey);
644 2
        if ($orig === null) {
645
            $this->log(
646
                "No object referenced by " . $oldKey . ". Can't copy to "
647
                . $newKey,
648
                Project::MSG_WARN
649
            );
650
651
            return;
652
        }
653
654 2
        $copy = clone $orig;
655
656 2
        if ($copy instanceof ProjectComponent) {
657 2
            $copy->setProject($this->newProject);
658 2
        } elseif (in_array('setProject', get_class_methods(get_class($copy)))) {
659
            $copy->setProject($this->newProject);
660 2
        } elseif (!($copy instanceof Project)) {
661
            // don't copy the old "Project" itself
662
            $msg = "Error setting new project instance for "
663
                . "reference with id " . $oldKey;
664
            throw new BuildException($msg);
665
        }
666
667 2
        $this->newProject->addReference($newKey, $copy);
668 2
    }
669
670
    /**
671
     * If true, pass all properties to the new phing project.
672
     * Defaults to true.
673
     *
674
     * @param $value
675
     */
676 20
    public function setInheritAll($value)
677
    {
678 20
        $this->inheritAll = (bool) $value;
679 20
    }
680
681
    /**
682
     * If true, pass all references to the new phing project.
683
     * Defaults to false.
684
     *
685
     * @param $value
686
     */
687 12
    public function setInheritRefs($value)
688
    {
689 12
        $this->inheritRefs = (bool) $value;
690 12
    }
691
692
    /**
693
     * The directory to use as a base directory for the new phing project.
694
     * Defaults to the current project's basedir, unless inheritall
695
     * has been set to false, in which case it doesn't have a default
696
     * value. This will override the basedir setting of the called project.
697
     *
698
     * @param File $d
699
     */
700 12
    public function setDir(File $d): void
701
    {
702 12
        $this->dir = $d;
703 12
    }
704
705
    /**
706
     * The build file to use.
707
     * Defaults to "build.xml". This file is expected to be a filename relative
708
     * to the dir attribute given.
709
     *
710
     * @param $s
711
     */
712 33
    public function setPhingFile($s)
713
    {
714
        // it is a string and not a file to handle relative/absolute
715
        // otherwise a relative file will be resolved based on the current
716
        // basedir.
717 33
        $this->phingFile = $s;
718 33
    }
719
720
    /**
721
     * Alias function for setPhingfile
722
     *
723
     * @param $s
724
     */
725 8
    public function setBuildfile($s)
726
    {
727 8
        $this->setPhingFile($s);
728 8
    }
729
730
    /**
731
     * The target of the new Phing project to execute.
732
     * Defaults to the new project's default target.
733
     *
734
     * @param string $s
735
     */
736 32
    public function setTarget(string $s)
737
    {
738 32
        if ('' === $s) {
739 1
            throw new BuildException("target attribute must not be empty");
740
        }
741
742 31
        $this->newTarget = $s;
0 ignored issues
show
Documentation Bug introduced by
It seems like $s of type string is incompatible with the declared type Phing\Target of property $newTarget.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
743 31
    }
744
745
    /**
746
     * Set the filename to write the output to. This is relative to the value
747
     * of the dir attribute if it has been set or to the base directory of the
748
     * current project otherwise.
749
     * @param string $outputFile the name of the file to which the output should go.
750
     */
751 1
    public function setOutput(string $outputFile): void
752
    {
753 1
        $this->output = $outputFile;
754 1
    }
755
756
    /**
757
     * Property to pass to the new project.
758
     * The property is passed as a 'user property'
759
     */
760 12
    public function createProperty()
761
    {
762 12
        $p = new PropertyTask();
763 12
        $p->setFallback($this->getNewProject());
764 12
        $p->setUserProperty(true);
765 12
        $p->setTaskName('property');
766 12
        $this->properties[] = $p;
767
768 12
        return $p;
769
    }
770
771
    /**
772
     * Reference element identifying a data type to carry
773
     * over to the new project.
774
     *
775
     * @param PhingReference $ref
776
     */
777 1
    public function addReference(PhingReference $ref)
778
    {
779 1
        $this->references[] = $ref;
780 1
    }
781
}
782