Test Failed
Push — dependabot/composer/phpmd/phpm... ( f954cb )
by
unknown
39:24 queued 13:57
created
src/Phing/Task/System/XmlLintTask.php 1 patch
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -216,7 +216,7 @@
 block discarded – undo
216 216
         }
217 217
         $return .= trim($error->message);
218 218
         if ($error->file) {
219
-            $return .=    " in $error->file";
219
+            $return .= " in $error->file";
220 220
         }
221 221
         $return .= " on line $error->line";
222 222
 
Please login to merge, or discard this patch.
src/Phing/Phing.php 5 patches
Indentation   -1616 removed lines patch added patch discarded remove patch
@@ -83,1619 +83,3 @@
 block discarded – undo
83 83
      */
84 84
     public const DEFAULT_BUILD_FILENAME = 'build.xml';
85 85
     public const DEFAULT_BUILD_CONTENT = <<<'XML'
86
-        <?xml version="1.0" encoding="UTF-8" ?>
87
-
88
-        <project name="" description="" default="">
89
-            
90
-            <target name="" description="">
91
-                
92
-            </target>
93
-            
94
-        </project>
95
-        XML;
96
-    public const PHING_HOME = 'phing.home';
97
-    public const PHP_VERSION = 'php.version';
98
-    public const PHP_INTERPRETER = 'php.interpreter';
99
-
100
-    /**
101
-     * Our current message output status. Follows Project::MSG_XXX.
102
-     */
103
-    private static $msgOutputLevel = Project::MSG_INFO;
104
-    /**
105
-     * Set of properties that are passed in from commandline or invoking code.
106
-     *
107
-     * @var Properties
108
-     */
109
-    private static $definedProps;
110
-    /**
111
-     * Used by utility function getResourcePath().
112
-     */
113
-    private static $importPaths;
114
-    /**
115
-     * System-wide static properties (moved from System).
116
-     */
117
-    private static $properties = [];
118
-    /**
119
-     * Static system timer.
120
-     */
121
-    private static $timer;
122
-    /**
123
-     * The current Project.
124
-     */
125
-    private static $currentProject;
126
-    /**
127
-     * Whether to capture PHP errors to buffer.
128
-     */
129
-    private static $phpErrorCapture = false;
130
-    /**
131
-     * Array of captured PHP errors.
132
-     */
133
-    private static $capturedPhpErrors = [];
134
-    /**
135
-     * @var OUtputStream stream for standard output
136
-     */
137
-    private static $out;
138
-    /**
139
-     * @var OutputStream stream for error output
140
-     */
141
-    private static $err;
142
-    /**
143
-     * @var bool whether we are using a logfile
144
-     */
145
-    private static $isLogFileUsed = false;
146
-    /**
147
-     * Array to hold original ini settings that Phing changes (and needs
148
-     * to restore in restoreIni() method).
149
-     *
150
-     * @var array Struct of array(setting-name => setting-value)
151
-     *
152
-     * @see restoreIni()
153
-     */
154
-    private static $origIniSettings = [];
155
-    /**
156
-     * PhingFile that we are using for configuration.
157
-     */
158
-    private $buildFile;
159
-    /**
160
-     * The build targets.
161
-     */
162
-    private $targets = [];
163
-    /**
164
-     * Names of classes to add as listeners to project.
165
-     */
166
-    private $listeners = [];
167
-    /**
168
-     * keep going mode.
169
-     *
170
-     * @var bool
171
-     */
172
-    private $keepGoingMode = false;
173
-    private $loggerClassname;
174
-    /**
175
-     * The class to handle input (can be only one).
176
-     */
177
-    private $inputHandlerClassname;
178
-    /**
179
-     * Whether or not log output should be reduced to the minimum.
180
-     *
181
-     * @var bool
182
-     */
183
-    private $silent = false;
184
-    /**
185
-     * Indicates whether phing should run in strict mode.
186
-     */
187
-    private $strictMode = false;
188
-    /**
189
-     * Indicates if this phing should be run.
190
-     */
191
-    private $readyToRun = false;
192
-    /**
193
-     * Indicates we should only parse and display the project help information.
194
-     */
195
-    private $projectHelp = false;
196
-    /**
197
-     * Whether to values in a property file should override existing values.
198
-     */
199
-    private $propertyFileOverride = false;
200
-    /**
201
-     * Whether or not output to the log is to be unadorned.
202
-     */
203
-    private $emacsMode = false;
204
-
205
-    /**
206
-     * @var string
207
-     */
208
-    private $searchForThis;
209
-    private $propertyFiles = [];
210
-
211
-    /**
212
-     * Gets the stream to use for standard (non-error) output.
213
-     *
214
-     * @return OutputStream
215
-     */
216
-    public static function getOutputStream()
217
-    {
218
-        return self::$out;
219
-    }
220
-
221
-    /**
222
-     * Gets the stream to use for error output.
223
-     *
224
-     * @return OutputStream
225
-     */
226
-    public static function getErrorStream()
227
-    {
228
-        return self::$err;
229
-    }
230
-
231
-    /**
232
-     * Command line entry point. This method kicks off the building
233
-     * of a project object and executes a build using either a given
234
-     * target or the default target.
235
-     *
236
-     * @param array $args command line args
237
-     * @throws Exception
238
-     */
239
-    public static function fire($args): void
240
-    {
241
-        self::start($args);
242
-    }
243
-
244
-    /**
245
-     * Entry point allowing for more options from other front ends.
246
-     *
247
-     * This method encapsulates the complete build lifecycle.
248
-     *
249
-     * @param array $args the commandline args passed to phing shell script
250
-     * @param array $additionalUserProperties Any additional properties to be passed to Phing (alternative front-end might implement this).
251
-     *                                        These additional properties will be available using the getDefinedProperty() method and will
252
-     *                                        be added to the project's "user" properties
253
-     *
254
-     * @throws Exception - if there is an error during build
255
-     * @see    runBuild()
256
-     *
257
-     * @see    execute()
258
-     */
259
-    public static function start($args, array $additionalUserProperties = null)
260
-    {
261
-        try {
262
-            $m = new self();
263
-            $m->execute($args);
264
-        } catch (Exception $exc) {
265
-            self::handleLogfile();
266
-            self::printMessage($exc);
267
-            self::statusExit(1);
268
-
269
-            return;
270
-        }
271
-
272
-        if (null !== $additionalUserProperties) {
273
-            foreach ($additionalUserProperties as $key => $value) {
274
-                $m::setDefinedProperty($key, $value);
275
-            }
276
-        }
277
-
278
-        // expect the worst
279
-        $exitCode = 1;
280
-
281
-        try {
282
-            try {
283
-                $m->runBuild();
284
-                $exitCode = 0;
285
-            } catch (ExitStatusException $ese) {
286
-                $exitCode = $ese->getCode();
287
-                if (0 !== $exitCode) {
288
-                    self::handleLogfile();
289
-
290
-                    throw $ese;
291
-                }
292
-            }
293
-        } catch (BuildException $exc) {
294
-            // avoid printing output twice: self::printMessage($exc);
295
-        } catch (Throwable $exc) {
296
-            self::printMessage($exc);
297
-        } finally {
298
-            self::handleLogfile();
299
-        }
300
-        self::statusExit($exitCode);
301
-    }
302
-
303
-    /**
304
-     * Setup/initialize Phing environment from commandline args.
305
-     *
306
-     * @param array $args commandline args passed to phing shell
307
-     *
308
-     * @throws ConfigurationException
309
-     */
310
-    public function execute($args): void
311
-    {
312
-        self::$definedProps = new Properties();
313
-        $this->searchForThis = null;
314
-
315
-        // 1) First handle any options which should always
316
-        // Note: The order in which these are executed is important (if multiple of these options are specified)
317
-
318
-        if (in_array('-help', $args) || in_array('-h', $args)) {
319
-            static::printUsage();
320
-
321
-            return;
322
-        }
323
-
324
-        if (in_array('-version', $args) || in_array('-v', $args)) {
325
-            static::printVersion();
326
-
327
-            return;
328
-        }
329
-
330
-        if (in_array('-init', $args) || in_array('-i', $args)) {
331
-            $key = array_search('-init', $args) ?: array_search('-i', $args);
332
-            $path = $args[$key + 1] ?? null;
333
-
334
-            self::init($path);
335
-
336
-            return;
337
-        }
338
-
339
-        if (in_array('-diagnostics', $args)) {
340
-            Diagnostics::doReport(new PrintStream(self::$out));
341
-
342
-            return;
343
-        }
344
-
345
-        // 2) Next pull out stand-alone args.
346
-        // Note: The order in which these are executed is important (if multiple of these options are specified)
347
-
348
-        if (
349
-            false !== ($key = array_search('-quiet', $args, true))
350
-            || false !== ($key = array_search(
351
-                '-q',
352
-                $args,
353
-                true
354
-            ))
355
-        ) {
356
-            self::$msgOutputLevel = Project::MSG_WARN;
357
-            unset($args[$key]);
358
-        }
359
-
360
-        if (
361
-            false !== ($key = array_search('-emacs', $args, true))
362
-            || false !== ($key = array_search('-e', $args, true))
363
-        ) {
364
-            $this->emacsMode = true;
365
-            unset($args[$key]);
366
-        }
367
-
368
-        if (false !== ($key = array_search('-verbose', $args, true))) {
369
-            self::$msgOutputLevel = Project::MSG_VERBOSE;
370
-            unset($args[$key]);
371
-        }
372
-
373
-        if (false !== ($key = array_search('-debug', $args, true))) {
374
-            self::$msgOutputLevel = Project::MSG_DEBUG;
375
-            unset($args[$key]);
376
-        }
377
-
378
-        if (
379
-            false !== ($key = array_search('-silent', $args, true))
380
-            || false !== ($key = array_search('-S', $args, true))
381
-        ) {
382
-            $this->silent = true;
383
-            unset($args[$key]);
384
-        }
385
-
386
-        if (false !== ($key = array_search('-propertyfileoverride', $args, true))) {
387
-            $this->propertyFileOverride = true;
388
-            unset($args[$key]);
389
-        }
390
-
391
-        // 3) Finally, cycle through to parse remaining args
392
-        //
393
-        $keys = array_keys($args); // Use keys and iterate to max(keys) since there may be some gaps
394
-        $max = $keys ? max($keys) : -1;
395
-        for ($i = 0; $i <= $max; ++$i) {
396
-            if (!array_key_exists($i, $args)) {
397
-                // skip this argument, since it must have been removed above.
398
-                continue;
399
-            }
400
-
401
-            $arg = $args[$i];
402
-
403
-            if ('-logfile' == $arg) {
404
-                try {
405
-                    // see: http://phing.info/trac/ticket/65
406
-                    if (!isset($args[$i + 1])) {
407
-                        $msg = "You must specify a log file when using the -logfile argument\n";
408
-
409
-                        throw new ConfigurationException($msg);
410
-                    }
411
-
412
-                    $logFile = new File($args[++$i]);
413
-                    $out = new FileOutputStream($logFile); // overwrite
414
-                    self::setOutputStream($out);
415
-                    self::setErrorStream($out);
416
-                    self::$isLogFileUsed = true;
417
-                } catch (IOException $ioe) {
418
-                    $msg = 'Cannot write on the specified log file. Make sure the path exists and you have write permissions.';
419
-
420
-                    throw new ConfigurationException($msg, $ioe);
421
-                }
422
-            } elseif ('-buildfile' == $arg || '-file' == $arg || '-f' == $arg) {
423
-                if (!isset($args[$i + 1])) {
424
-                    $msg = 'You must specify a buildfile when using the -buildfile argument.';
425
-
426
-                    throw new ConfigurationException($msg);
427
-                }
428
-
429
-                $this->buildFile = new File($args[++$i]);
430
-            } elseif ('-listener' == $arg) {
431
-                if (!isset($args[$i + 1])) {
432
-                    $msg = 'You must specify a listener class when using the -listener argument';
433
-
434
-                    throw new ConfigurationException($msg);
435
-                }
436
-
437
-                $this->listeners[] = $args[++$i];
438
-            } elseif (StringHelper::startsWith('-D', $arg)) {
439
-                // Evaluating the property information //
440
-                // Checking whether arg. is not just a switch, and next arg. does not starts with switch identifier
441
-                if (('-D' == $arg) && (!StringHelper::startsWith('-', $args[$i + 1]))) {
442
-                    $name = $args[++$i];
443
-                } else {
444
-                    $name = substr($arg, 2);
445
-                }
446
-
447
-                $value = null;
448
-                $posEq = strpos($name, '=');
449
-                if (false !== $posEq) {
450
-                    $value = substr($name, $posEq + 1);
451
-                    $name = substr($name, 0, $posEq);
452
-                } elseif ($i < count($args) - 1 && !StringHelper::startsWith('-D', $args[$i + 1])) {
453
-                    $value = $args[++$i];
454
-                }
455
-                self::$definedProps->setProperty($name, $value);
456
-            } elseif ('-logger' == $arg) {
457
-                if (!isset($args[$i + 1])) {
458
-                    $msg = 'You must specify a classname when using the -logger argument';
459
-
460
-                    throw new ConfigurationException($msg);
461
-                }
462
-
463
-                $this->loggerClassname = $args[++$i];
464
-            } elseif ('-no-strict' == $arg) {
465
-                $this->strictMode = false;
466
-            } elseif ('-strict' == $arg) {
467
-                $this->strictMode = true;
468
-            } elseif ('-inputhandler' == $arg) {
469
-                if (null !== $this->inputHandlerClassname) {
470
-                    throw new ConfigurationException('Only one input handler class may be specified.');
471
-                }
472
-                if (!isset($args[$i + 1])) {
473
-                    $msg = 'You must specify a classname when using the -inputhandler argument';
474
-
475
-                    throw new ConfigurationException($msg);
476
-                }
477
-
478
-                $this->inputHandlerClassname = $args[++$i];
479
-            } elseif ('-propertyfile' === $arg) {
480
-                $i = $this->handleArgPropertyFile($args, $i);
481
-            } elseif ('-keep-going' === $arg || '-k' === $arg) {
482
-                $this->keepGoingMode = true;
483
-            } elseif ('-longtargets' == $arg) {
484
-                self::$definedProps->setProperty('phing.showlongtargets', 1);
485
-            } elseif ('-projecthelp' == $arg || '-targets' == $arg || '-list' == $arg || '-l' == $arg || '-p' == $arg) {
486
-                // set the flag to display the targets and quit
487
-                $this->projectHelp = true;
488
-            } elseif ('-find' == $arg) {
489
-                // eat up next arg if present, default to build.xml
490
-                if ($i < count($args) - 1) {
491
-                    $this->searchForThis = $args[++$i];
492
-                } else {
493
-                    $this->searchForThis = self::DEFAULT_BUILD_FILENAME;
494
-                }
495
-            } elseif ('-' == substr($arg, 0, 1)) {
496
-                // we don't have any more args
497
-                self::printUsage();
498
-                self::$err->write(PHP_EOL);
499
-
500
-                throw new ConfigurationException('Unknown argument: ' . $arg);
501
-            } else {
502
-                // if it's no other arg, it may be the target
503
-                $this->targets[] = $arg;
504
-            }
505
-        }
506
-
507
-        // if buildFile was not specified on the command line,
508
-        if (null === $this->buildFile) {
509
-            // but -find then search for it
510
-            if (null !== $this->searchForThis) {
511
-                $this->buildFile = $this->findBuildFile(self::getProperty('user.dir'), $this->searchForThis);
512
-            } else {
513
-                $this->buildFile = new File(self::DEFAULT_BUILD_FILENAME);
514
-            }
515
-        }
516
-
517
-        try {
518
-            // make sure buildfile (or buildfile.dist) exists
519
-            if (!$this->buildFile->exists()) {
520
-                $distFile = new File($this->buildFile->getAbsolutePath() . '.dist');
521
-                if (!$distFile->exists()) {
522
-                    throw new ConfigurationException(
523
-                        'Buildfile: ' . $this->buildFile->__toString() . ' does not exist!'
524
-                    );
525
-                }
526
-                $this->buildFile = $distFile;
527
-            }
528
-
529
-            // make sure it's not a directory
530
-            if ($this->buildFile->isDirectory()) {
531
-                throw new ConfigurationException('Buildfile: ' . $this->buildFile->__toString() . ' is a dir!');
532
-            }
533
-        } catch (IOException $e) {
534
-            // something else happened, buildfile probably not readable
535
-            throw new ConfigurationException('Buildfile: ' . $this->buildFile->__toString() . ' is not readable!');
536
-        }
537
-
538
-        $this->loadPropertyFiles();
539
-
540
-        $this->readyToRun = true;
541
-    }
542
-
543
-    /**
544
-     * Prints the usage of how to use this class.
545
-     */
546
-    public static function printUsage()
547
-    {
548
-        $msg = '';
549
-        $msg .= 'phing [options] [target [target2 [target3] ...]]' . PHP_EOL;
550
-        $msg .= 'Options: ' . PHP_EOL;
551
-        $msg .= '  -h -help               print this message' . PHP_EOL;
552
-        $msg .= '  -l -list               list available targets in this project' . PHP_EOL;
553
-        $msg .= '  -i -init [file]        generates an initial buildfile' . PHP_EOL;
554
-        $msg .= '  -v -version            print the version information and exit' . PHP_EOL;
555
-        $msg .= '  -q -quiet              be extra quiet' . PHP_EOL;
556
-        $msg .= '  -S -silent             print nothing but task outputs and build failures' . PHP_EOL;
557
-        $msg .= '  -verbose               be extra verbose' . PHP_EOL;
558
-        $msg .= '  -debug                 print debugging information' . PHP_EOL;
559
-        $msg .= '  -emacs, -e             produce logging information without adornments' . PHP_EOL;
560
-        $msg .= '  -diagnostics           print diagnostics information' . PHP_EOL;
561
-        $msg .= '  -strict                runs build in strict mode, considering a warning as error' . PHP_EOL;
562
-        $msg .= '  -no-strict             runs build normally (overrides buildfile attribute)' . PHP_EOL;
563
-        $msg .= '  -longtargets           show target descriptions during build' . PHP_EOL;
564
-        $msg .= '  -logfile <file>        use given file for log' . PHP_EOL;
565
-        $msg .= '  -logger <classname>    the class which is to perform logging' . PHP_EOL;
566
-        $msg .= '  -listener <classname>  add an instance of class as a project listener' . PHP_EOL;
567
-        $msg .= '  -f -buildfile <file>   use given buildfile' . PHP_EOL;
568
-        $msg .= '  -D<property>=<value>   use value for given property' . PHP_EOL;
569
-        $msg .= '  -keep-going, -k        execute all targets that do not depend' . PHP_EOL;
570
-        $msg .= '                         on failed target(s)' . PHP_EOL;
571
-        $msg .= '  -propertyfile <file>   load all properties from file' . PHP_EOL;
572
-        $msg .= '  -propertyfileoverride  values in property file override existing values' . PHP_EOL;
573
-        $msg .= '  -find <file>           search for buildfile towards the root of the' . PHP_EOL;
574
-        $msg .= '                         filesystem and use it' . PHP_EOL;
575
-        $msg .= '  -inputhandler <file>   the class to use to handle user input' . PHP_EOL;
576
-        //$msg .= "  -recursive <file>      search for buildfile downwards and use it" . PHP_EOL;
577
-        $msg .= PHP_EOL;
578
-        $msg .= 'Report bugs to https://github.com/phingofficial/phing/issues' . PHP_EOL;
579
-        self::$err->write($msg);
580
-    }
581
-
582
-    /**
583
-     * Prints the current Phing version.
584
-     */
585
-    public static function printVersion()
586
-    {
587
-        self::$out->write(self::getPhingVersion() . PHP_EOL);
588
-    }
589
-
590
-    /**
591
-     * Gets the current Phing version based on VERSION.TXT file.
592
-     *
593
-     * @return string
594
-     * @throws ConfigurationException
595
-     *
596
-     */
597
-    public static function getPhingVersion(): string
598
-    {
599
-        $versionPath = self::getResourcePath('phing/etc/VERSION.TXT');
600
-        if (null === $versionPath) {
601
-            $versionPath = self::getResourcePath('etc/VERSION.TXT');
602
-        }
603
-        if (null === $versionPath) {
604
-            throw new ConfigurationException('No VERSION.TXT file found; try setting phing.home environment variable.');
605
-        }
606
-
607
-        try { // try to read file
608
-            $file = new File($versionPath);
609
-            $reader = new FileReader($file);
610
-            $phingVersion = trim($reader->read());
611
-        } catch (IOException $iox) {
612
-            throw new ConfigurationException("Can't read version information file");
613
-        }
614
-
615
-        $basePath = dirname(__DIR__, 2);
616
-
617
-        $version = new Version($phingVersion, $basePath);
618
-
619
-        return 'Phing ' . $version->getVersion();
620
-    }
621
-
622
-    /**
623
-     * Looks on include path for specified file.
624
-     *
625
-     * @param string $path
626
-     *
627
-     * @return string|null file found (null if no file found)
628
-     */
629
-    public static function getResourcePath($path): ?string
630
-    {
631
-        if (null === self::$importPaths) {
632
-            self::$importPaths = self::explodeIncludePath();
633
-        }
634
-
635
-        $path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $path);
636
-
637
-        foreach (self::$importPaths as $prefix) {
638
-            $testPath = $prefix . DIRECTORY_SEPARATOR . $path;
639
-            if (file_exists($testPath)) {
640
-                return $testPath;
641
-            }
642
-        }
643
-
644
-        // Check for the property phing.home
645
-        $homeDir = self::getProperty(self::PHING_HOME);
646
-        if ($homeDir) {
647
-            $testPath = $homeDir . DIRECTORY_SEPARATOR . $path;
648
-            if (file_exists($testPath)) {
649
-                return $testPath;
650
-            }
651
-        }
652
-
653
-        // Check for the phing home of phar archive
654
-        if (0 === strpos(self::$importPaths[0], 'phar://')) {
655
-            $testPath = self::$importPaths[0] . '/../' . $path;
656
-            if (file_exists($testPath)) {
657
-                return $testPath;
658
-            }
659
-        }
660
-
661
-        // Do one additional check based on path of current file (Phing.php)
662
-        $maybeHomeDir = realpath(__DIR__ . DIRECTORY_SEPARATOR);
663
-        $testPath = $maybeHomeDir . DIRECTORY_SEPARATOR . $path;
664
-        if (file_exists($testPath)) {
665
-            return $testPath;
666
-        }
667
-
668
-        return null;
669
-    }
670
-
671
-    /**
672
-     * Explode an include path into an array.
673
-     *
674
-     * If no path provided, uses current include_path. Works around issues that
675
-     * occur when the path includes stream schemas.
676
-     *
677
-     * Pulled from Zend_Loader::explodeIncludePath() in ZF1.
678
-     *
679
-     * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
680
-     * @license   http://framework.zend.com/license/new-bsd New BSD License
681
-     *
682
-     * @param null|string $path
683
-     *
684
-     * @return array
685
-     */
686
-    public static function explodeIncludePath($path = null)
687
-    {
688
-        if (null === $path) {
689
-            $path = get_include_path();
690
-        }
691
-
692
-        if (PATH_SEPARATOR === ':') {
693
-            // On *nix systems, include_paths which include paths with a stream
694
-            // schema cannot be safely explode'd, so we have to be a bit more
695
-            // intelligent in the approach.
696
-            $paths = preg_split('#:(?!//)#', $path);
697
-        } else {
698
-            $paths = explode(PATH_SEPARATOR, $path);
699
-        }
700
-
701
-        return $paths;
702
-    }
703
-
704
-    /**
705
-     * Returns property value for a System property.
706
-     * System properties are "global" properties like application.startdir,
707
-     * and user.dir.  Many of these correspond to similar properties in Java
708
-     * or Ant.
709
-     *
710
-     * @param string $propName
711
-     *
712
-     * @return string value of found property (or null, if none found)
713
-     */
714
-    public static function getProperty($propName)
715
-    {
716
-        // some properties are detemined on each access
717
-        // some are cached, see below
718
-
719
-        // default is the cached value:
720
-        $val = self::$properties[$propName] ?? null;
721
-
722
-        // special exceptions
723
-        switch ($propName) {
724
-            case 'user.dir':
725
-                $val = getcwd();
726
-
727
-                break;
728
-        }
729
-
730
-        return $val;
731
-    }
732
-
733
-    /**
734
-     * Creates generic buildfile.
735
-     *
736
-     * @param string $path
737
-     */
738
-    public static function init($path)
739
-    {
740
-        if ($buildfilePath = self::initPath($path)) {
741
-            self::initWrite($buildfilePath);
742
-        }
743
-    }
744
-
745
-    /**
746
-     * Returns buildfile's path.
747
-     *
748
-     * @param $path
749
-     *
750
-     * @return string
751
-     * @throws ConfigurationException
752
-     *
753
-     */
754
-    protected static function initPath($path)
755
-    {
756
-        // Fallback
757
-        if (empty($path)) {
758
-            $defaultDir = self::getProperty('application.startdir');
759
-            $path = $defaultDir . DIRECTORY_SEPARATOR . self::DEFAULT_BUILD_FILENAME;
760
-        }
761
-
762
-        // Adding filename if necessary
763
-        if (is_dir($path)) {
764
-            $path .= DIRECTORY_SEPARATOR . self::DEFAULT_BUILD_FILENAME;
765
-        }
766
-
767
-        // Check if path is available
768
-        $dirname = dirname($path);
769
-        if (is_dir($dirname) && !is_file($path)) {
770
-            return $path;
771
-        }
772
-
773
-        // Path is valid, but buildfile already exists
774
-        if (is_file($path)) {
775
-            throw new ConfigurationException('Buildfile already exists.');
776
-        }
777
-
778
-        throw new ConfigurationException('Invalid path for sample buildfile.');
779
-    }
780
-
781
-    /**
782
-     * Writes sample buildfile.
783
-     *
784
-     * If $buildfilePath does not exist, the buildfile is created.
785
-     *
786
-     * @param $buildfilePath buildfile's location
787
-     *
788
-     * @throws ConfigurationException
789
-     */
790
-    protected static function initWrite($buildfilePath): void
791
-    {
792
-        // Overwriting protection
793
-        if (file_exists($buildfilePath)) {
794
-            throw new ConfigurationException('Cannot overwrite existing file.');
795
-        }
796
-
797
-        file_put_contents($buildfilePath, self::DEFAULT_BUILD_CONTENT);
798
-    }
799
-
800
-    /**
801
-     * Sets the stream to use for standard (non-error) output.
802
-     *
803
-     * @param OutputStream $stream the stream to use for standard output
804
-     */
805
-    public static function setOutputStream(OutputStream $stream)
806
-    {
807
-        self::$out = $stream;
808
-    }
809
-
810
-    /**
811
-     * Sets the stream to use for error output.
812
-     *
813
-     * @param OutputStream $stream the stream to use for error output
814
-     */
815
-    public static function setErrorStream(OutputStream $stream): void
816
-    {
817
-        self::$err = $stream;
818
-    }
819
-
820
-    /**
821
-     * Handle the -propertyfile argument.
822
-     *
823
-     * @throws ConfigurationException
824
-     * @throws IOException
825
-     */
826
-    private function handleArgPropertyFile(array $args, int $pos): int
827
-    {
828
-        if (!isset($args[$pos + 1])) {
829
-            throw new ConfigurationException('You must specify a filename when using the -propertyfile argument');
830
-        }
831
-
832
-        $this->propertyFiles[] = $args[++$pos];
833
-
834
-        return $pos;
835
-    }
836
-
837
-    /**
838
-     * Search parent directories for the build file.
839
-     *
840
-     * Takes the given target as a suffix to append to each
841
-     * parent directory in search of a build file.  Once the
842
-     * root of the file-system has been reached an exception
843
-     * is thrown.
844
-     *
845
-     * @param string $start start file path
846
-     * @param string $suffix suffix filename to look for in parents
847
-     *
848
-     * @return File A handle to the build file
849
-     * @throws ConfigurationException
850
-     *
851
-     */
852
-    private function findBuildFile($start, $suffix)
853
-    {
854
-        if (self::getMsgOutputLevel() >= Project::MSG_INFO) {
855
-            self::$out->write('Searching for ' . $suffix . ' ...' . PHP_EOL);
856
-        }
857
-
858
-        $parent = new File((new File($start))->getAbsolutePath());
859
-        $file = new File($parent, $suffix);
860
-
861
-        // check if the target file exists in the current directory
862
-        while (!$file->exists()) {
863
-            // change to parent directory
864
-            $parent = $parent->getParentFile();
865
-
866
-            // if parent is null, then we are at the root of the fs,
867
-            // complain that we can't find the build file.
868
-            if (null === $parent) {
869
-                throw new ConfigurationException('Could not locate a build file!');
870
-            }
871
-            // refresh our file handle
872
-            $file = new File($parent, $suffix);
873
-        }
874
-
875
-        return $file;
876
-    }
877
-
878
-    /**
879
-     * Making output level a static property so that this property
880
-     * can be accessed by other parts of the system, enabling
881
-     * us to display more information -- e.g. backtraces -- for "debug" level.
882
-     *
883
-     * @return int
884
-     */
885
-    public static function getMsgOutputLevel()
886
-    {
887
-        return self::$msgOutputLevel;
888
-    }
889
-
890
-    /**
891
-     * @throws IOException
892
-     */
893
-    private function loadPropertyFiles(): void
894
-    {
895
-        foreach ($this->propertyFiles as $filename) {
896
-            $fileParserFactory = new FileParserFactory();
897
-            $fileParser = $fileParserFactory->createParser(pathinfo($filename, PATHINFO_EXTENSION));
898
-            $p = new Properties(null, $fileParser);
899
-
900
-            try {
901
-                $p->load(new File($filename));
902
-            } catch (IOException $e) {
903
-                self::$out->write('Could not load property file ' . $filename . ': ' . $e->getMessage());
904
-            }
905
-            foreach ($p->getProperties() as $prop => $value) {
906
-                self::$definedProps->setProperty($prop, $value);
907
-            }
908
-        }
909
-    }
910
-
911
-    /**
912
-     * Close logfiles, if we have been writing to them.
913
-     *
914
-     * @since Phing 2.3.0
915
-     */
916
-    private static function handleLogfile(): void
917
-    {
918
-        if (self::$isLogFileUsed) {
919
-            self::$err->close();
920
-            self::$out->close();
921
-        }
922
-    }
923
-
924
-    /**
925
-     * Prints the message of the Exception if it's not null.
926
-     */
927
-    public static function printMessage(Throwable $t): void
928
-    {
929
-        if (null === self::$err) { // Make sure our error output is initialized
930
-            self::initializeOutputStreams();
931
-        }
932
-        if (self::getMsgOutputLevel() >= Project::MSG_VERBOSE) {
933
-            self::$err->write((string) $t . PHP_EOL);
934
-        } else {
935
-            self::$err->write($t->getMessage() . PHP_EOL);
936
-        }
937
-    }
938
-
939
-    /**
940
-     * Sets the stdout and stderr streams if they are not already set.
941
-     */
942
-    private static function initializeOutputStreams()
943
-    {
944
-        if (null === self::$out) {
945
-            if (!defined('STDOUT')) {
946
-                self::$out = new OutputStream(fopen('php://stdout', 'w'));
947
-            } else {
948
-                self::$out = new OutputStream(STDOUT);
949
-            }
950
-        }
951
-        if (null === self::$err) {
952
-            if (!defined('STDERR')) {
953
-                self::$err = new OutputStream(fopen('php://stderr', 'w'));
954
-            } else {
955
-                self::$err = new OutputStream(STDERR);
956
-            }
957
-        }
958
-    }
959
-
960
-    /**
961
-     * This operation is expected to call `exit($int)`, which
962
-     * is what the base version does.
963
-     * However, it is possible to do something else.
964
-     *
965
-     * @param int $exitCode code to exit with
966
-     */
967
-    protected static function statusExit($exitCode): void
968
-    {
969
-        Phing::shutdown();
970
-
971
-        exit($exitCode);
972
-    }
973
-
974
-    /**
975
-     * Performs any shutdown routines, such as stopping timers.
976
-     *
977
-     * @throws IOException
978
-     */
979
-    public static function shutdown(): void
980
-    {
981
-        FileSystem::getFileSystem()::deleteFilesOnExit();
982
-        self::$msgOutputLevel = Project::MSG_INFO;
983
-        self::restoreIni();
984
-        self::getTimer()->stop();
985
-    }
986
-
987
-    /**
988
-     * Restores [most] PHP INI values to their pre-Phing state.
989
-     *
990
-     * Currently the following settings are not restored:
991
-     *  - max_execution_time (because getting current time limit is not possible)
992
-     *  - memory_limit (which may have been increased by Phing)
993
-     */
994
-    private static function restoreIni(): void
995
-    {
996
-        foreach (self::$origIniSettings as $settingName => $settingValue) {
997
-            switch ($settingName) {
998
-                case 'error_reporting':
999
-                    error_reporting($settingValue);
1000
-
1001
-                    break;
1002
-
1003
-                default:
1004
-                    ini_set($settingName, $settingValue);
1005
-            }
1006
-        }
1007
-    }
1008
-
1009
-    /**
1010
-     * Returns reference to DefaultClock object.
1011
-     */
1012
-    public static function getTimer(): DefaultClock
1013
-    {
1014
-        if (null === self::$timer) {
1015
-            self::$timer = new DefaultClock();
1016
-        }
1017
-
1018
-        return self::$timer;
1019
-    }
1020
-
1021
-    /**
1022
-     * This sets a property that was set via command line or otherwise passed into Phing.
1023
-     *
1024
-     * @param string $name
1025
-     * @param mixed $value
1026
-     *
1027
-     * @return mixed value of found property (or null, if none found)
1028
-     */
1029
-    public static function setDefinedProperty($name, $value)
1030
-    {
1031
-        return self::$definedProps->setProperty($name, $value);
1032
-    }
1033
-
1034
-    /**
1035
-     * Executes the build.
1036
-     *
1037
-     * @throws IOException
1038
-     * @throws Throwable
1039
-     */
1040
-    public function runBuild(): void
1041
-    {
1042
-        if (!$this->readyToRun) {
1043
-            return;
1044
-        }
1045
-
1046
-        $project = new Project();
1047
-
1048
-        self::setCurrentProject($project);
1049
-        set_error_handler(['Phing\Phing', 'handlePhpError']);
1050
-
1051
-        $error = null;
1052
-
1053
-        try {
1054
-            $this->addBuildListeners($project);
1055
-            $this->addInputHandler($project);
1056
-
1057
-            // set this right away, so that it can be used in logging.
1058
-            $project->setUserProperty('phing.file', $this->buildFile->getAbsolutePath());
1059
-            $project->setUserProperty('phing.dir', dirname($this->buildFile->getAbsolutePath()));
1060
-            $project->setUserProperty('phing.version', static::getPhingVersion());
1061
-            $project->fireBuildStarted();
1062
-            $project->init();
1063
-            $project->setKeepGoingMode($this->keepGoingMode);
1064
-
1065
-            $e = self::$definedProps->keys();
1066
-            while (count($e)) {
1067
-                $arg = (string) array_shift($e);
1068
-                $value = (string) self::$definedProps->getProperty($arg);
1069
-                $project->setUserProperty($arg, $value);
1070
-            }
1071
-            unset($e);
1072
-
1073
-            // first use the Configurator to create the project object
1074
-            // from the given build file.
1075
-
1076
-            ProjectConfigurator::configureProject($project, $this->buildFile);
1077
-
1078
-            // Set the project mode
1079
-            $project->setStrictMode(StringHelper::booleanValue($this->strictMode));
1080
-
1081
-            // make sure that minimum required phing version is satisfied
1082
-            $this->comparePhingVersion($project->getPhingVersion());
1083
-
1084
-            if ($this->projectHelp) {
1085
-                $this->printDescription($project);
1086
-                $this->printTargets($project);
1087
-
1088
-                return;
1089
-            }
1090
-
1091
-            // make sure that we have a target to execute
1092
-            if (0 === count($this->targets)) {
1093
-                $this->targets[] = $project->getDefaultTarget();
1094
-            }
1095
-
1096
-            $project->executeTargets($this->targets);
1097
-        } catch (Throwable $t) {
1098
-            $error = $t;
1099
-
1100
-            throw $t;
1101
-        } finally {
1102
-            if (!$this->projectHelp) {
1103
-                try {
1104
-                    $project->fireBuildFinished($error);
1105
-                } catch (Exception $e) {
1106
-                    self::$err->write('Caught an exception while logging the end of the build.  Exception was:' . PHP_EOL);
1107
-                    self::$err->write($e->getTraceAsString());
1108
-                    if (null !== $error) {
1109
-                        self::$err->write('There has been an error prior to that:' . PHP_EOL);
1110
-                        self::$err->write($error->getTraceAsString());
1111
-                    }
1112
-
1113
-                    throw new BuildException($error);
1114
-                }
1115
-            } elseif (null !== $error) {
1116
-                $project->log($error->getMessage(), Project::MSG_ERR);
1117
-            }
1118
-
1119
-            restore_error_handler();
1120
-            self::unsetCurrentProject();
1121
-        }
1122
-    }
1123
-
1124
-    /**
1125
-     * Bind any registered build listeners to this project.
1126
-     *
1127
-     * This means adding the logger and any build listeners that were specified
1128
-     * with -listener arg.
1129
-     *
1130
-     * @throws BuildException
1131
-     * @throws ConfigurationException
1132
-     */
1133
-    private function addBuildListeners(Project $project)
1134
-    {
1135
-        // Add the default listener
1136
-        $project->addBuildListener($this->createLogger());
1137
-
1138
-        foreach ($this->listeners as $listenerClassname) {
1139
-            try {
1140
-                $clz = Phing::import($listenerClassname);
1141
-            } catch (Exception $e) {
1142
-                $msg = 'Unable to instantiate specified listener '
1143
-                    . 'class ' . $listenerClassname . ' : '
1144
-                    . $e->getMessage();
1145
-
1146
-                throw new ConfigurationException($msg);
1147
-            }
1148
-
1149
-            $listener = new $clz();
1150
-
1151
-            if ($listener instanceof StreamRequiredBuildLogger) {
1152
-                throw new ConfigurationException('Unable to add ' . $listenerClassname . ' as a listener, since it requires explicit error/output streams. (You can specify it as a -logger.)');
1153
-            }
1154
-            $project->addBuildListener($listener);
1155
-        }
1156
-    }
1157
-
1158
-    /**
1159
-     * Creates the default build logger for sending build events to the log.
1160
-     *
1161
-     * @return BuildLogger The created Logger
1162
-     * @throws BuildException
1163
-     *
1164
-     */
1165
-    private function createLogger()
1166
-    {
1167
-        if ($this->silent) {
1168
-            $logger = new SilentLogger();
1169
-            self::$msgOutputLevel = Project::MSG_WARN;
1170
-        } elseif (null !== $this->loggerClassname) {
1171
-            self::import($this->loggerClassname);
1172
-            // get class name part
1173
-            $classname = self::import($this->loggerClassname);
1174
-            $logger = new $classname();
1175
-            if (!($logger instanceof BuildLogger)) {
1176
-                throw new BuildException($classname . ' does not implement the BuildLogger interface.');
1177
-            }
1178
-        } else {
1179
-            $logger = new DefaultLogger();
1180
-        }
1181
-        $logger->setMessageOutputLevel(self::$msgOutputLevel);
1182
-        $logger->setOutputStream(self::$out);
1183
-        $logger->setErrorStream(self::$err);
1184
-        $logger->setEmacsMode($this->emacsMode);
1185
-
1186
-        return $logger;
1187
-    }
1188
-
1189
-    /**
1190
-     * Import a class, supporting the following conventions:
1191
-     * - PEAR style (@see http://pear.php.net/manual/en/standards.naming.php)
1192
-     * - PSR-0 (@see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md).
1193
-     *
1194
-     * @param string $classname Name of class
1195
-     * @param mixed $classpath String or object supporting __toString()
1196
-     *
1197
-     * @throws BuildException - if cannot find the specified file
1198
-     *
1199
-     * @return string the unqualified classname (which can be instantiated)
1200
-     */
1201
-    public static function import($classname, $classpath = null)
1202
-    {
1203
-        // first check to see that the class specified hasn't already been included.
1204
-        if (class_exists($classname)) {
1205
-            return $classname;
1206
-        }
1207
-
1208
-        $filename = strtr($classname, ['_' => DIRECTORY_SEPARATOR, '\\' => DIRECTORY_SEPARATOR]) . '.php';
1209
-
1210
-        Phing::importFile($filename, $classpath);
1211
-
1212
-        return $classname;
1213
-    }
1214
-
1215
-    /**
1216
-     * Import a PHP file.
1217
-     *
1218
-     * This used to be named __import, however PHP has reserved all method names
1219
-     * with a double underscore prefix for future use.
1220
-     *
1221
-     * @param string $path Path to the PHP file
1222
-     * @param mixed $classpath String or object supporting __toString()
1223
-     *
1224
-     * @throws ConfigurationException
1225
-     */
1226
-    public static function importFile($path, $classpath = null)
1227
-    {
1228
-        if ($classpath) {
1229
-            // Apparently casting to (string) no longer invokes __toString() automatically.
1230
-            if (is_object($classpath)) {
1231
-                $classpath = $classpath->__toString();
1232
-            }
1233
-
1234
-            // classpaths are currently additive, but we also don't want to just
1235
-            // indiscriminantly prepand/append stuff to the include_path.  This means
1236
-            // we need to parse current incldue_path, and prepend any
1237
-            // specified classpath locations that are not already in the include_path.
1238
-            //
1239
-            // NOTE:  the reason why we do it this way instead of just changing include_path
1240
-            // and then changing it back, is that in many cases applications (e.g. Propel) will
1241
-            // include/require class files from within method calls.  This means that not all
1242
-            // necessary files will be included in this import() call, and hence we can't
1243
-            // change the include_path back without breaking those apps.  While this method could
1244
-            // be more expensive than switching & switching back (not sure, but maybe), it makes it
1245
-            // possible to write far less expensive run-time applications (e.g. using Propel), which is
1246
-            // really where speed matters more.
1247
-
1248
-            $curr_parts = Phing::explodeIncludePath();
1249
-            $add_parts = Phing::explodeIncludePath($classpath);
1250
-            $new_parts = array_diff($add_parts, $curr_parts);
1251
-            if ($new_parts) {
1252
-                set_include_path(implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts)));
1253
-            }
1254
-        }
1255
-
1256
-        $ret = include_once $path;
1257
-
1258
-        if (false === $ret) {
1259
-            $msg = "Error importing {$path}";
1260
-            if (self::getMsgOutputLevel() >= Project::MSG_DEBUG) {
1261
-                $x = new Exception('for-path-trace-only');
1262
-                $msg .= $x->getTraceAsString();
1263
-            }
1264
-
1265
-            throw new ConfigurationException($msg);
1266
-        }
1267
-    }
1268
-
1269
-    /**
1270
-     * Creates the InputHandler and adds it to the project.
1271
-     *
1272
-     * @param Project $project the project instance
1273
-     *
1274
-     * @throws ConfigurationException
1275
-     */
1276
-    private function addInputHandler(Project $project): void
1277
-    {
1278
-        if (null === $this->inputHandlerClassname) {
1279
-            $handler = new ConsoleInputHandler(STDIN, new ConsoleOutput());
1280
-        } else {
1281
-            try {
1282
-                $clz = Phing::import($this->inputHandlerClassname);
1283
-                $handler = new $clz();
1284
-                if (null !== $project && method_exists($handler, 'setProject')) {
1285
-                    $handler->setProject($project);
1286
-                }
1287
-            } catch (Exception $e) {
1288
-                $msg = 'Unable to instantiate specified input handler '
1289
-                    . 'class ' . $this->inputHandlerClassname . ' : '
1290
-                    . $e->getMessage();
1291
-
1292
-                throw new ConfigurationException($msg);
1293
-            }
1294
-        }
1295
-        $project->setInputHandler($handler);
1296
-    }
1297
-
1298
-    /**
1299
-     * @param string $version
1300
-     *
1301
-     * @throws BuildException
1302
-     * @throws ConfigurationException
1303
-     */
1304
-    private function comparePhingVersion($version): void
1305
-    {
1306
-        $current = strtolower(self::getPhingVersion());
1307
-        $current = trim(str_replace('phing', '', $current));
1308
-
1309
-        // make sure that version checks are not applied to trunk
1310
-        if ('dev' === $current) {
1311
-            return;
1312
-        }
1313
-
1314
-        if (-1 == version_compare($current, $version)) {
1315
-            throw new BuildException(
1316
-                sprintf('Incompatible Phing version (%s). Version "%s" required.', $current, $version)
1317
-            );
1318
-        }
1319
-    }
1320
-
1321
-    /**
1322
-     * Print the project description, if any.
1323
-     *
1324
-     * @throws IOException
1325
-     */
1326
-    public function printDescription(Project $project): void
1327
-    {
1328
-        if (null !== $project->getDescription()) {
1329
-            $project->log($project->getDescription());
1330
-        }
1331
-    }
1332
-
1333
-    /**
1334
-     * Print out a list of all targets in the current buildfile.
1335
-     */
1336
-    public function printTargets(Project $project)
1337
-    {
1338
-        $visibleTargets = array_filter($project->getTargets(), function (Target $target) {
1339
-            return !$target->isHidden() && !empty($target->getName());
1340
-        });
1341
-        $padding = array_reduce($visibleTargets, function (int $carry, Target $target) {
1342
-            return max(strlen($target->getName()), $carry);
1343
-        }, 0);
1344
-        $categories = [
1345
-            'Default target:' => array_filter($visibleTargets, function (Target $target) use ($project) {
1346
-                return trim(strval($target)) === $project->getDefaultTarget();
1347
-            }),
1348
-            'Main targets:' => array_filter($visibleTargets, function (Target $target) {
1349
-                return !empty($target->getDescription());
1350
-            }),
1351
-            'Subtargets:' => array_filter($visibleTargets, function (Target $target) {
1352
-                return empty($target->getDescription());
1353
-            }),
1354
-        ];
1355
-        foreach ($categories as $title => $targets) {
1356
-            $targetList = $this->generateTargetList($title, $targets, $padding);
1357
-            $project->log($targetList, Project::MSG_WARN);
1358
-        }
1359
-    }
1360
-
1361
-    /**
1362
-     * Returns a formatted list of target names with an optional description.
1363
-     *
1364
-     * @param string $title Title for this list
1365
-     * @param Target[] $targets Targets in this list
1366
-     * @param int $padding Padding for name column
1367
-     */
1368
-    private function generateTargetList(string $title, array $targets, int $padding): string
1369
-    {
1370
-        usort($targets, function (Target $a, Target $b) {
1371
-            return $a->getName() <=> $b->getName();
1372
-        });
1373
-
1374
-        $header = <<<HEADER
1375
-            {$title}
1376
-            -------------------------------------------------------------------------------
1377
-
1378
-            HEADER;
1379
-
1380
-        $getDetails = function (Target $target) use ($padding): string {
1381
-            $details = [];
1382
-            if (!empty($target->getDescription())) {
1383
-                $details[] = $target->getDescription();
1384
-            }
1385
-            if (!empty($target->getDependencies())) {
1386
-                $details[] = ' - depends on: ' . implode(', ', $target->getDependencies());
1387
-            }
1388
-            if (!empty($target->getIf())) {
1389
-                $details[] = ' - if property: ' . $target->getIf();
1390
-            }
1391
-            if (!empty($target->getUnless())) {
1392
-                $details[] = ' - unless property: ' . $target->getUnless();
1393
-            }
1394
-            $detailsToString = function (?string $name, ?string $detail) use ($padding): string {
1395
-                return sprintf(" %-{$padding}s  %s", $name, $detail);
1396
-            };
1397
-
1398
-            return implode(PHP_EOL, array_map($detailsToString, [$target->getName()], $details));
1399
-        };
1400
-
1401
-        return $header . implode(PHP_EOL, array_map($getDetails, $targets)) . PHP_EOL;
1402
-    }
1403
-
1404
-    /**
1405
-     * Unsets the current Project.
1406
-     */
1407
-    public static function unsetCurrentProject(): void
1408
-    {
1409
-        self::$currentProject = null;
1410
-    }
1411
-
1412
-    /**
1413
-     * Error handler for PHP errors encountered during the build.
1414
-     * This uses the logging for the currently configured project.
1415
-     *
1416
-     * @param $level
1417
-     * @param string $message
1418
-     * @param $file
1419
-     * @param $line
1420
-     */
1421
-    public static function handlePhpError($level, $message, $file, $line)
1422
-    {
1423
-        // don't want to print suppressed errors
1424
-        if (error_reporting() > 0) {
1425
-            if (self::$phpErrorCapture) {
1426
-                self::$capturedPhpErrors[] = [
1427
-                    'message' => $message,
1428
-                    'level' => $level,
1429
-                    'line' => $line,
1430
-                    'file' => $file,
1431
-                ];
1432
-            } else {
1433
-                $message = '[PHP Error] ' . $message;
1434
-                $message .= ' [line ' . $line . ' of ' . $file . ']';
1435
-
1436
-                switch ($level) {
1437
-                    case E_USER_DEPRECATED:
1438
-                    case E_DEPRECATED:
1439
-                    case E_STRICT:
1440
-                    case E_NOTICE:
1441
-                    case E_USER_NOTICE:
1442
-                        self::log($message, Project::MSG_VERBOSE);
1443
-
1444
-                        break;
1445
-
1446
-                    case E_WARNING:
1447
-                    case E_USER_WARNING:
1448
-                        self::log($message, Project::MSG_WARN);
1449
-
1450
-                        break;
1451
-
1452
-                    case E_ERROR:
1453
-                    case E_USER_ERROR:
1454
-                    default:
1455
-                        self::log($message, Project::MSG_ERR);
1456
-                } // switch
1457
-            } // if phpErrorCapture
1458
-        } // if not @
1459
-    }
1460
-
1461
-    /**
1462
-     * A static convenience method to send a log to the current (last-setup) Project.
1463
-     * If there is no currently-configured Project, then this will do nothing.
1464
-     *
1465
-     * @param string $message
1466
-     * @param int $priority project::MSG_INFO, etc
1467
-     */
1468
-    public static function log($message, $priority = Project::MSG_INFO): void
1469
-    {
1470
-        $p = self::getCurrentProject();
1471
-        if ($p) {
1472
-            $p->log($message, $priority);
1473
-        }
1474
-    }
1475
-
1476
-    /**
1477
-     * Gets the current Project.
1478
-     *
1479
-     * @return Project current Project or NULL if none is set yet/still
1480
-     */
1481
-    public static function getCurrentProject()
1482
-    {
1483
-        return self::$currentProject;
1484
-    }
1485
-
1486
-    /**
1487
-     * Sets the current Project.
1488
-     *
1489
-     * @param Project $p
1490
-     */
1491
-    public static function setCurrentProject($p): void
1492
-    {
1493
-        self::$currentProject = $p;
1494
-    }
1495
-
1496
-    /**
1497
-     * Begins capturing PHP errors to a buffer.
1498
-     * While errors are being captured, they are not logged.
1499
-     */
1500
-    public static function startPhpErrorCapture(): void
1501
-    {
1502
-        self::$phpErrorCapture = true;
1503
-        self::$capturedPhpErrors = [];
1504
-    }
1505
-
1506
-    /**
1507
-     * Stops capturing PHP errors to a buffer.
1508
-     * The errors will once again be logged after calling this method.
1509
-     */
1510
-    public static function stopPhpErrorCapture(): void
1511
-    {
1512
-        self::$phpErrorCapture = false;
1513
-    }
1514
-
1515
-    /**
1516
-     * Clears the captured errors without affecting the starting/stopping of the capture.
1517
-     */
1518
-    public static function clearCapturedPhpErrors(): void
1519
-    {
1520
-        self::$capturedPhpErrors = [];
1521
-    }
1522
-
1523
-    /**
1524
-     * Gets any PHP errors that were captured to buffer.
1525
-     *
1526
-     * @return array array('message' => message, 'line' => line number, 'file' => file name, 'level' => error level)
1527
-     */
1528
-    public static function getCapturedPhpErrors()
1529
-    {
1530
-        return self::$capturedPhpErrors;
1531
-    }
1532
-
1533
-    /**
1534
-     * This gets a property that was set via command line or otherwise passed into Phing.
1535
-     * "Defined" in this case means "externally defined".  The reason this method exists is to
1536
-     * provide a public means of accessing commandline properties for (e.g.) logger or listener
1537
-     * scripts.  E.g. to specify which logfile to use, PearLogger needs to be able to access
1538
-     * the pear.log.name property.
1539
-     *
1540
-     * @param string $name
1541
-     *
1542
-     * @return string value of found property (or null, if none found)
1543
-     */
1544
-    public static function getDefinedProperty($name)
1545
-    {
1546
-        return self::$definedProps->getProperty($name);
1547
-    }
1548
-
1549
-    /**
1550
-     * Retuns reference to all properties.
1551
-     */
1552
-    public static function &getProperties()
1553
-    {
1554
-        return self::$properties;
1555
-    }
1556
-
1557
-    /**
1558
-     * Start up Phing.
1559
-     * Sets up the Phing environment but does not initiate the build process.
1560
-     *
1561
-     * @throws exception - If the Phing environment cannot be initialized
1562
-     */
1563
-    public static function startup(): void
1564
-    {
1565
-        // setup STDOUT and STDERR defaults
1566
-        self::initializeOutputStreams();
1567
-
1568
-        // some init stuff
1569
-        self::getTimer()->start();
1570
-
1571
-        self::setSystemConstants();
1572
-        self::setIncludePaths();
1573
-        self::setIni();
1574
-    }
1575
-
1576
-    /**
1577
-     * Set System constants which can be retrieved by calling Phing::getProperty($propName).
1578
-     */
1579
-    private static function setSystemConstants(): void
1580
-    {
1581
-        /*
1582
-         * PHP_OS returns on
1583
-         *   WindowsNT4.0sp6  => WINNT
1584
-         *   Windows2000      => WINNT
1585
-         *   Windows ME       => WIN32
1586
-         *   Windows 98SE     => WIN32
1587
-         *   FreeBSD 4.5p7    => FreeBSD
1588
-         *   Redhat Linux     => Linux
1589
-         *   Mac OS X         => Darwin
1590
-         */
1591
-        self::setProperty('host.os', PHP_OS);
1592
-
1593
-        // this is used by some tasks too
1594
-        self::setProperty('os.name', PHP_OS);
1595
-
1596
-        // it's still possible this won't be defined,
1597
-        // e.g. if Phing is being included in another app w/o
1598
-        // using the phing.php script.
1599
-        if (!defined('PHP_CLASSPATH')) {
1600
-            define('PHP_CLASSPATH', get_include_path());
1601
-        }
1602
-
1603
-        self::setProperty('php.classpath', PHP_CLASSPATH);
1604
-
1605
-        // try to determine the host filesystem and set system property
1606
-        // used by Fileself::getFileSystem to instantiate the correct
1607
-        // abstraction layer
1608
-
1609
-        if (PHP_OS_FAMILY === 'Windows') {
1610
-            self::setProperty('host.fstype', 'WINDOWS');
1611
-            self::setProperty('user.home', getenv('HOMEDRIVE') . getenv('HOMEPATH'));
1612
-        } else {
1613
-            self::setProperty('host.fstype', 'UNIX');
1614
-            self::setProperty('user.home', getenv('HOME'));
1615
-        }
1616
-        self::setProperty(self::PHP_INTERPRETER, PHP_BINARY);
1617
-        self::setProperty('file.separator', FileUtils::getSeparator());
1618
-        self::setProperty('line.separator', PHP_EOL);
1619
-        self::setProperty('path.separator', FileUtils::getPathSeparator());
1620
-        self::setProperty(self::PHP_VERSION, PHP_VERSION);
1621
-        self::setProperty('php.tmpdir', sys_get_temp_dir());
1622
-        self::setProperty('application.startdir', getcwd());
1623
-        self::setProperty('phing.startTime', gmdate('D, d M Y H:i:s', time()) . ' GMT');
1624
-
1625
-        // try to detect machine dependent information
1626
-        $sysInfo = [];
1627
-        if (function_exists('posix_uname') && 0 !== stripos(PHP_OS, 'WIN')) {
1628
-            $sysInfo = posix_uname();
1629
-        } else {
1630
-            $sysInfo['nodename'] = php_uname('n');
1631
-            $sysInfo['machine'] = php_uname('m');
1632
-            //this is a not so ideal substition, but maybe better than nothing
1633
-            $sysInfo['domain'] = $_SERVER['SERVER_NAME'] ?? 'unknown';
1634
-            $sysInfo['release'] = php_uname('r');
1635
-            $sysInfo['version'] = php_uname('v');
1636
-        }
1637
-
1638
-        self::setProperty('host.name', $sysInfo['nodename'] ?? 'unknown');
1639
-        self::setProperty('host.arch', $sysInfo['machine'] ?? 'unknown');
1640
-        self::setProperty('host.domain', $sysInfo['domain'] ?? 'unknown');
1641
-        self::setProperty('host.os.release', $sysInfo['release'] ?? 'unknown');
1642
-        self::setProperty('host.os.version', $sysInfo['version'] ?? 'unknown');
1643
-        unset($sysInfo);
1644
-    }
1645
-
1646
-    /**
1647
-     * @param $propName
1648
-     * @param $propValue
1649
-     *
1650
-     * @return string
1651
-     */
1652
-    public static function setProperty($propName, $propValue)
1653
-    {
1654
-        $propName = (string) $propName;
1655
-        $oldValue = self::getProperty($propName);
1656
-        self::$properties[$propName] = $propValue;
1657
-
1658
-        return $oldValue;
1659
-    }
1660
-
1661
-    /**
1662
-     * Sets the include path to PHP_CLASSPATH constant (if this has been defined).
1663
-     *
1664
-     * @throws ConfigurationException - if the include_path could not be set (for some bizarre reason)
1665
-     */
1666
-    private static function setIncludePaths(): void
1667
-    {
1668
-        if (defined('PHP_CLASSPATH')) {
1669
-            $result = set_include_path(PHP_CLASSPATH);
1670
-            if (false === $result) {
1671
-                throw new ConfigurationException('Could not set PHP include_path.');
1672
-            }
1673
-            self::$origIniSettings['include_path'] = $result; // save original value for setting back later
1674
-        }
1675
-    }
1676
-
1677
-    /**
1678
-     * Sets PHP INI values that Phing needs.
1679
-     */
1680
-    private static function setIni(): void
1681
-    {
1682
-        self::$origIniSettings['error_reporting'] = error_reporting(E_ALL);
1683
-
1684
-        // We won't bother storing original max_execution_time, since 1) the value in
1685
-        // php.ini may be wrong (and there's no way to get the current value) and
1686
-        // 2) it would mean something very strange to set it to a value less than time script
1687
-        // has already been running, which would be the likely change.
1688
-
1689
-        set_time_limit(0);
1690
-
1691
-        self::$origIniSettings['short_open_tag'] = ini_set('short_open_tag', 'off');
1692
-        self::$origIniSettings['default_charset'] = ini_set('default_charset', 'iso-8859-1');
1693
-
1694
-        $mem_limit = (int) SizeHelper::fromHumanToBytes(ini_get('memory_limit'));
1695
-        if ($mem_limit < (32 * 1024 * 1024) && $mem_limit > -1) {
1696
-            // We do *not* need to save the original value here, since we don't plan to restore
1697
-            // this after shutdown (we don't trust the effectiveness of PHP's garbage collection).
1698
-            ini_set('memory_limit', '32M'); // nore: this may need to be higher for many projects
1699
-        }
1700
-    }
1701
-}
Please login to merge, or discard this patch.
Switch Indentation   -1616 removed lines patch added patch discarded remove patch
@@ -83,1619 +83,3 @@
 block discarded – undo
83 83
      */
84 84
     public const DEFAULT_BUILD_FILENAME = 'build.xml';
85 85
     public const DEFAULT_BUILD_CONTENT = <<<'XML'
86
-        <?xml version="1.0" encoding="UTF-8" ?>
87
-
88
-        <project name="" description="" default="">
89
-            
90
-            <target name="" description="">
91
-                
92
-            </target>
93
-            
94
-        </project>
95
-        XML;
96
-    public const PHING_HOME = 'phing.home';
97
-    public const PHP_VERSION = 'php.version';
98
-    public const PHP_INTERPRETER = 'php.interpreter';
99
-
100
-    /**
101
-     * Our current message output status. Follows Project::MSG_XXX.
102
-     */
103
-    private static $msgOutputLevel = Project::MSG_INFO;
104
-    /**
105
-     * Set of properties that are passed in from commandline or invoking code.
106
-     *
107
-     * @var Properties
108
-     */
109
-    private static $definedProps;
110
-    /**
111
-     * Used by utility function getResourcePath().
112
-     */
113
-    private static $importPaths;
114
-    /**
115
-     * System-wide static properties (moved from System).
116
-     */
117
-    private static $properties = [];
118
-    /**
119
-     * Static system timer.
120
-     */
121
-    private static $timer;
122
-    /**
123
-     * The current Project.
124
-     */
125
-    private static $currentProject;
126
-    /**
127
-     * Whether to capture PHP errors to buffer.
128
-     */
129
-    private static $phpErrorCapture = false;
130
-    /**
131
-     * Array of captured PHP errors.
132
-     */
133
-    private static $capturedPhpErrors = [];
134
-    /**
135
-     * @var OUtputStream stream for standard output
136
-     */
137
-    private static $out;
138
-    /**
139
-     * @var OutputStream stream for error output
140
-     */
141
-    private static $err;
142
-    /**
143
-     * @var bool whether we are using a logfile
144
-     */
145
-    private static $isLogFileUsed = false;
146
-    /**
147
-     * Array to hold original ini settings that Phing changes (and needs
148
-     * to restore in restoreIni() method).
149
-     *
150
-     * @var array Struct of array(setting-name => setting-value)
151
-     *
152
-     * @see restoreIni()
153
-     */
154
-    private static $origIniSettings = [];
155
-    /**
156
-     * PhingFile that we are using for configuration.
157
-     */
158
-    private $buildFile;
159
-    /**
160
-     * The build targets.
161
-     */
162
-    private $targets = [];
163
-    /**
164
-     * Names of classes to add as listeners to project.
165
-     */
166
-    private $listeners = [];
167
-    /**
168
-     * keep going mode.
169
-     *
170
-     * @var bool
171
-     */
172
-    private $keepGoingMode = false;
173
-    private $loggerClassname;
174
-    /**
175
-     * The class to handle input (can be only one).
176
-     */
177
-    private $inputHandlerClassname;
178
-    /**
179
-     * Whether or not log output should be reduced to the minimum.
180
-     *
181
-     * @var bool
182
-     */
183
-    private $silent = false;
184
-    /**
185
-     * Indicates whether phing should run in strict mode.
186
-     */
187
-    private $strictMode = false;
188
-    /**
189
-     * Indicates if this phing should be run.
190
-     */
191
-    private $readyToRun = false;
192
-    /**
193
-     * Indicates we should only parse and display the project help information.
194
-     */
195
-    private $projectHelp = false;
196
-    /**
197
-     * Whether to values in a property file should override existing values.
198
-     */
199
-    private $propertyFileOverride = false;
200
-    /**
201
-     * Whether or not output to the log is to be unadorned.
202
-     */
203
-    private $emacsMode = false;
204
-
205
-    /**
206
-     * @var string
207
-     */
208
-    private $searchForThis;
209
-    private $propertyFiles = [];
210
-
211
-    /**
212
-     * Gets the stream to use for standard (non-error) output.
213
-     *
214
-     * @return OutputStream
215
-     */
216
-    public static function getOutputStream()
217
-    {
218
-        return self::$out;
219
-    }
220
-
221
-    /**
222
-     * Gets the stream to use for error output.
223
-     *
224
-     * @return OutputStream
225
-     */
226
-    public static function getErrorStream()
227
-    {
228
-        return self::$err;
229
-    }
230
-
231
-    /**
232
-     * Command line entry point. This method kicks off the building
233
-     * of a project object and executes a build using either a given
234
-     * target or the default target.
235
-     *
236
-     * @param array $args command line args
237
-     * @throws Exception
238
-     */
239
-    public static function fire($args): void
240
-    {
241
-        self::start($args);
242
-    }
243
-
244
-    /**
245
-     * Entry point allowing for more options from other front ends.
246
-     *
247
-     * This method encapsulates the complete build lifecycle.
248
-     *
249
-     * @param array $args the commandline args passed to phing shell script
250
-     * @param array $additionalUserProperties Any additional properties to be passed to Phing (alternative front-end might implement this).
251
-     *                                        These additional properties will be available using the getDefinedProperty() method and will
252
-     *                                        be added to the project's "user" properties
253
-     *
254
-     * @throws Exception - if there is an error during build
255
-     * @see    runBuild()
256
-     *
257
-     * @see    execute()
258
-     */
259
-    public static function start($args, array $additionalUserProperties = null)
260
-    {
261
-        try {
262
-            $m = new self();
263
-            $m->execute($args);
264
-        } catch (Exception $exc) {
265
-            self::handleLogfile();
266
-            self::printMessage($exc);
267
-            self::statusExit(1);
268
-
269
-            return;
270
-        }
271
-
272
-        if (null !== $additionalUserProperties) {
273
-            foreach ($additionalUserProperties as $key => $value) {
274
-                $m::setDefinedProperty($key, $value);
275
-            }
276
-        }
277
-
278
-        // expect the worst
279
-        $exitCode = 1;
280
-
281
-        try {
282
-            try {
283
-                $m->runBuild();
284
-                $exitCode = 0;
285
-            } catch (ExitStatusException $ese) {
286
-                $exitCode = $ese->getCode();
287
-                if (0 !== $exitCode) {
288
-                    self::handleLogfile();
289
-
290
-                    throw $ese;
291
-                }
292
-            }
293
-        } catch (BuildException $exc) {
294
-            // avoid printing output twice: self::printMessage($exc);
295
-        } catch (Throwable $exc) {
296
-            self::printMessage($exc);
297
-        } finally {
298
-            self::handleLogfile();
299
-        }
300
-        self::statusExit($exitCode);
301
-    }
302
-
303
-    /**
304
-     * Setup/initialize Phing environment from commandline args.
305
-     *
306
-     * @param array $args commandline args passed to phing shell
307
-     *
308
-     * @throws ConfigurationException
309
-     */
310
-    public function execute($args): void
311
-    {
312
-        self::$definedProps = new Properties();
313
-        $this->searchForThis = null;
314
-
315
-        // 1) First handle any options which should always
316
-        // Note: The order in which these are executed is important (if multiple of these options are specified)
317
-
318
-        if (in_array('-help', $args) || in_array('-h', $args)) {
319
-            static::printUsage();
320
-
321
-            return;
322
-        }
323
-
324
-        if (in_array('-version', $args) || in_array('-v', $args)) {
325
-            static::printVersion();
326
-
327
-            return;
328
-        }
329
-
330
-        if (in_array('-init', $args) || in_array('-i', $args)) {
331
-            $key = array_search('-init', $args) ?: array_search('-i', $args);
332
-            $path = $args[$key + 1] ?? null;
333
-
334
-            self::init($path);
335
-
336
-            return;
337
-        }
338
-
339
-        if (in_array('-diagnostics', $args)) {
340
-            Diagnostics::doReport(new PrintStream(self::$out));
341
-
342
-            return;
343
-        }
344
-
345
-        // 2) Next pull out stand-alone args.
346
-        // Note: The order in which these are executed is important (if multiple of these options are specified)
347
-
348
-        if (
349
-            false !== ($key = array_search('-quiet', $args, true))
350
-            || false !== ($key = array_search(
351
-                '-q',
352
-                $args,
353
-                true
354
-            ))
355
-        ) {
356
-            self::$msgOutputLevel = Project::MSG_WARN;
357
-            unset($args[$key]);
358
-        }
359
-
360
-        if (
361
-            false !== ($key = array_search('-emacs', $args, true))
362
-            || false !== ($key = array_search('-e', $args, true))
363
-        ) {
364
-            $this->emacsMode = true;
365
-            unset($args[$key]);
366
-        }
367
-
368
-        if (false !== ($key = array_search('-verbose', $args, true))) {
369
-            self::$msgOutputLevel = Project::MSG_VERBOSE;
370
-            unset($args[$key]);
371
-        }
372
-
373
-        if (false !== ($key = array_search('-debug', $args, true))) {
374
-            self::$msgOutputLevel = Project::MSG_DEBUG;
375
-            unset($args[$key]);
376
-        }
377
-
378
-        if (
379
-            false !== ($key = array_search('-silent', $args, true))
380
-            || false !== ($key = array_search('-S', $args, true))
381
-        ) {
382
-            $this->silent = true;
383
-            unset($args[$key]);
384
-        }
385
-
386
-        if (false !== ($key = array_search('-propertyfileoverride', $args, true))) {
387
-            $this->propertyFileOverride = true;
388
-            unset($args[$key]);
389
-        }
390
-
391
-        // 3) Finally, cycle through to parse remaining args
392
-        //
393
-        $keys = array_keys($args); // Use keys and iterate to max(keys) since there may be some gaps
394
-        $max = $keys ? max($keys) : -1;
395
-        for ($i = 0; $i <= $max; ++$i) {
396
-            if (!array_key_exists($i, $args)) {
397
-                // skip this argument, since it must have been removed above.
398
-                continue;
399
-            }
400
-
401
-            $arg = $args[$i];
402
-
403
-            if ('-logfile' == $arg) {
404
-                try {
405
-                    // see: http://phing.info/trac/ticket/65
406
-                    if (!isset($args[$i + 1])) {
407
-                        $msg = "You must specify a log file when using the -logfile argument\n";
408
-
409
-                        throw new ConfigurationException($msg);
410
-                    }
411
-
412
-                    $logFile = new File($args[++$i]);
413
-                    $out = new FileOutputStream($logFile); // overwrite
414
-                    self::setOutputStream($out);
415
-                    self::setErrorStream($out);
416
-                    self::$isLogFileUsed = true;
417
-                } catch (IOException $ioe) {
418
-                    $msg = 'Cannot write on the specified log file. Make sure the path exists and you have write permissions.';
419
-
420
-                    throw new ConfigurationException($msg, $ioe);
421
-                }
422
-            } elseif ('-buildfile' == $arg || '-file' == $arg || '-f' == $arg) {
423
-                if (!isset($args[$i + 1])) {
424
-                    $msg = 'You must specify a buildfile when using the -buildfile argument.';
425
-
426
-                    throw new ConfigurationException($msg);
427
-                }
428
-
429
-                $this->buildFile = new File($args[++$i]);
430
-            } elseif ('-listener' == $arg) {
431
-                if (!isset($args[$i + 1])) {
432
-                    $msg = 'You must specify a listener class when using the -listener argument';
433
-
434
-                    throw new ConfigurationException($msg);
435
-                }
436
-
437
-                $this->listeners[] = $args[++$i];
438
-            } elseif (StringHelper::startsWith('-D', $arg)) {
439
-                // Evaluating the property information //
440
-                // Checking whether arg. is not just a switch, and next arg. does not starts with switch identifier
441
-                if (('-D' == $arg) && (!StringHelper::startsWith('-', $args[$i + 1]))) {
442
-                    $name = $args[++$i];
443
-                } else {
444
-                    $name = substr($arg, 2);
445
-                }
446
-
447
-                $value = null;
448
-                $posEq = strpos($name, '=');
449
-                if (false !== $posEq) {
450
-                    $value = substr($name, $posEq + 1);
451
-                    $name = substr($name, 0, $posEq);
452
-                } elseif ($i < count($args) - 1 && !StringHelper::startsWith('-D', $args[$i + 1])) {
453
-                    $value = $args[++$i];
454
-                }
455
-                self::$definedProps->setProperty($name, $value);
456
-            } elseif ('-logger' == $arg) {
457
-                if (!isset($args[$i + 1])) {
458
-                    $msg = 'You must specify a classname when using the -logger argument';
459
-
460
-                    throw new ConfigurationException($msg);
461
-                }
462
-
463
-                $this->loggerClassname = $args[++$i];
464
-            } elseif ('-no-strict' == $arg) {
465
-                $this->strictMode = false;
466
-            } elseif ('-strict' == $arg) {
467
-                $this->strictMode = true;
468
-            } elseif ('-inputhandler' == $arg) {
469
-                if (null !== $this->inputHandlerClassname) {
470
-                    throw new ConfigurationException('Only one input handler class may be specified.');
471
-                }
472
-                if (!isset($args[$i + 1])) {
473
-                    $msg = 'You must specify a classname when using the -inputhandler argument';
474
-
475
-                    throw new ConfigurationException($msg);
476
-                }
477
-
478
-                $this->inputHandlerClassname = $args[++$i];
479
-            } elseif ('-propertyfile' === $arg) {
480
-                $i = $this->handleArgPropertyFile($args, $i);
481
-            } elseif ('-keep-going' === $arg || '-k' === $arg) {
482
-                $this->keepGoingMode = true;
483
-            } elseif ('-longtargets' == $arg) {
484
-                self::$definedProps->setProperty('phing.showlongtargets', 1);
485
-            } elseif ('-projecthelp' == $arg || '-targets' == $arg || '-list' == $arg || '-l' == $arg || '-p' == $arg) {
486
-                // set the flag to display the targets and quit
487
-                $this->projectHelp = true;
488
-            } elseif ('-find' == $arg) {
489
-                // eat up next arg if present, default to build.xml
490
-                if ($i < count($args) - 1) {
491
-                    $this->searchForThis = $args[++$i];
492
-                } else {
493
-                    $this->searchForThis = self::DEFAULT_BUILD_FILENAME;
494
-                }
495
-            } elseif ('-' == substr($arg, 0, 1)) {
496
-                // we don't have any more args
497
-                self::printUsage();
498
-                self::$err->write(PHP_EOL);
499
-
500
-                throw new ConfigurationException('Unknown argument: ' . $arg);
501
-            } else {
502
-                // if it's no other arg, it may be the target
503
-                $this->targets[] = $arg;
504
-            }
505
-        }
506
-
507
-        // if buildFile was not specified on the command line,
508
-        if (null === $this->buildFile) {
509
-            // but -find then search for it
510
-            if (null !== $this->searchForThis) {
511
-                $this->buildFile = $this->findBuildFile(self::getProperty('user.dir'), $this->searchForThis);
512
-            } else {
513
-                $this->buildFile = new File(self::DEFAULT_BUILD_FILENAME);
514
-            }
515
-        }
516
-
517
-        try {
518
-            // make sure buildfile (or buildfile.dist) exists
519
-            if (!$this->buildFile->exists()) {
520
-                $distFile = new File($this->buildFile->getAbsolutePath() . '.dist');
521
-                if (!$distFile->exists()) {
522
-                    throw new ConfigurationException(
523
-                        'Buildfile: ' . $this->buildFile->__toString() . ' does not exist!'
524
-                    );
525
-                }
526
-                $this->buildFile = $distFile;
527
-            }
528
-
529
-            // make sure it's not a directory
530
-            if ($this->buildFile->isDirectory()) {
531
-                throw new ConfigurationException('Buildfile: ' . $this->buildFile->__toString() . ' is a dir!');
532
-            }
533
-        } catch (IOException $e) {
534
-            // something else happened, buildfile probably not readable
535
-            throw new ConfigurationException('Buildfile: ' . $this->buildFile->__toString() . ' is not readable!');
536
-        }
537
-
538
-        $this->loadPropertyFiles();
539
-
540
-        $this->readyToRun = true;
541
-    }
542
-
543
-    /**
544
-     * Prints the usage of how to use this class.
545
-     */
546
-    public static function printUsage()
547
-    {
548
-        $msg = '';
549
-        $msg .= 'phing [options] [target [target2 [target3] ...]]' . PHP_EOL;
550
-        $msg .= 'Options: ' . PHP_EOL;
551
-        $msg .= '  -h -help               print this message' . PHP_EOL;
552
-        $msg .= '  -l -list               list available targets in this project' . PHP_EOL;
553
-        $msg .= '  -i -init [file]        generates an initial buildfile' . PHP_EOL;
554
-        $msg .= '  -v -version            print the version information and exit' . PHP_EOL;
555
-        $msg .= '  -q -quiet              be extra quiet' . PHP_EOL;
556
-        $msg .= '  -S -silent             print nothing but task outputs and build failures' . PHP_EOL;
557
-        $msg .= '  -verbose               be extra verbose' . PHP_EOL;
558
-        $msg .= '  -debug                 print debugging information' . PHP_EOL;
559
-        $msg .= '  -emacs, -e             produce logging information without adornments' . PHP_EOL;
560
-        $msg .= '  -diagnostics           print diagnostics information' . PHP_EOL;
561
-        $msg .= '  -strict                runs build in strict mode, considering a warning as error' . PHP_EOL;
562
-        $msg .= '  -no-strict             runs build normally (overrides buildfile attribute)' . PHP_EOL;
563
-        $msg .= '  -longtargets           show target descriptions during build' . PHP_EOL;
564
-        $msg .= '  -logfile <file>        use given file for log' . PHP_EOL;
565
-        $msg .= '  -logger <classname>    the class which is to perform logging' . PHP_EOL;
566
-        $msg .= '  -listener <classname>  add an instance of class as a project listener' . PHP_EOL;
567
-        $msg .= '  -f -buildfile <file>   use given buildfile' . PHP_EOL;
568
-        $msg .= '  -D<property>=<value>   use value for given property' . PHP_EOL;
569
-        $msg .= '  -keep-going, -k        execute all targets that do not depend' . PHP_EOL;
570
-        $msg .= '                         on failed target(s)' . PHP_EOL;
571
-        $msg .= '  -propertyfile <file>   load all properties from file' . PHP_EOL;
572
-        $msg .= '  -propertyfileoverride  values in property file override existing values' . PHP_EOL;
573
-        $msg .= '  -find <file>           search for buildfile towards the root of the' . PHP_EOL;
574
-        $msg .= '                         filesystem and use it' . PHP_EOL;
575
-        $msg .= '  -inputhandler <file>   the class to use to handle user input' . PHP_EOL;
576
-        //$msg .= "  -recursive <file>      search for buildfile downwards and use it" . PHP_EOL;
577
-        $msg .= PHP_EOL;
578
-        $msg .= 'Report bugs to https://github.com/phingofficial/phing/issues' . PHP_EOL;
579
-        self::$err->write($msg);
580
-    }
581
-
582
-    /**
583
-     * Prints the current Phing version.
584
-     */
585
-    public static function printVersion()
586
-    {
587
-        self::$out->write(self::getPhingVersion() . PHP_EOL);
588
-    }
589
-
590
-    /**
591
-     * Gets the current Phing version based on VERSION.TXT file.
592
-     *
593
-     * @return string
594
-     * @throws ConfigurationException
595
-     *
596
-     */
597
-    public static function getPhingVersion(): string
598
-    {
599
-        $versionPath = self::getResourcePath('phing/etc/VERSION.TXT');
600
-        if (null === $versionPath) {
601
-            $versionPath = self::getResourcePath('etc/VERSION.TXT');
602
-        }
603
-        if (null === $versionPath) {
604
-            throw new ConfigurationException('No VERSION.TXT file found; try setting phing.home environment variable.');
605
-        }
606
-
607
-        try { // try to read file
608
-            $file = new File($versionPath);
609
-            $reader = new FileReader($file);
610
-            $phingVersion = trim($reader->read());
611
-        } catch (IOException $iox) {
612
-            throw new ConfigurationException("Can't read version information file");
613
-        }
614
-
615
-        $basePath = dirname(__DIR__, 2);
616
-
617
-        $version = new Version($phingVersion, $basePath);
618
-
619
-        return 'Phing ' . $version->getVersion();
620
-    }
621
-
622
-    /**
623
-     * Looks on include path for specified file.
624
-     *
625
-     * @param string $path
626
-     *
627
-     * @return string|null file found (null if no file found)
628
-     */
629
-    public static function getResourcePath($path): ?string
630
-    {
631
-        if (null === self::$importPaths) {
632
-            self::$importPaths = self::explodeIncludePath();
633
-        }
634
-
635
-        $path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $path);
636
-
637
-        foreach (self::$importPaths as $prefix) {
638
-            $testPath = $prefix . DIRECTORY_SEPARATOR . $path;
639
-            if (file_exists($testPath)) {
640
-                return $testPath;
641
-            }
642
-        }
643
-
644
-        // Check for the property phing.home
645
-        $homeDir = self::getProperty(self::PHING_HOME);
646
-        if ($homeDir) {
647
-            $testPath = $homeDir . DIRECTORY_SEPARATOR . $path;
648
-            if (file_exists($testPath)) {
649
-                return $testPath;
650
-            }
651
-        }
652
-
653
-        // Check for the phing home of phar archive
654
-        if (0 === strpos(self::$importPaths[0], 'phar://')) {
655
-            $testPath = self::$importPaths[0] . '/../' . $path;
656
-            if (file_exists($testPath)) {
657
-                return $testPath;
658
-            }
659
-        }
660
-
661
-        // Do one additional check based on path of current file (Phing.php)
662
-        $maybeHomeDir = realpath(__DIR__ . DIRECTORY_SEPARATOR);
663
-        $testPath = $maybeHomeDir . DIRECTORY_SEPARATOR . $path;
664
-        if (file_exists($testPath)) {
665
-            return $testPath;
666
-        }
667
-
668
-        return null;
669
-    }
670
-
671
-    /**
672
-     * Explode an include path into an array.
673
-     *
674
-     * If no path provided, uses current include_path. Works around issues that
675
-     * occur when the path includes stream schemas.
676
-     *
677
-     * Pulled from Zend_Loader::explodeIncludePath() in ZF1.
678
-     *
679
-     * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
680
-     * @license   http://framework.zend.com/license/new-bsd New BSD License
681
-     *
682
-     * @param null|string $path
683
-     *
684
-     * @return array
685
-     */
686
-    public static function explodeIncludePath($path = null)
687
-    {
688
-        if (null === $path) {
689
-            $path = get_include_path();
690
-        }
691
-
692
-        if (PATH_SEPARATOR === ':') {
693
-            // On *nix systems, include_paths which include paths with a stream
694
-            // schema cannot be safely explode'd, so we have to be a bit more
695
-            // intelligent in the approach.
696
-            $paths = preg_split('#:(?!//)#', $path);
697
-        } else {
698
-            $paths = explode(PATH_SEPARATOR, $path);
699
-        }
700
-
701
-        return $paths;
702
-    }
703
-
704
-    /**
705
-     * Returns property value for a System property.
706
-     * System properties are "global" properties like application.startdir,
707
-     * and user.dir.  Many of these correspond to similar properties in Java
708
-     * or Ant.
709
-     *
710
-     * @param string $propName
711
-     *
712
-     * @return string value of found property (or null, if none found)
713
-     */
714
-    public static function getProperty($propName)
715
-    {
716
-        // some properties are detemined on each access
717
-        // some are cached, see below
718
-
719
-        // default is the cached value:
720
-        $val = self::$properties[$propName] ?? null;
721
-
722
-        // special exceptions
723
-        switch ($propName) {
724
-            case 'user.dir':
725
-                $val = getcwd();
726
-
727
-                break;
728
-        }
729
-
730
-        return $val;
731
-    }
732
-
733
-    /**
734
-     * Creates generic buildfile.
735
-     *
736
-     * @param string $path
737
-     */
738
-    public static function init($path)
739
-    {
740
-        if ($buildfilePath = self::initPath($path)) {
741
-            self::initWrite($buildfilePath);
742
-        }
743
-    }
744
-
745
-    /**
746
-     * Returns buildfile's path.
747
-     *
748
-     * @param $path
749
-     *
750
-     * @return string
751
-     * @throws ConfigurationException
752
-     *
753
-     */
754
-    protected static function initPath($path)
755
-    {
756
-        // Fallback
757
-        if (empty($path)) {
758
-            $defaultDir = self::getProperty('application.startdir');
759
-            $path = $defaultDir . DIRECTORY_SEPARATOR . self::DEFAULT_BUILD_FILENAME;
760
-        }
761
-
762
-        // Adding filename if necessary
763
-        if (is_dir($path)) {
764
-            $path .= DIRECTORY_SEPARATOR . self::DEFAULT_BUILD_FILENAME;
765
-        }
766
-
767
-        // Check if path is available
768
-        $dirname = dirname($path);
769
-        if (is_dir($dirname) && !is_file($path)) {
770
-            return $path;
771
-        }
772
-
773
-        // Path is valid, but buildfile already exists
774
-        if (is_file($path)) {
775
-            throw new ConfigurationException('Buildfile already exists.');
776
-        }
777
-
778
-        throw new ConfigurationException('Invalid path for sample buildfile.');
779
-    }
780
-
781
-    /**
782
-     * Writes sample buildfile.
783
-     *
784
-     * If $buildfilePath does not exist, the buildfile is created.
785
-     *
786
-     * @param $buildfilePath buildfile's location
787
-     *
788
-     * @throws ConfigurationException
789
-     */
790
-    protected static function initWrite($buildfilePath): void
791
-    {
792
-        // Overwriting protection
793
-        if (file_exists($buildfilePath)) {
794
-            throw new ConfigurationException('Cannot overwrite existing file.');
795
-        }
796
-
797
-        file_put_contents($buildfilePath, self::DEFAULT_BUILD_CONTENT);
798
-    }
799
-
800
-    /**
801
-     * Sets the stream to use for standard (non-error) output.
802
-     *
803
-     * @param OutputStream $stream the stream to use for standard output
804
-     */
805
-    public static function setOutputStream(OutputStream $stream)
806
-    {
807
-        self::$out = $stream;
808
-    }
809
-
810
-    /**
811
-     * Sets the stream to use for error output.
812
-     *
813
-     * @param OutputStream $stream the stream to use for error output
814
-     */
815
-    public static function setErrorStream(OutputStream $stream): void
816
-    {
817
-        self::$err = $stream;
818
-    }
819
-
820
-    /**
821
-     * Handle the -propertyfile argument.
822
-     *
823
-     * @throws ConfigurationException
824
-     * @throws IOException
825
-     */
826
-    private function handleArgPropertyFile(array $args, int $pos): int
827
-    {
828
-        if (!isset($args[$pos + 1])) {
829
-            throw new ConfigurationException('You must specify a filename when using the -propertyfile argument');
830
-        }
831
-
832
-        $this->propertyFiles[] = $args[++$pos];
833
-
834
-        return $pos;
835
-    }
836
-
837
-    /**
838
-     * Search parent directories for the build file.
839
-     *
840
-     * Takes the given target as a suffix to append to each
841
-     * parent directory in search of a build file.  Once the
842
-     * root of the file-system has been reached an exception
843
-     * is thrown.
844
-     *
845
-     * @param string $start start file path
846
-     * @param string $suffix suffix filename to look for in parents
847
-     *
848
-     * @return File A handle to the build file
849
-     * @throws ConfigurationException
850
-     *
851
-     */
852
-    private function findBuildFile($start, $suffix)
853
-    {
854
-        if (self::getMsgOutputLevel() >= Project::MSG_INFO) {
855
-            self::$out->write('Searching for ' . $suffix . ' ...' . PHP_EOL);
856
-        }
857
-
858
-        $parent = new File((new File($start))->getAbsolutePath());
859
-        $file = new File($parent, $suffix);
860
-
861
-        // check if the target file exists in the current directory
862
-        while (!$file->exists()) {
863
-            // change to parent directory
864
-            $parent = $parent->getParentFile();
865
-
866
-            // if parent is null, then we are at the root of the fs,
867
-            // complain that we can't find the build file.
868
-            if (null === $parent) {
869
-                throw new ConfigurationException('Could not locate a build file!');
870
-            }
871
-            // refresh our file handle
872
-            $file = new File($parent, $suffix);
873
-        }
874
-
875
-        return $file;
876
-    }
877
-
878
-    /**
879
-     * Making output level a static property so that this property
880
-     * can be accessed by other parts of the system, enabling
881
-     * us to display more information -- e.g. backtraces -- for "debug" level.
882
-     *
883
-     * @return int
884
-     */
885
-    public static function getMsgOutputLevel()
886
-    {
887
-        return self::$msgOutputLevel;
888
-    }
889
-
890
-    /**
891
-     * @throws IOException
892
-     */
893
-    private function loadPropertyFiles(): void
894
-    {
895
-        foreach ($this->propertyFiles as $filename) {
896
-            $fileParserFactory = new FileParserFactory();
897
-            $fileParser = $fileParserFactory->createParser(pathinfo($filename, PATHINFO_EXTENSION));
898
-            $p = new Properties(null, $fileParser);
899
-
900
-            try {
901
-                $p->load(new File($filename));
902
-            } catch (IOException $e) {
903
-                self::$out->write('Could not load property file ' . $filename . ': ' . $e->getMessage());
904
-            }
905
-            foreach ($p->getProperties() as $prop => $value) {
906
-                self::$definedProps->setProperty($prop, $value);
907
-            }
908
-        }
909
-    }
910
-
911
-    /**
912
-     * Close logfiles, if we have been writing to them.
913
-     *
914
-     * @since Phing 2.3.0
915
-     */
916
-    private static function handleLogfile(): void
917
-    {
918
-        if (self::$isLogFileUsed) {
919
-            self::$err->close();
920
-            self::$out->close();
921
-        }
922
-    }
923
-
924
-    /**
925
-     * Prints the message of the Exception if it's not null.
926
-     */
927
-    public static function printMessage(Throwable $t): void
928
-    {
929
-        if (null === self::$err) { // Make sure our error output is initialized
930
-            self::initializeOutputStreams();
931
-        }
932
-        if (self::getMsgOutputLevel() >= Project::MSG_VERBOSE) {
933
-            self::$err->write((string) $t . PHP_EOL);
934
-        } else {
935
-            self::$err->write($t->getMessage() . PHP_EOL);
936
-        }
937
-    }
938
-
939
-    /**
940
-     * Sets the stdout and stderr streams if they are not already set.
941
-     */
942
-    private static function initializeOutputStreams()
943
-    {
944
-        if (null === self::$out) {
945
-            if (!defined('STDOUT')) {
946
-                self::$out = new OutputStream(fopen('php://stdout', 'w'));
947
-            } else {
948
-                self::$out = new OutputStream(STDOUT);
949
-            }
950
-        }
951
-        if (null === self::$err) {
952
-            if (!defined('STDERR')) {
953
-                self::$err = new OutputStream(fopen('php://stderr', 'w'));
954
-            } else {
955
-                self::$err = new OutputStream(STDERR);
956
-            }
957
-        }
958
-    }
959
-
960
-    /**
961
-     * This operation is expected to call `exit($int)`, which
962
-     * is what the base version does.
963
-     * However, it is possible to do something else.
964
-     *
965
-     * @param int $exitCode code to exit with
966
-     */
967
-    protected static function statusExit($exitCode): void
968
-    {
969
-        Phing::shutdown();
970
-
971
-        exit($exitCode);
972
-    }
973
-
974
-    /**
975
-     * Performs any shutdown routines, such as stopping timers.
976
-     *
977
-     * @throws IOException
978
-     */
979
-    public static function shutdown(): void
980
-    {
981
-        FileSystem::getFileSystem()::deleteFilesOnExit();
982
-        self::$msgOutputLevel = Project::MSG_INFO;
983
-        self::restoreIni();
984
-        self::getTimer()->stop();
985
-    }
986
-
987
-    /**
988
-     * Restores [most] PHP INI values to their pre-Phing state.
989
-     *
990
-     * Currently the following settings are not restored:
991
-     *  - max_execution_time (because getting current time limit is not possible)
992
-     *  - memory_limit (which may have been increased by Phing)
993
-     */
994
-    private static function restoreIni(): void
995
-    {
996
-        foreach (self::$origIniSettings as $settingName => $settingValue) {
997
-            switch ($settingName) {
998
-                case 'error_reporting':
999
-                    error_reporting($settingValue);
1000
-
1001
-                    break;
1002
-
1003
-                default:
1004
-                    ini_set($settingName, $settingValue);
1005
-            }
1006
-        }
1007
-    }
1008
-
1009
-    /**
1010
-     * Returns reference to DefaultClock object.
1011
-     */
1012
-    public static function getTimer(): DefaultClock
1013
-    {
1014
-        if (null === self::$timer) {
1015
-            self::$timer = new DefaultClock();
1016
-        }
1017
-
1018
-        return self::$timer;
1019
-    }
1020
-
1021
-    /**
1022
-     * This sets a property that was set via command line or otherwise passed into Phing.
1023
-     *
1024
-     * @param string $name
1025
-     * @param mixed $value
1026
-     *
1027
-     * @return mixed value of found property (or null, if none found)
1028
-     */
1029
-    public static function setDefinedProperty($name, $value)
1030
-    {
1031
-        return self::$definedProps->setProperty($name, $value);
1032
-    }
1033
-
1034
-    /**
1035
-     * Executes the build.
1036
-     *
1037
-     * @throws IOException
1038
-     * @throws Throwable
1039
-     */
1040
-    public function runBuild(): void
1041
-    {
1042
-        if (!$this->readyToRun) {
1043
-            return;
1044
-        }
1045
-
1046
-        $project = new Project();
1047
-
1048
-        self::setCurrentProject($project);
1049
-        set_error_handler(['Phing\Phing', 'handlePhpError']);
1050
-
1051
-        $error = null;
1052
-
1053
-        try {
1054
-            $this->addBuildListeners($project);
1055
-            $this->addInputHandler($project);
1056
-
1057
-            // set this right away, so that it can be used in logging.
1058
-            $project->setUserProperty('phing.file', $this->buildFile->getAbsolutePath());
1059
-            $project->setUserProperty('phing.dir', dirname($this->buildFile->getAbsolutePath()));
1060
-            $project->setUserProperty('phing.version', static::getPhingVersion());
1061
-            $project->fireBuildStarted();
1062
-            $project->init();
1063
-            $project->setKeepGoingMode($this->keepGoingMode);
1064
-
1065
-            $e = self::$definedProps->keys();
1066
-            while (count($e)) {
1067
-                $arg = (string) array_shift($e);
1068
-                $value = (string) self::$definedProps->getProperty($arg);
1069
-                $project->setUserProperty($arg, $value);
1070
-            }
1071
-            unset($e);
1072
-
1073
-            // first use the Configurator to create the project object
1074
-            // from the given build file.
1075
-
1076
-            ProjectConfigurator::configureProject($project, $this->buildFile);
1077
-
1078
-            // Set the project mode
1079
-            $project->setStrictMode(StringHelper::booleanValue($this->strictMode));
1080
-
1081
-            // make sure that minimum required phing version is satisfied
1082
-            $this->comparePhingVersion($project->getPhingVersion());
1083
-
1084
-            if ($this->projectHelp) {
1085
-                $this->printDescription($project);
1086
-                $this->printTargets($project);
1087
-
1088
-                return;
1089
-            }
1090
-
1091
-            // make sure that we have a target to execute
1092
-            if (0 === count($this->targets)) {
1093
-                $this->targets[] = $project->getDefaultTarget();
1094
-            }
1095
-
1096
-            $project->executeTargets($this->targets);
1097
-        } catch (Throwable $t) {
1098
-            $error = $t;
1099
-
1100
-            throw $t;
1101
-        } finally {
1102
-            if (!$this->projectHelp) {
1103
-                try {
1104
-                    $project->fireBuildFinished($error);
1105
-                } catch (Exception $e) {
1106
-                    self::$err->write('Caught an exception while logging the end of the build.  Exception was:' . PHP_EOL);
1107
-                    self::$err->write($e->getTraceAsString());
1108
-                    if (null !== $error) {
1109
-                        self::$err->write('There has been an error prior to that:' . PHP_EOL);
1110
-                        self::$err->write($error->getTraceAsString());
1111
-                    }
1112
-
1113
-                    throw new BuildException($error);
1114
-                }
1115
-            } elseif (null !== $error) {
1116
-                $project->log($error->getMessage(), Project::MSG_ERR);
1117
-            }
1118
-
1119
-            restore_error_handler();
1120
-            self::unsetCurrentProject();
1121
-        }
1122
-    }
1123
-
1124
-    /**
1125
-     * Bind any registered build listeners to this project.
1126
-     *
1127
-     * This means adding the logger and any build listeners that were specified
1128
-     * with -listener arg.
1129
-     *
1130
-     * @throws BuildException
1131
-     * @throws ConfigurationException
1132
-     */
1133
-    private function addBuildListeners(Project $project)
1134
-    {
1135
-        // Add the default listener
1136
-        $project->addBuildListener($this->createLogger());
1137
-
1138
-        foreach ($this->listeners as $listenerClassname) {
1139
-            try {
1140
-                $clz = Phing::import($listenerClassname);
1141
-            } catch (Exception $e) {
1142
-                $msg = 'Unable to instantiate specified listener '
1143
-                    . 'class ' . $listenerClassname . ' : '
1144
-                    . $e->getMessage();
1145
-
1146
-                throw new ConfigurationException($msg);
1147
-            }
1148
-
1149
-            $listener = new $clz();
1150
-
1151
-            if ($listener instanceof StreamRequiredBuildLogger) {
1152
-                throw new ConfigurationException('Unable to add ' . $listenerClassname . ' as a listener, since it requires explicit error/output streams. (You can specify it as a -logger.)');
1153
-            }
1154
-            $project->addBuildListener($listener);
1155
-        }
1156
-    }
1157
-
1158
-    /**
1159
-     * Creates the default build logger for sending build events to the log.
1160
-     *
1161
-     * @return BuildLogger The created Logger
1162
-     * @throws BuildException
1163
-     *
1164
-     */
1165
-    private function createLogger()
1166
-    {
1167
-        if ($this->silent) {
1168
-            $logger = new SilentLogger();
1169
-            self::$msgOutputLevel = Project::MSG_WARN;
1170
-        } elseif (null !== $this->loggerClassname) {
1171
-            self::import($this->loggerClassname);
1172
-            // get class name part
1173
-            $classname = self::import($this->loggerClassname);
1174
-            $logger = new $classname();
1175
-            if (!($logger instanceof BuildLogger)) {
1176
-                throw new BuildException($classname . ' does not implement the BuildLogger interface.');
1177
-            }
1178
-        } else {
1179
-            $logger = new DefaultLogger();
1180
-        }
1181
-        $logger->setMessageOutputLevel(self::$msgOutputLevel);
1182
-        $logger->setOutputStream(self::$out);
1183
-        $logger->setErrorStream(self::$err);
1184
-        $logger->setEmacsMode($this->emacsMode);
1185
-
1186
-        return $logger;
1187
-    }
1188
-
1189
-    /**
1190
-     * Import a class, supporting the following conventions:
1191
-     * - PEAR style (@see http://pear.php.net/manual/en/standards.naming.php)
1192
-     * - PSR-0 (@see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md).
1193
-     *
1194
-     * @param string $classname Name of class
1195
-     * @param mixed $classpath String or object supporting __toString()
1196
-     *
1197
-     * @throws BuildException - if cannot find the specified file
1198
-     *
1199
-     * @return string the unqualified classname (which can be instantiated)
1200
-     */
1201
-    public static function import($classname, $classpath = null)
1202
-    {
1203
-        // first check to see that the class specified hasn't already been included.
1204
-        if (class_exists($classname)) {
1205
-            return $classname;
1206
-        }
1207
-
1208
-        $filename = strtr($classname, ['_' => DIRECTORY_SEPARATOR, '\\' => DIRECTORY_SEPARATOR]) . '.php';
1209
-
1210
-        Phing::importFile($filename, $classpath);
1211
-
1212
-        return $classname;
1213
-    }
1214
-
1215
-    /**
1216
-     * Import a PHP file.
1217
-     *
1218
-     * This used to be named __import, however PHP has reserved all method names
1219
-     * with a double underscore prefix for future use.
1220
-     *
1221
-     * @param string $path Path to the PHP file
1222
-     * @param mixed $classpath String or object supporting __toString()
1223
-     *
1224
-     * @throws ConfigurationException
1225
-     */
1226
-    public static function importFile($path, $classpath = null)
1227
-    {
1228
-        if ($classpath) {
1229
-            // Apparently casting to (string) no longer invokes __toString() automatically.
1230
-            if (is_object($classpath)) {
1231
-                $classpath = $classpath->__toString();
1232
-            }
1233
-
1234
-            // classpaths are currently additive, but we also don't want to just
1235
-            // indiscriminantly prepand/append stuff to the include_path.  This means
1236
-            // we need to parse current incldue_path, and prepend any
1237
-            // specified classpath locations that are not already in the include_path.
1238
-            //
1239
-            // NOTE:  the reason why we do it this way instead of just changing include_path
1240
-            // and then changing it back, is that in many cases applications (e.g. Propel) will
1241
-            // include/require class files from within method calls.  This means that not all
1242
-            // necessary files will be included in this import() call, and hence we can't
1243
-            // change the include_path back without breaking those apps.  While this method could
1244
-            // be more expensive than switching & switching back (not sure, but maybe), it makes it
1245
-            // possible to write far less expensive run-time applications (e.g. using Propel), which is
1246
-            // really where speed matters more.
1247
-
1248
-            $curr_parts = Phing::explodeIncludePath();
1249
-            $add_parts = Phing::explodeIncludePath($classpath);
1250
-            $new_parts = array_diff($add_parts, $curr_parts);
1251
-            if ($new_parts) {
1252
-                set_include_path(implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts)));
1253
-            }
1254
-        }
1255
-
1256
-        $ret = include_once $path;
1257
-
1258
-        if (false === $ret) {
1259
-            $msg = "Error importing {$path}";
1260
-            if (self::getMsgOutputLevel() >= Project::MSG_DEBUG) {
1261
-                $x = new Exception('for-path-trace-only');
1262
-                $msg .= $x->getTraceAsString();
1263
-            }
1264
-
1265
-            throw new ConfigurationException($msg);
1266
-        }
1267
-    }
1268
-
1269
-    /**
1270
-     * Creates the InputHandler and adds it to the project.
1271
-     *
1272
-     * @param Project $project the project instance
1273
-     *
1274
-     * @throws ConfigurationException
1275
-     */
1276
-    private function addInputHandler(Project $project): void
1277
-    {
1278
-        if (null === $this->inputHandlerClassname) {
1279
-            $handler = new ConsoleInputHandler(STDIN, new ConsoleOutput());
1280
-        } else {
1281
-            try {
1282
-                $clz = Phing::import($this->inputHandlerClassname);
1283
-                $handler = new $clz();
1284
-                if (null !== $project && method_exists($handler, 'setProject')) {
1285
-                    $handler->setProject($project);
1286
-                }
1287
-            } catch (Exception $e) {
1288
-                $msg = 'Unable to instantiate specified input handler '
1289
-                    . 'class ' . $this->inputHandlerClassname . ' : '
1290
-                    . $e->getMessage();
1291
-
1292
-                throw new ConfigurationException($msg);
1293
-            }
1294
-        }
1295
-        $project->setInputHandler($handler);
1296
-    }
1297
-
1298
-    /**
1299
-     * @param string $version
1300
-     *
1301
-     * @throws BuildException
1302
-     * @throws ConfigurationException
1303
-     */
1304
-    private function comparePhingVersion($version): void
1305
-    {
1306
-        $current = strtolower(self::getPhingVersion());
1307
-        $current = trim(str_replace('phing', '', $current));
1308
-
1309
-        // make sure that version checks are not applied to trunk
1310
-        if ('dev' === $current) {
1311
-            return;
1312
-        }
1313
-
1314
-        if (-1 == version_compare($current, $version)) {
1315
-            throw new BuildException(
1316
-                sprintf('Incompatible Phing version (%s). Version "%s" required.', $current, $version)
1317
-            );
1318
-        }
1319
-    }
1320
-
1321
-    /**
1322
-     * Print the project description, if any.
1323
-     *
1324
-     * @throws IOException
1325
-     */
1326
-    public function printDescription(Project $project): void
1327
-    {
1328
-        if (null !== $project->getDescription()) {
1329
-            $project->log($project->getDescription());
1330
-        }
1331
-    }
1332
-
1333
-    /**
1334
-     * Print out a list of all targets in the current buildfile.
1335
-     */
1336
-    public function printTargets(Project $project)
1337
-    {
1338
-        $visibleTargets = array_filter($project->getTargets(), function (Target $target) {
1339
-            return !$target->isHidden() && !empty($target->getName());
1340
-        });
1341
-        $padding = array_reduce($visibleTargets, function (int $carry, Target $target) {
1342
-            return max(strlen($target->getName()), $carry);
1343
-        }, 0);
1344
-        $categories = [
1345
-            'Default target:' => array_filter($visibleTargets, function (Target $target) use ($project) {
1346
-                return trim(strval($target)) === $project->getDefaultTarget();
1347
-            }),
1348
-            'Main targets:' => array_filter($visibleTargets, function (Target $target) {
1349
-                return !empty($target->getDescription());
1350
-            }),
1351
-            'Subtargets:' => array_filter($visibleTargets, function (Target $target) {
1352
-                return empty($target->getDescription());
1353
-            }),
1354
-        ];
1355
-        foreach ($categories as $title => $targets) {
1356
-            $targetList = $this->generateTargetList($title, $targets, $padding);
1357
-            $project->log($targetList, Project::MSG_WARN);
1358
-        }
1359
-    }
1360
-
1361
-    /**
1362
-     * Returns a formatted list of target names with an optional description.
1363
-     *
1364
-     * @param string $title Title for this list
1365
-     * @param Target[] $targets Targets in this list
1366
-     * @param int $padding Padding for name column
1367
-     */
1368
-    private function generateTargetList(string $title, array $targets, int $padding): string
1369
-    {
1370
-        usort($targets, function (Target $a, Target $b) {
1371
-            return $a->getName() <=> $b->getName();
1372
-        });
1373
-
1374
-        $header = <<<HEADER
1375
-            {$title}
1376
-            -------------------------------------------------------------------------------
1377
-
1378
-            HEADER;
1379
-
1380
-        $getDetails = function (Target $target) use ($padding): string {
1381
-            $details = [];
1382
-            if (!empty($target->getDescription())) {
1383
-                $details[] = $target->getDescription();
1384
-            }
1385
-            if (!empty($target->getDependencies())) {
1386
-                $details[] = ' - depends on: ' . implode(', ', $target->getDependencies());
1387
-            }
1388
-            if (!empty($target->getIf())) {
1389
-                $details[] = ' - if property: ' . $target->getIf();
1390
-            }
1391
-            if (!empty($target->getUnless())) {
1392
-                $details[] = ' - unless property: ' . $target->getUnless();
1393
-            }
1394
-            $detailsToString = function (?string $name, ?string $detail) use ($padding): string {
1395
-                return sprintf(" %-{$padding}s  %s", $name, $detail);
1396
-            };
1397
-
1398
-            return implode(PHP_EOL, array_map($detailsToString, [$target->getName()], $details));
1399
-        };
1400
-
1401
-        return $header . implode(PHP_EOL, array_map($getDetails, $targets)) . PHP_EOL;
1402
-    }
1403
-
1404
-    /**
1405
-     * Unsets the current Project.
1406
-     */
1407
-    public static function unsetCurrentProject(): void
1408
-    {
1409
-        self::$currentProject = null;
1410
-    }
1411
-
1412
-    /**
1413
-     * Error handler for PHP errors encountered during the build.
1414
-     * This uses the logging for the currently configured project.
1415
-     *
1416
-     * @param $level
1417
-     * @param string $message
1418
-     * @param $file
1419
-     * @param $line
1420
-     */
1421
-    public static function handlePhpError($level, $message, $file, $line)
1422
-    {
1423
-        // don't want to print suppressed errors
1424
-        if (error_reporting() > 0) {
1425
-            if (self::$phpErrorCapture) {
1426
-                self::$capturedPhpErrors[] = [
1427
-                    'message' => $message,
1428
-                    'level' => $level,
1429
-                    'line' => $line,
1430
-                    'file' => $file,
1431
-                ];
1432
-            } else {
1433
-                $message = '[PHP Error] ' . $message;
1434
-                $message .= ' [line ' . $line . ' of ' . $file . ']';
1435
-
1436
-                switch ($level) {
1437
-                    case E_USER_DEPRECATED:
1438
-                    case E_DEPRECATED:
1439
-                    case E_STRICT:
1440
-                    case E_NOTICE:
1441
-                    case E_USER_NOTICE:
1442
-                        self::log($message, Project::MSG_VERBOSE);
1443
-
1444
-                        break;
1445
-
1446
-                    case E_WARNING:
1447
-                    case E_USER_WARNING:
1448
-                        self::log($message, Project::MSG_WARN);
1449
-
1450
-                        break;
1451
-
1452
-                    case E_ERROR:
1453
-                    case E_USER_ERROR:
1454
-                    default:
1455
-                        self::log($message, Project::MSG_ERR);
1456
-                } // switch
1457
-            } // if phpErrorCapture
1458
-        } // if not @
1459
-    }
1460
-
1461
-    /**
1462
-     * A static convenience method to send a log to the current (last-setup) Project.
1463
-     * If there is no currently-configured Project, then this will do nothing.
1464
-     *
1465
-     * @param string $message
1466
-     * @param int $priority project::MSG_INFO, etc
1467
-     */
1468
-    public static function log($message, $priority = Project::MSG_INFO): void
1469
-    {
1470
-        $p = self::getCurrentProject();
1471
-        if ($p) {
1472
-            $p->log($message, $priority);
1473
-        }
1474
-    }
1475
-
1476
-    /**
1477
-     * Gets the current Project.
1478
-     *
1479
-     * @return Project current Project or NULL if none is set yet/still
1480
-     */
1481
-    public static function getCurrentProject()
1482
-    {
1483
-        return self::$currentProject;
1484
-    }
1485
-
1486
-    /**
1487
-     * Sets the current Project.
1488
-     *
1489
-     * @param Project $p
1490
-     */
1491
-    public static function setCurrentProject($p): void
1492
-    {
1493
-        self::$currentProject = $p;
1494
-    }
1495
-
1496
-    /**
1497
-     * Begins capturing PHP errors to a buffer.
1498
-     * While errors are being captured, they are not logged.
1499
-     */
1500
-    public static function startPhpErrorCapture(): void
1501
-    {
1502
-        self::$phpErrorCapture = true;
1503
-        self::$capturedPhpErrors = [];
1504
-    }
1505
-
1506
-    /**
1507
-     * Stops capturing PHP errors to a buffer.
1508
-     * The errors will once again be logged after calling this method.
1509
-     */
1510
-    public static function stopPhpErrorCapture(): void
1511
-    {
1512
-        self::$phpErrorCapture = false;
1513
-    }
1514
-
1515
-    /**
1516
-     * Clears the captured errors without affecting the starting/stopping of the capture.
1517
-     */
1518
-    public static function clearCapturedPhpErrors(): void
1519
-    {
1520
-        self::$capturedPhpErrors = [];
1521
-    }
1522
-
1523
-    /**
1524
-     * Gets any PHP errors that were captured to buffer.
1525
-     *
1526
-     * @return array array('message' => message, 'line' => line number, 'file' => file name, 'level' => error level)
1527
-     */
1528
-    public static function getCapturedPhpErrors()
1529
-    {
1530
-        return self::$capturedPhpErrors;
1531
-    }
1532
-
1533
-    /**
1534
-     * This gets a property that was set via command line or otherwise passed into Phing.
1535
-     * "Defined" in this case means "externally defined".  The reason this method exists is to
1536
-     * provide a public means of accessing commandline properties for (e.g.) logger or listener
1537
-     * scripts.  E.g. to specify which logfile to use, PearLogger needs to be able to access
1538
-     * the pear.log.name property.
1539
-     *
1540
-     * @param string $name
1541
-     *
1542
-     * @return string value of found property (or null, if none found)
1543
-     */
1544
-    public static function getDefinedProperty($name)
1545
-    {
1546
-        return self::$definedProps->getProperty($name);
1547
-    }
1548
-
1549
-    /**
1550
-     * Retuns reference to all properties.
1551
-     */
1552
-    public static function &getProperties()
1553
-    {
1554
-        return self::$properties;
1555
-    }
1556
-
1557
-    /**
1558
-     * Start up Phing.
1559
-     * Sets up the Phing environment but does not initiate the build process.
1560
-     *
1561
-     * @throws exception - If the Phing environment cannot be initialized
1562
-     */
1563
-    public static function startup(): void
1564
-    {
1565
-        // setup STDOUT and STDERR defaults
1566
-        self::initializeOutputStreams();
1567
-
1568
-        // some init stuff
1569
-        self::getTimer()->start();
1570
-
1571
-        self::setSystemConstants();
1572
-        self::setIncludePaths();
1573
-        self::setIni();
1574
-    }
1575
-
1576
-    /**
1577
-     * Set System constants which can be retrieved by calling Phing::getProperty($propName).
1578
-     */
1579
-    private static function setSystemConstants(): void
1580
-    {
1581
-        /*
1582
-         * PHP_OS returns on
1583
-         *   WindowsNT4.0sp6  => WINNT
1584
-         *   Windows2000      => WINNT
1585
-         *   Windows ME       => WIN32
1586
-         *   Windows 98SE     => WIN32
1587
-         *   FreeBSD 4.5p7    => FreeBSD
1588
-         *   Redhat Linux     => Linux
1589
-         *   Mac OS X         => Darwin
1590
-         */
1591
-        self::setProperty('host.os', PHP_OS);
1592
-
1593
-        // this is used by some tasks too
1594
-        self::setProperty('os.name', PHP_OS);
1595
-
1596
-        // it's still possible this won't be defined,
1597
-        // e.g. if Phing is being included in another app w/o
1598
-        // using the phing.php script.
1599
-        if (!defined('PHP_CLASSPATH')) {
1600
-            define('PHP_CLASSPATH', get_include_path());
1601
-        }
1602
-
1603
-        self::setProperty('php.classpath', PHP_CLASSPATH);
1604
-
1605
-        // try to determine the host filesystem and set system property
1606
-        // used by Fileself::getFileSystem to instantiate the correct
1607
-        // abstraction layer
1608
-
1609
-        if (PHP_OS_FAMILY === 'Windows') {
1610
-            self::setProperty('host.fstype', 'WINDOWS');
1611
-            self::setProperty('user.home', getenv('HOMEDRIVE') . getenv('HOMEPATH'));
1612
-        } else {
1613
-            self::setProperty('host.fstype', 'UNIX');
1614
-            self::setProperty('user.home', getenv('HOME'));
1615
-        }
1616
-        self::setProperty(self::PHP_INTERPRETER, PHP_BINARY);
1617
-        self::setProperty('file.separator', FileUtils::getSeparator());
1618
-        self::setProperty('line.separator', PHP_EOL);
1619
-        self::setProperty('path.separator', FileUtils::getPathSeparator());
1620
-        self::setProperty(self::PHP_VERSION, PHP_VERSION);
1621
-        self::setProperty('php.tmpdir', sys_get_temp_dir());
1622
-        self::setProperty('application.startdir', getcwd());
1623
-        self::setProperty('phing.startTime', gmdate('D, d M Y H:i:s', time()) . ' GMT');
1624
-
1625
-        // try to detect machine dependent information
1626
-        $sysInfo = [];
1627
-        if (function_exists('posix_uname') && 0 !== stripos(PHP_OS, 'WIN')) {
1628
-            $sysInfo = posix_uname();
1629
-        } else {
1630
-            $sysInfo['nodename'] = php_uname('n');
1631
-            $sysInfo['machine'] = php_uname('m');
1632
-            //this is a not so ideal substition, but maybe better than nothing
1633
-            $sysInfo['domain'] = $_SERVER['SERVER_NAME'] ?? 'unknown';
1634
-            $sysInfo['release'] = php_uname('r');
1635
-            $sysInfo['version'] = php_uname('v');
1636
-        }
1637
-
1638
-        self::setProperty('host.name', $sysInfo['nodename'] ?? 'unknown');
1639
-        self::setProperty('host.arch', $sysInfo['machine'] ?? 'unknown');
1640
-        self::setProperty('host.domain', $sysInfo['domain'] ?? 'unknown');
1641
-        self::setProperty('host.os.release', $sysInfo['release'] ?? 'unknown');
1642
-        self::setProperty('host.os.version', $sysInfo['version'] ?? 'unknown');
1643
-        unset($sysInfo);
1644
-    }
1645
-
1646
-    /**
1647
-     * @param $propName
1648
-     * @param $propValue
1649
-     *
1650
-     * @return string
1651
-     */
1652
-    public static function setProperty($propName, $propValue)
1653
-    {
1654
-        $propName = (string) $propName;
1655
-        $oldValue = self::getProperty($propName);
1656
-        self::$properties[$propName] = $propValue;
1657
-
1658
-        return $oldValue;
1659
-    }
1660
-
1661
-    /**
1662
-     * Sets the include path to PHP_CLASSPATH constant (if this has been defined).
1663
-     *
1664
-     * @throws ConfigurationException - if the include_path could not be set (for some bizarre reason)
1665
-     */
1666
-    private static function setIncludePaths(): void
1667
-    {
1668
-        if (defined('PHP_CLASSPATH')) {
1669
-            $result = set_include_path(PHP_CLASSPATH);
1670
-            if (false === $result) {
1671
-                throw new ConfigurationException('Could not set PHP include_path.');
1672
-            }
1673
-            self::$origIniSettings['include_path'] = $result; // save original value for setting back later
1674
-        }
1675
-    }
1676
-
1677
-    /**
1678
-     * Sets PHP INI values that Phing needs.
1679
-     */
1680
-    private static function setIni(): void
1681
-    {
1682
-        self::$origIniSettings['error_reporting'] = error_reporting(E_ALL);
1683
-
1684
-        // We won't bother storing original max_execution_time, since 1) the value in
1685
-        // php.ini may be wrong (and there's no way to get the current value) and
1686
-        // 2) it would mean something very strange to set it to a value less than time script
1687
-        // has already been running, which would be the likely change.
1688
-
1689
-        set_time_limit(0);
1690
-
1691
-        self::$origIniSettings['short_open_tag'] = ini_set('short_open_tag', 'off');
1692
-        self::$origIniSettings['default_charset'] = ini_set('default_charset', 'iso-8859-1');
1693
-
1694
-        $mem_limit = (int) SizeHelper::fromHumanToBytes(ini_get('memory_limit'));
1695
-        if ($mem_limit < (32 * 1024 * 1024) && $mem_limit > -1) {
1696
-            // We do *not* need to save the original value here, since we don't plan to restore
1697
-            // this after shutdown (we don't trust the effectiveness of PHP's garbage collection).
1698
-            ini_set('memory_limit', '32M'); // nore: this may need to be higher for many projects
1699
-        }
1700
-    }
1701
-}
Please login to merge, or discard this patch.
Spacing   -1616 removed lines patch added patch discarded remove patch
@@ -83,1619 +83,3 @@
 block discarded – undo
83 83
      */
84 84
     public const DEFAULT_BUILD_FILENAME = 'build.xml';
85 85
     public const DEFAULT_BUILD_CONTENT = <<<'XML'
86
-        <?xml version="1.0" encoding="UTF-8" ?>
87
-
88
-        <project name="" description="" default="">
89
-            
90
-            <target name="" description="">
91
-                
92
-            </target>
93
-            
94
-        </project>
95
-        XML;
96
-    public const PHING_HOME = 'phing.home';
97
-    public const PHP_VERSION = 'php.version';
98
-    public const PHP_INTERPRETER = 'php.interpreter';
99
-
100
-    /**
101
-     * Our current message output status. Follows Project::MSG_XXX.
102
-     */
103
-    private static $msgOutputLevel = Project::MSG_INFO;
104
-    /**
105
-     * Set of properties that are passed in from commandline or invoking code.
106
-     *
107
-     * @var Properties
108
-     */
109
-    private static $definedProps;
110
-    /**
111
-     * Used by utility function getResourcePath().
112
-     */
113
-    private static $importPaths;
114
-    /**
115
-     * System-wide static properties (moved from System).
116
-     */
117
-    private static $properties = [];
118
-    /**
119
-     * Static system timer.
120
-     */
121
-    private static $timer;
122
-    /**
123
-     * The current Project.
124
-     */
125
-    private static $currentProject;
126
-    /**
127
-     * Whether to capture PHP errors to buffer.
128
-     */
129
-    private static $phpErrorCapture = false;
130
-    /**
131
-     * Array of captured PHP errors.
132
-     */
133
-    private static $capturedPhpErrors = [];
134
-    /**
135
-     * @var OUtputStream stream for standard output
136
-     */
137
-    private static $out;
138
-    /**
139
-     * @var OutputStream stream for error output
140
-     */
141
-    private static $err;
142
-    /**
143
-     * @var bool whether we are using a logfile
144
-     */
145
-    private static $isLogFileUsed = false;
146
-    /**
147
-     * Array to hold original ini settings that Phing changes (and needs
148
-     * to restore in restoreIni() method).
149
-     *
150
-     * @var array Struct of array(setting-name => setting-value)
151
-     *
152
-     * @see restoreIni()
153
-     */
154
-    private static $origIniSettings = [];
155
-    /**
156
-     * PhingFile that we are using for configuration.
157
-     */
158
-    private $buildFile;
159
-    /**
160
-     * The build targets.
161
-     */
162
-    private $targets = [];
163
-    /**
164
-     * Names of classes to add as listeners to project.
165
-     */
166
-    private $listeners = [];
167
-    /**
168
-     * keep going mode.
169
-     *
170
-     * @var bool
171
-     */
172
-    private $keepGoingMode = false;
173
-    private $loggerClassname;
174
-    /**
175
-     * The class to handle input (can be only one).
176
-     */
177
-    private $inputHandlerClassname;
178
-    /**
179
-     * Whether or not log output should be reduced to the minimum.
180
-     *
181
-     * @var bool
182
-     */
183
-    private $silent = false;
184
-    /**
185
-     * Indicates whether phing should run in strict mode.
186
-     */
187
-    private $strictMode = false;
188
-    /**
189
-     * Indicates if this phing should be run.
190
-     */
191
-    private $readyToRun = false;
192
-    /**
193
-     * Indicates we should only parse and display the project help information.
194
-     */
195
-    private $projectHelp = false;
196
-    /**
197
-     * Whether to values in a property file should override existing values.
198
-     */
199
-    private $propertyFileOverride = false;
200
-    /**
201
-     * Whether or not output to the log is to be unadorned.
202
-     */
203
-    private $emacsMode = false;
204
-
205
-    /**
206
-     * @var string
207
-     */
208
-    private $searchForThis;
209
-    private $propertyFiles = [];
210
-
211
-    /**
212
-     * Gets the stream to use for standard (non-error) output.
213
-     *
214
-     * @return OutputStream
215
-     */
216
-    public static function getOutputStream()
217
-    {
218
-        return self::$out;
219
-    }
220
-
221
-    /**
222
-     * Gets the stream to use for error output.
223
-     *
224
-     * @return OutputStream
225
-     */
226
-    public static function getErrorStream()
227
-    {
228
-        return self::$err;
229
-    }
230
-
231
-    /**
232
-     * Command line entry point. This method kicks off the building
233
-     * of a project object and executes a build using either a given
234
-     * target or the default target.
235
-     *
236
-     * @param array $args command line args
237
-     * @throws Exception
238
-     */
239
-    public static function fire($args): void
240
-    {
241
-        self::start($args);
242
-    }
243
-
244
-    /**
245
-     * Entry point allowing for more options from other front ends.
246
-     *
247
-     * This method encapsulates the complete build lifecycle.
248
-     *
249
-     * @param array $args the commandline args passed to phing shell script
250
-     * @param array $additionalUserProperties Any additional properties to be passed to Phing (alternative front-end might implement this).
251
-     *                                        These additional properties will be available using the getDefinedProperty() method and will
252
-     *                                        be added to the project's "user" properties
253
-     *
254
-     * @throws Exception - if there is an error during build
255
-     * @see    runBuild()
256
-     *
257
-     * @see    execute()
258
-     */
259
-    public static function start($args, array $additionalUserProperties = null)
260
-    {
261
-        try {
262
-            $m = new self();
263
-            $m->execute($args);
264
-        } catch (Exception $exc) {
265
-            self::handleLogfile();
266
-            self::printMessage($exc);
267
-            self::statusExit(1);
268
-
269
-            return;
270
-        }
271
-
272
-        if (null !== $additionalUserProperties) {
273
-            foreach ($additionalUserProperties as $key => $value) {
274
-                $m::setDefinedProperty($key, $value);
275
-            }
276
-        }
277
-
278
-        // expect the worst
279
-        $exitCode = 1;
280
-
281
-        try {
282
-            try {
283
-                $m->runBuild();
284
-                $exitCode = 0;
285
-            } catch (ExitStatusException $ese) {
286
-                $exitCode = $ese->getCode();
287
-                if (0 !== $exitCode) {
288
-                    self::handleLogfile();
289
-
290
-                    throw $ese;
291
-                }
292
-            }
293
-        } catch (BuildException $exc) {
294
-            // avoid printing output twice: self::printMessage($exc);
295
-        } catch (Throwable $exc) {
296
-            self::printMessage($exc);
297
-        } finally {
298
-            self::handleLogfile();
299
-        }
300
-        self::statusExit($exitCode);
301
-    }
302
-
303
-    /**
304
-     * Setup/initialize Phing environment from commandline args.
305
-     *
306
-     * @param array $args commandline args passed to phing shell
307
-     *
308
-     * @throws ConfigurationException
309
-     */
310
-    public function execute($args): void
311
-    {
312
-        self::$definedProps = new Properties();
313
-        $this->searchForThis = null;
314
-
315
-        // 1) First handle any options which should always
316
-        // Note: The order in which these are executed is important (if multiple of these options are specified)
317
-
318
-        if (in_array('-help', $args) || in_array('-h', $args)) {
319
-            static::printUsage();
320
-
321
-            return;
322
-        }
323
-
324
-        if (in_array('-version', $args) || in_array('-v', $args)) {
325
-            static::printVersion();
326
-
327
-            return;
328
-        }
329
-
330
-        if (in_array('-init', $args) || in_array('-i', $args)) {
331
-            $key = array_search('-init', $args) ?: array_search('-i', $args);
332
-            $path = $args[$key + 1] ?? null;
333
-
334
-            self::init($path);
335
-
336
-            return;
337
-        }
338
-
339
-        if (in_array('-diagnostics', $args)) {
340
-            Diagnostics::doReport(new PrintStream(self::$out));
341
-
342
-            return;
343
-        }
344
-
345
-        // 2) Next pull out stand-alone args.
346
-        // Note: The order in which these are executed is important (if multiple of these options are specified)
347
-
348
-        if (
349
-            false !== ($key = array_search('-quiet', $args, true))
350
-            || false !== ($key = array_search(
351
-                '-q',
352
-                $args,
353
-                true
354
-            ))
355
-        ) {
356
-            self::$msgOutputLevel = Project::MSG_WARN;
357
-            unset($args[$key]);
358
-        }
359
-
360
-        if (
361
-            false !== ($key = array_search('-emacs', $args, true))
362
-            || false !== ($key = array_search('-e', $args, true))
363
-        ) {
364
-            $this->emacsMode = true;
365
-            unset($args[$key]);
366
-        }
367
-
368
-        if (false !== ($key = array_search('-verbose', $args, true))) {
369
-            self::$msgOutputLevel = Project::MSG_VERBOSE;
370
-            unset($args[$key]);
371
-        }
372
-
373
-        if (false !== ($key = array_search('-debug', $args, true))) {
374
-            self::$msgOutputLevel = Project::MSG_DEBUG;
375
-            unset($args[$key]);
376
-        }
377
-
378
-        if (
379
-            false !== ($key = array_search('-silent', $args, true))
380
-            || false !== ($key = array_search('-S', $args, true))
381
-        ) {
382
-            $this->silent = true;
383
-            unset($args[$key]);
384
-        }
385
-
386
-        if (false !== ($key = array_search('-propertyfileoverride', $args, true))) {
387
-            $this->propertyFileOverride = true;
388
-            unset($args[$key]);
389
-        }
390
-
391
-        // 3) Finally, cycle through to parse remaining args
392
-        //
393
-        $keys = array_keys($args); // Use keys and iterate to max(keys) since there may be some gaps
394
-        $max = $keys ? max($keys) : -1;
395
-        for ($i = 0; $i <= $max; ++$i) {
396
-            if (!array_key_exists($i, $args)) {
397
-                // skip this argument, since it must have been removed above.
398
-                continue;
399
-            }
400
-
401
-            $arg = $args[$i];
402
-
403
-            if ('-logfile' == $arg) {
404
-                try {
405
-                    // see: http://phing.info/trac/ticket/65
406
-                    if (!isset($args[$i + 1])) {
407
-                        $msg = "You must specify a log file when using the -logfile argument\n";
408
-
409
-                        throw new ConfigurationException($msg);
410
-                    }
411
-
412
-                    $logFile = new File($args[++$i]);
413
-                    $out = new FileOutputStream($logFile); // overwrite
414
-                    self::setOutputStream($out);
415
-                    self::setErrorStream($out);
416
-                    self::$isLogFileUsed = true;
417
-                } catch (IOException $ioe) {
418
-                    $msg = 'Cannot write on the specified log file. Make sure the path exists and you have write permissions.';
419
-
420
-                    throw new ConfigurationException($msg, $ioe);
421
-                }
422
-            } elseif ('-buildfile' == $arg || '-file' == $arg || '-f' == $arg) {
423
-                if (!isset($args[$i + 1])) {
424
-                    $msg = 'You must specify a buildfile when using the -buildfile argument.';
425
-
426
-                    throw new ConfigurationException($msg);
427
-                }
428
-
429
-                $this->buildFile = new File($args[++$i]);
430
-            } elseif ('-listener' == $arg) {
431
-                if (!isset($args[$i + 1])) {
432
-                    $msg = 'You must specify a listener class when using the -listener argument';
433
-
434
-                    throw new ConfigurationException($msg);
435
-                }
436
-
437
-                $this->listeners[] = $args[++$i];
438
-            } elseif (StringHelper::startsWith('-D', $arg)) {
439
-                // Evaluating the property information //
440
-                // Checking whether arg. is not just a switch, and next arg. does not starts with switch identifier
441
-                if (('-D' == $arg) && (!StringHelper::startsWith('-', $args[$i + 1]))) {
442
-                    $name = $args[++$i];
443
-                } else {
444
-                    $name = substr($arg, 2);
445
-                }
446
-
447
-                $value = null;
448
-                $posEq = strpos($name, '=');
449
-                if (false !== $posEq) {
450
-                    $value = substr($name, $posEq + 1);
451
-                    $name = substr($name, 0, $posEq);
452
-                } elseif ($i < count($args) - 1 && !StringHelper::startsWith('-D', $args[$i + 1])) {
453
-                    $value = $args[++$i];
454
-                }
455
-                self::$definedProps->setProperty($name, $value);
456
-            } elseif ('-logger' == $arg) {
457
-                if (!isset($args[$i + 1])) {
458
-                    $msg = 'You must specify a classname when using the -logger argument';
459
-
460
-                    throw new ConfigurationException($msg);
461
-                }
462
-
463
-                $this->loggerClassname = $args[++$i];
464
-            } elseif ('-no-strict' == $arg) {
465
-                $this->strictMode = false;
466
-            } elseif ('-strict' == $arg) {
467
-                $this->strictMode = true;
468
-            } elseif ('-inputhandler' == $arg) {
469
-                if (null !== $this->inputHandlerClassname) {
470
-                    throw new ConfigurationException('Only one input handler class may be specified.');
471
-                }
472
-                if (!isset($args[$i + 1])) {
473
-                    $msg = 'You must specify a classname when using the -inputhandler argument';
474
-
475
-                    throw new ConfigurationException($msg);
476
-                }
477
-
478
-                $this->inputHandlerClassname = $args[++$i];
479
-            } elseif ('-propertyfile' === $arg) {
480
-                $i = $this->handleArgPropertyFile($args, $i);
481
-            } elseif ('-keep-going' === $arg || '-k' === $arg) {
482
-                $this->keepGoingMode = true;
483
-            } elseif ('-longtargets' == $arg) {
484
-                self::$definedProps->setProperty('phing.showlongtargets', 1);
485
-            } elseif ('-projecthelp' == $arg || '-targets' == $arg || '-list' == $arg || '-l' == $arg || '-p' == $arg) {
486
-                // set the flag to display the targets and quit
487
-                $this->projectHelp = true;
488
-            } elseif ('-find' == $arg) {
489
-                // eat up next arg if present, default to build.xml
490
-                if ($i < count($args) - 1) {
491
-                    $this->searchForThis = $args[++$i];
492
-                } else {
493
-                    $this->searchForThis = self::DEFAULT_BUILD_FILENAME;
494
-                }
495
-            } elseif ('-' == substr($arg, 0, 1)) {
496
-                // we don't have any more args
497
-                self::printUsage();
498
-                self::$err->write(PHP_EOL);
499
-
500
-                throw new ConfigurationException('Unknown argument: ' . $arg);
501
-            } else {
502
-                // if it's no other arg, it may be the target
503
-                $this->targets[] = $arg;
504
-            }
505
-        }
506
-
507
-        // if buildFile was not specified on the command line,
508
-        if (null === $this->buildFile) {
509
-            // but -find then search for it
510
-            if (null !== $this->searchForThis) {
511
-                $this->buildFile = $this->findBuildFile(self::getProperty('user.dir'), $this->searchForThis);
512
-            } else {
513
-                $this->buildFile = new File(self::DEFAULT_BUILD_FILENAME);
514
-            }
515
-        }
516
-
517
-        try {
518
-            // make sure buildfile (or buildfile.dist) exists
519
-            if (!$this->buildFile->exists()) {
520
-                $distFile = new File($this->buildFile->getAbsolutePath() . '.dist');
521
-                if (!$distFile->exists()) {
522
-                    throw new ConfigurationException(
523
-                        'Buildfile: ' . $this->buildFile->__toString() . ' does not exist!'
524
-                    );
525
-                }
526
-                $this->buildFile = $distFile;
527
-            }
528
-
529
-            // make sure it's not a directory
530
-            if ($this->buildFile->isDirectory()) {
531
-                throw new ConfigurationException('Buildfile: ' . $this->buildFile->__toString() . ' is a dir!');
532
-            }
533
-        } catch (IOException $e) {
534
-            // something else happened, buildfile probably not readable
535
-            throw new ConfigurationException('Buildfile: ' . $this->buildFile->__toString() . ' is not readable!');
536
-        }
537
-
538
-        $this->loadPropertyFiles();
539
-
540
-        $this->readyToRun = true;
541
-    }
542
-
543
-    /**
544
-     * Prints the usage of how to use this class.
545
-     */
546
-    public static function printUsage()
547
-    {
548
-        $msg = '';
549
-        $msg .= 'phing [options] [target [target2 [target3] ...]]' . PHP_EOL;
550
-        $msg .= 'Options: ' . PHP_EOL;
551
-        $msg .= '  -h -help               print this message' . PHP_EOL;
552
-        $msg .= '  -l -list               list available targets in this project' . PHP_EOL;
553
-        $msg .= '  -i -init [file]        generates an initial buildfile' . PHP_EOL;
554
-        $msg .= '  -v -version            print the version information and exit' . PHP_EOL;
555
-        $msg .= '  -q -quiet              be extra quiet' . PHP_EOL;
556
-        $msg .= '  -S -silent             print nothing but task outputs and build failures' . PHP_EOL;
557
-        $msg .= '  -verbose               be extra verbose' . PHP_EOL;
558
-        $msg .= '  -debug                 print debugging information' . PHP_EOL;
559
-        $msg .= '  -emacs, -e             produce logging information without adornments' . PHP_EOL;
560
-        $msg .= '  -diagnostics           print diagnostics information' . PHP_EOL;
561
-        $msg .= '  -strict                runs build in strict mode, considering a warning as error' . PHP_EOL;
562
-        $msg .= '  -no-strict             runs build normally (overrides buildfile attribute)' . PHP_EOL;
563
-        $msg .= '  -longtargets           show target descriptions during build' . PHP_EOL;
564
-        $msg .= '  -logfile <file>        use given file for log' . PHP_EOL;
565
-        $msg .= '  -logger <classname>    the class which is to perform logging' . PHP_EOL;
566
-        $msg .= '  -listener <classname>  add an instance of class as a project listener' . PHP_EOL;
567
-        $msg .= '  -f -buildfile <file>   use given buildfile' . PHP_EOL;
568
-        $msg .= '  -D<property>=<value>   use value for given property' . PHP_EOL;
569
-        $msg .= '  -keep-going, -k        execute all targets that do not depend' . PHP_EOL;
570
-        $msg .= '                         on failed target(s)' . PHP_EOL;
571
-        $msg .= '  -propertyfile <file>   load all properties from file' . PHP_EOL;
572
-        $msg .= '  -propertyfileoverride  values in property file override existing values' . PHP_EOL;
573
-        $msg .= '  -find <file>           search for buildfile towards the root of the' . PHP_EOL;
574
-        $msg .= '                         filesystem and use it' . PHP_EOL;
575
-        $msg .= '  -inputhandler <file>   the class to use to handle user input' . PHP_EOL;
576
-        //$msg .= "  -recursive <file>      search for buildfile downwards and use it" . PHP_EOL;
577
-        $msg .= PHP_EOL;
578
-        $msg .= 'Report bugs to https://github.com/phingofficial/phing/issues' . PHP_EOL;
579
-        self::$err->write($msg);
580
-    }
581
-
582
-    /**
583
-     * Prints the current Phing version.
584
-     */
585
-    public static function printVersion()
586
-    {
587
-        self::$out->write(self::getPhingVersion() . PHP_EOL);
588
-    }
589
-
590
-    /**
591
-     * Gets the current Phing version based on VERSION.TXT file.
592
-     *
593
-     * @return string
594
-     * @throws ConfigurationException
595
-     *
596
-     */
597
-    public static function getPhingVersion(): string
598
-    {
599
-        $versionPath = self::getResourcePath('phing/etc/VERSION.TXT');
600
-        if (null === $versionPath) {
601
-            $versionPath = self::getResourcePath('etc/VERSION.TXT');
602
-        }
603
-        if (null === $versionPath) {
604
-            throw new ConfigurationException('No VERSION.TXT file found; try setting phing.home environment variable.');
605
-        }
606
-
607
-        try { // try to read file
608
-            $file = new File($versionPath);
609
-            $reader = new FileReader($file);
610
-            $phingVersion = trim($reader->read());
611
-        } catch (IOException $iox) {
612
-            throw new ConfigurationException("Can't read version information file");
613
-        }
614
-
615
-        $basePath = dirname(__DIR__, 2);
616
-
617
-        $version = new Version($phingVersion, $basePath);
618
-
619
-        return 'Phing ' . $version->getVersion();
620
-    }
621
-
622
-    /**
623
-     * Looks on include path for specified file.
624
-     *
625
-     * @param string $path
626
-     *
627
-     * @return string|null file found (null if no file found)
628
-     */
629
-    public static function getResourcePath($path): ?string
630
-    {
631
-        if (null === self::$importPaths) {
632
-            self::$importPaths = self::explodeIncludePath();
633
-        }
634
-
635
-        $path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $path);
636
-
637
-        foreach (self::$importPaths as $prefix) {
638
-            $testPath = $prefix . DIRECTORY_SEPARATOR . $path;
639
-            if (file_exists($testPath)) {
640
-                return $testPath;
641
-            }
642
-        }
643
-
644
-        // Check for the property phing.home
645
-        $homeDir = self::getProperty(self::PHING_HOME);
646
-        if ($homeDir) {
647
-            $testPath = $homeDir . DIRECTORY_SEPARATOR . $path;
648
-            if (file_exists($testPath)) {
649
-                return $testPath;
650
-            }
651
-        }
652
-
653
-        // Check for the phing home of phar archive
654
-        if (0 === strpos(self::$importPaths[0], 'phar://')) {
655
-            $testPath = self::$importPaths[0] . '/../' . $path;
656
-            if (file_exists($testPath)) {
657
-                return $testPath;
658
-            }
659
-        }
660
-
661
-        // Do one additional check based on path of current file (Phing.php)
662
-        $maybeHomeDir = realpath(__DIR__ . DIRECTORY_SEPARATOR);
663
-        $testPath = $maybeHomeDir . DIRECTORY_SEPARATOR . $path;
664
-        if (file_exists($testPath)) {
665
-            return $testPath;
666
-        }
667
-
668
-        return null;
669
-    }
670
-
671
-    /**
672
-     * Explode an include path into an array.
673
-     *
674
-     * If no path provided, uses current include_path. Works around issues that
675
-     * occur when the path includes stream schemas.
676
-     *
677
-     * Pulled from Zend_Loader::explodeIncludePath() in ZF1.
678
-     *
679
-     * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
680
-     * @license   http://framework.zend.com/license/new-bsd New BSD License
681
-     *
682
-     * @param null|string $path
683
-     *
684
-     * @return array
685
-     */
686
-    public static function explodeIncludePath($path = null)
687
-    {
688
-        if (null === $path) {
689
-            $path = get_include_path();
690
-        }
691
-
692
-        if (PATH_SEPARATOR === ':') {
693
-            // On *nix systems, include_paths which include paths with a stream
694
-            // schema cannot be safely explode'd, so we have to be a bit more
695
-            // intelligent in the approach.
696
-            $paths = preg_split('#:(?!//)#', $path);
697
-        } else {
698
-            $paths = explode(PATH_SEPARATOR, $path);
699
-        }
700
-
701
-        return $paths;
702
-    }
703
-
704
-    /**
705
-     * Returns property value for a System property.
706
-     * System properties are "global" properties like application.startdir,
707
-     * and user.dir.  Many of these correspond to similar properties in Java
708
-     * or Ant.
709
-     *
710
-     * @param string $propName
711
-     *
712
-     * @return string value of found property (or null, if none found)
713
-     */
714
-    public static function getProperty($propName)
715
-    {
716
-        // some properties are detemined on each access
717
-        // some are cached, see below
718
-
719
-        // default is the cached value:
720
-        $val = self::$properties[$propName] ?? null;
721
-
722
-        // special exceptions
723
-        switch ($propName) {
724
-            case 'user.dir':
725
-                $val = getcwd();
726
-
727
-                break;
728
-        }
729
-
730
-        return $val;
731
-    }
732
-
733
-    /**
734
-     * Creates generic buildfile.
735
-     *
736
-     * @param string $path
737
-     */
738
-    public static function init($path)
739
-    {
740
-        if ($buildfilePath = self::initPath($path)) {
741
-            self::initWrite($buildfilePath);
742
-        }
743
-    }
744
-
745
-    /**
746
-     * Returns buildfile's path.
747
-     *
748
-     * @param $path
749
-     *
750
-     * @return string
751
-     * @throws ConfigurationException
752
-     *
753
-     */
754
-    protected static function initPath($path)
755
-    {
756
-        // Fallback
757
-        if (empty($path)) {
758
-            $defaultDir = self::getProperty('application.startdir');
759
-            $path = $defaultDir . DIRECTORY_SEPARATOR . self::DEFAULT_BUILD_FILENAME;
760
-        }
761
-
762
-        // Adding filename if necessary
763
-        if (is_dir($path)) {
764
-            $path .= DIRECTORY_SEPARATOR . self::DEFAULT_BUILD_FILENAME;
765
-        }
766
-
767
-        // Check if path is available
768
-        $dirname = dirname($path);
769
-        if (is_dir($dirname) && !is_file($path)) {
770
-            return $path;
771
-        }
772
-
773
-        // Path is valid, but buildfile already exists
774
-        if (is_file($path)) {
775
-            throw new ConfigurationException('Buildfile already exists.');
776
-        }
777
-
778
-        throw new ConfigurationException('Invalid path for sample buildfile.');
779
-    }
780
-
781
-    /**
782
-     * Writes sample buildfile.
783
-     *
784
-     * If $buildfilePath does not exist, the buildfile is created.
785
-     *
786
-     * @param $buildfilePath buildfile's location
787
-     *
788
-     * @throws ConfigurationException
789
-     */
790
-    protected static function initWrite($buildfilePath): void
791
-    {
792
-        // Overwriting protection
793
-        if (file_exists($buildfilePath)) {
794
-            throw new ConfigurationException('Cannot overwrite existing file.');
795
-        }
796
-
797
-        file_put_contents($buildfilePath, self::DEFAULT_BUILD_CONTENT);
798
-    }
799
-
800
-    /**
801
-     * Sets the stream to use for standard (non-error) output.
802
-     *
803
-     * @param OutputStream $stream the stream to use for standard output
804
-     */
805
-    public static function setOutputStream(OutputStream $stream)
806
-    {
807
-        self::$out = $stream;
808
-    }
809
-
810
-    /**
811
-     * Sets the stream to use for error output.
812
-     *
813
-     * @param OutputStream $stream the stream to use for error output
814
-     */
815
-    public static function setErrorStream(OutputStream $stream): void
816
-    {
817
-        self::$err = $stream;
818
-    }
819
-
820
-    /**
821
-     * Handle the -propertyfile argument.
822
-     *
823
-     * @throws ConfigurationException
824
-     * @throws IOException
825
-     */
826
-    private function handleArgPropertyFile(array $args, int $pos): int
827
-    {
828
-        if (!isset($args[$pos + 1])) {
829
-            throw new ConfigurationException('You must specify a filename when using the -propertyfile argument');
830
-        }
831
-
832
-        $this->propertyFiles[] = $args[++$pos];
833
-
834
-        return $pos;
835
-    }
836
-
837
-    /**
838
-     * Search parent directories for the build file.
839
-     *
840
-     * Takes the given target as a suffix to append to each
841
-     * parent directory in search of a build file.  Once the
842
-     * root of the file-system has been reached an exception
843
-     * is thrown.
844
-     *
845
-     * @param string $start start file path
846
-     * @param string $suffix suffix filename to look for in parents
847
-     *
848
-     * @return File A handle to the build file
849
-     * @throws ConfigurationException
850
-     *
851
-     */
852
-    private function findBuildFile($start, $suffix)
853
-    {
854
-        if (self::getMsgOutputLevel() >= Project::MSG_INFO) {
855
-            self::$out->write('Searching for ' . $suffix . ' ...' . PHP_EOL);
856
-        }
857
-
858
-        $parent = new File((new File($start))->getAbsolutePath());
859
-        $file = new File($parent, $suffix);
860
-
861
-        // check if the target file exists in the current directory
862
-        while (!$file->exists()) {
863
-            // change to parent directory
864
-            $parent = $parent->getParentFile();
865
-
866
-            // if parent is null, then we are at the root of the fs,
867
-            // complain that we can't find the build file.
868
-            if (null === $parent) {
869
-                throw new ConfigurationException('Could not locate a build file!');
870
-            }
871
-            // refresh our file handle
872
-            $file = new File($parent, $suffix);
873
-        }
874
-
875
-        return $file;
876
-    }
877
-
878
-    /**
879
-     * Making output level a static property so that this property
880
-     * can be accessed by other parts of the system, enabling
881
-     * us to display more information -- e.g. backtraces -- for "debug" level.
882
-     *
883
-     * @return int
884
-     */
885
-    public static function getMsgOutputLevel()
886
-    {
887
-        return self::$msgOutputLevel;
888
-    }
889
-
890
-    /**
891
-     * @throws IOException
892
-     */
893
-    private function loadPropertyFiles(): void
894
-    {
895
-        foreach ($this->propertyFiles as $filename) {
896
-            $fileParserFactory = new FileParserFactory();
897
-            $fileParser = $fileParserFactory->createParser(pathinfo($filename, PATHINFO_EXTENSION));
898
-            $p = new Properties(null, $fileParser);
899
-
900
-            try {
901
-                $p->load(new File($filename));
902
-            } catch (IOException $e) {
903
-                self::$out->write('Could not load property file ' . $filename . ': ' . $e->getMessage());
904
-            }
905
-            foreach ($p->getProperties() as $prop => $value) {
906
-                self::$definedProps->setProperty($prop, $value);
907
-            }
908
-        }
909
-    }
910
-
911
-    /**
912
-     * Close logfiles, if we have been writing to them.
913
-     *
914
-     * @since Phing 2.3.0
915
-     */
916
-    private static function handleLogfile(): void
917
-    {
918
-        if (self::$isLogFileUsed) {
919
-            self::$err->close();
920
-            self::$out->close();
921
-        }
922
-    }
923
-
924
-    /**
925
-     * Prints the message of the Exception if it's not null.
926
-     */
927
-    public static function printMessage(Throwable $t): void
928
-    {
929
-        if (null === self::$err) { // Make sure our error output is initialized
930
-            self::initializeOutputStreams();
931
-        }
932
-        if (self::getMsgOutputLevel() >= Project::MSG_VERBOSE) {
933
-            self::$err->write((string) $t . PHP_EOL);
934
-        } else {
935
-            self::$err->write($t->getMessage() . PHP_EOL);
936
-        }
937
-    }
938
-
939
-    /**
940
-     * Sets the stdout and stderr streams if they are not already set.
941
-     */
942
-    private static function initializeOutputStreams()
943
-    {
944
-        if (null === self::$out) {
945
-            if (!defined('STDOUT')) {
946
-                self::$out = new OutputStream(fopen('php://stdout', 'w'));
947
-            } else {
948
-                self::$out = new OutputStream(STDOUT);
949
-            }
950
-        }
951
-        if (null === self::$err) {
952
-            if (!defined('STDERR')) {
953
-                self::$err = new OutputStream(fopen('php://stderr', 'w'));
954
-            } else {
955
-                self::$err = new OutputStream(STDERR);
956
-            }
957
-        }
958
-    }
959
-
960
-    /**
961
-     * This operation is expected to call `exit($int)`, which
962
-     * is what the base version does.
963
-     * However, it is possible to do something else.
964
-     *
965
-     * @param int $exitCode code to exit with
966
-     */
967
-    protected static function statusExit($exitCode): void
968
-    {
969
-        Phing::shutdown();
970
-
971
-        exit($exitCode);
972
-    }
973
-
974
-    /**
975
-     * Performs any shutdown routines, such as stopping timers.
976
-     *
977
-     * @throws IOException
978
-     */
979
-    public static function shutdown(): void
980
-    {
981
-        FileSystem::getFileSystem()::deleteFilesOnExit();
982
-        self::$msgOutputLevel = Project::MSG_INFO;
983
-        self::restoreIni();
984
-        self::getTimer()->stop();
985
-    }
986
-
987
-    /**
988
-     * Restores [most] PHP INI values to their pre-Phing state.
989
-     *
990
-     * Currently the following settings are not restored:
991
-     *  - max_execution_time (because getting current time limit is not possible)
992
-     *  - memory_limit (which may have been increased by Phing)
993
-     */
994
-    private static function restoreIni(): void
995
-    {
996
-        foreach (self::$origIniSettings as $settingName => $settingValue) {
997
-            switch ($settingName) {
998
-                case 'error_reporting':
999
-                    error_reporting($settingValue);
1000
-
1001
-                    break;
1002
-
1003
-                default:
1004
-                    ini_set($settingName, $settingValue);
1005
-            }
1006
-        }
1007
-    }
1008
-
1009
-    /**
1010
-     * Returns reference to DefaultClock object.
1011
-     */
1012
-    public static function getTimer(): DefaultClock
1013
-    {
1014
-        if (null === self::$timer) {
1015
-            self::$timer = new DefaultClock();
1016
-        }
1017
-
1018
-        return self::$timer;
1019
-    }
1020
-
1021
-    /**
1022
-     * This sets a property that was set via command line or otherwise passed into Phing.
1023
-     *
1024
-     * @param string $name
1025
-     * @param mixed $value
1026
-     *
1027
-     * @return mixed value of found property (or null, if none found)
1028
-     */
1029
-    public static function setDefinedProperty($name, $value)
1030
-    {
1031
-        return self::$definedProps->setProperty($name, $value);
1032
-    }
1033
-
1034
-    /**
1035
-     * Executes the build.
1036
-     *
1037
-     * @throws IOException
1038
-     * @throws Throwable
1039
-     */
1040
-    public function runBuild(): void
1041
-    {
1042
-        if (!$this->readyToRun) {
1043
-            return;
1044
-        }
1045
-
1046
-        $project = new Project();
1047
-
1048
-        self::setCurrentProject($project);
1049
-        set_error_handler(['Phing\Phing', 'handlePhpError']);
1050
-
1051
-        $error = null;
1052
-
1053
-        try {
1054
-            $this->addBuildListeners($project);
1055
-            $this->addInputHandler($project);
1056
-
1057
-            // set this right away, so that it can be used in logging.
1058
-            $project->setUserProperty('phing.file', $this->buildFile->getAbsolutePath());
1059
-            $project->setUserProperty('phing.dir', dirname($this->buildFile->getAbsolutePath()));
1060
-            $project->setUserProperty('phing.version', static::getPhingVersion());
1061
-            $project->fireBuildStarted();
1062
-            $project->init();
1063
-            $project->setKeepGoingMode($this->keepGoingMode);
1064
-
1065
-            $e = self::$definedProps->keys();
1066
-            while (count($e)) {
1067
-                $arg = (string) array_shift($e);
1068
-                $value = (string) self::$definedProps->getProperty($arg);
1069
-                $project->setUserProperty($arg, $value);
1070
-            }
1071
-            unset($e);
1072
-
1073
-            // first use the Configurator to create the project object
1074
-            // from the given build file.
1075
-
1076
-            ProjectConfigurator::configureProject($project, $this->buildFile);
1077
-
1078
-            // Set the project mode
1079
-            $project->setStrictMode(StringHelper::booleanValue($this->strictMode));
1080
-
1081
-            // make sure that minimum required phing version is satisfied
1082
-            $this->comparePhingVersion($project->getPhingVersion());
1083
-
1084
-            if ($this->projectHelp) {
1085
-                $this->printDescription($project);
1086
-                $this->printTargets($project);
1087
-
1088
-                return;
1089
-            }
1090
-
1091
-            // make sure that we have a target to execute
1092
-            if (0 === count($this->targets)) {
1093
-                $this->targets[] = $project->getDefaultTarget();
1094
-            }
1095
-
1096
-            $project->executeTargets($this->targets);
1097
-        } catch (Throwable $t) {
1098
-            $error = $t;
1099
-
1100
-            throw $t;
1101
-        } finally {
1102
-            if (!$this->projectHelp) {
1103
-                try {
1104
-                    $project->fireBuildFinished($error);
1105
-                } catch (Exception $e) {
1106
-                    self::$err->write('Caught an exception while logging the end of the build.  Exception was:' . PHP_EOL);
1107
-                    self::$err->write($e->getTraceAsString());
1108
-                    if (null !== $error) {
1109
-                        self::$err->write('There has been an error prior to that:' . PHP_EOL);
1110
-                        self::$err->write($error->getTraceAsString());
1111
-                    }
1112
-
1113
-                    throw new BuildException($error);
1114
-                }
1115
-            } elseif (null !== $error) {
1116
-                $project->log($error->getMessage(), Project::MSG_ERR);
1117
-            }
1118
-
1119
-            restore_error_handler();
1120
-            self::unsetCurrentProject();
1121
-        }
1122
-    }
1123
-
1124
-    /**
1125
-     * Bind any registered build listeners to this project.
1126
-     *
1127
-     * This means adding the logger and any build listeners that were specified
1128
-     * with -listener arg.
1129
-     *
1130
-     * @throws BuildException
1131
-     * @throws ConfigurationException
1132
-     */
1133
-    private function addBuildListeners(Project $project)
1134
-    {
1135
-        // Add the default listener
1136
-        $project->addBuildListener($this->createLogger());
1137
-
1138
-        foreach ($this->listeners as $listenerClassname) {
1139
-            try {
1140
-                $clz = Phing::import($listenerClassname);
1141
-            } catch (Exception $e) {
1142
-                $msg = 'Unable to instantiate specified listener '
1143
-                    . 'class ' . $listenerClassname . ' : '
1144
-                    . $e->getMessage();
1145
-
1146
-                throw new ConfigurationException($msg);
1147
-            }
1148
-
1149
-            $listener = new $clz();
1150
-
1151
-            if ($listener instanceof StreamRequiredBuildLogger) {
1152
-                throw new ConfigurationException('Unable to add ' . $listenerClassname . ' as a listener, since it requires explicit error/output streams. (You can specify it as a -logger.)');
1153
-            }
1154
-            $project->addBuildListener($listener);
1155
-        }
1156
-    }
1157
-
1158
-    /**
1159
-     * Creates the default build logger for sending build events to the log.
1160
-     *
1161
-     * @return BuildLogger The created Logger
1162
-     * @throws BuildException
1163
-     *
1164
-     */
1165
-    private function createLogger()
1166
-    {
1167
-        if ($this->silent) {
1168
-            $logger = new SilentLogger();
1169
-            self::$msgOutputLevel = Project::MSG_WARN;
1170
-        } elseif (null !== $this->loggerClassname) {
1171
-            self::import($this->loggerClassname);
1172
-            // get class name part
1173
-            $classname = self::import($this->loggerClassname);
1174
-            $logger = new $classname();
1175
-            if (!($logger instanceof BuildLogger)) {
1176
-                throw new BuildException($classname . ' does not implement the BuildLogger interface.');
1177
-            }
1178
-        } else {
1179
-            $logger = new DefaultLogger();
1180
-        }
1181
-        $logger->setMessageOutputLevel(self::$msgOutputLevel);
1182
-        $logger->setOutputStream(self::$out);
1183
-        $logger->setErrorStream(self::$err);
1184
-        $logger->setEmacsMode($this->emacsMode);
1185
-
1186
-        return $logger;
1187
-    }
1188
-
1189
-    /**
1190
-     * Import a class, supporting the following conventions:
1191
-     * - PEAR style (@see http://pear.php.net/manual/en/standards.naming.php)
1192
-     * - PSR-0 (@see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md).
1193
-     *
1194
-     * @param string $classname Name of class
1195
-     * @param mixed $classpath String or object supporting __toString()
1196
-     *
1197
-     * @throws BuildException - if cannot find the specified file
1198
-     *
1199
-     * @return string the unqualified classname (which can be instantiated)
1200
-     */
1201
-    public static function import($classname, $classpath = null)
1202
-    {
1203
-        // first check to see that the class specified hasn't already been included.
1204
-        if (class_exists($classname)) {
1205
-            return $classname;
1206
-        }
1207
-
1208
-        $filename = strtr($classname, ['_' => DIRECTORY_SEPARATOR, '\\' => DIRECTORY_SEPARATOR]) . '.php';
1209
-
1210
-        Phing::importFile($filename, $classpath);
1211
-
1212
-        return $classname;
1213
-    }
1214
-
1215
-    /**
1216
-     * Import a PHP file.
1217
-     *
1218
-     * This used to be named __import, however PHP has reserved all method names
1219
-     * with a double underscore prefix for future use.
1220
-     *
1221
-     * @param string $path Path to the PHP file
1222
-     * @param mixed $classpath String or object supporting __toString()
1223
-     *
1224
-     * @throws ConfigurationException
1225
-     */
1226
-    public static function importFile($path, $classpath = null)
1227
-    {
1228
-        if ($classpath) {
1229
-            // Apparently casting to (string) no longer invokes __toString() automatically.
1230
-            if (is_object($classpath)) {
1231
-                $classpath = $classpath->__toString();
1232
-            }
1233
-
1234
-            // classpaths are currently additive, but we also don't want to just
1235
-            // indiscriminantly prepand/append stuff to the include_path.  This means
1236
-            // we need to parse current incldue_path, and prepend any
1237
-            // specified classpath locations that are not already in the include_path.
1238
-            //
1239
-            // NOTE:  the reason why we do it this way instead of just changing include_path
1240
-            // and then changing it back, is that in many cases applications (e.g. Propel) will
1241
-            // include/require class files from within method calls.  This means that not all
1242
-            // necessary files will be included in this import() call, and hence we can't
1243
-            // change the include_path back without breaking those apps.  While this method could
1244
-            // be more expensive than switching & switching back (not sure, but maybe), it makes it
1245
-            // possible to write far less expensive run-time applications (e.g. using Propel), which is
1246
-            // really where speed matters more.
1247
-
1248
-            $curr_parts = Phing::explodeIncludePath();
1249
-            $add_parts = Phing::explodeIncludePath($classpath);
1250
-            $new_parts = array_diff($add_parts, $curr_parts);
1251
-            if ($new_parts) {
1252
-                set_include_path(implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts)));
1253
-            }
1254
-        }
1255
-
1256
-        $ret = include_once $path;
1257
-
1258
-        if (false === $ret) {
1259
-            $msg = "Error importing {$path}";
1260
-            if (self::getMsgOutputLevel() >= Project::MSG_DEBUG) {
1261
-                $x = new Exception('for-path-trace-only');
1262
-                $msg .= $x->getTraceAsString();
1263
-            }
1264
-
1265
-            throw new ConfigurationException($msg);
1266
-        }
1267
-    }
1268
-
1269
-    /**
1270
-     * Creates the InputHandler and adds it to the project.
1271
-     *
1272
-     * @param Project $project the project instance
1273
-     *
1274
-     * @throws ConfigurationException
1275
-     */
1276
-    private function addInputHandler(Project $project): void
1277
-    {
1278
-        if (null === $this->inputHandlerClassname) {
1279
-            $handler = new ConsoleInputHandler(STDIN, new ConsoleOutput());
1280
-        } else {
1281
-            try {
1282
-                $clz = Phing::import($this->inputHandlerClassname);
1283
-                $handler = new $clz();
1284
-                if (null !== $project && method_exists($handler, 'setProject')) {
1285
-                    $handler->setProject($project);
1286
-                }
1287
-            } catch (Exception $e) {
1288
-                $msg = 'Unable to instantiate specified input handler '
1289
-                    . 'class ' . $this->inputHandlerClassname . ' : '
1290
-                    . $e->getMessage();
1291
-
1292
-                throw new ConfigurationException($msg);
1293
-            }
1294
-        }
1295
-        $project->setInputHandler($handler);
1296
-    }
1297
-
1298
-    /**
1299
-     * @param string $version
1300
-     *
1301
-     * @throws BuildException
1302
-     * @throws ConfigurationException
1303
-     */
1304
-    private function comparePhingVersion($version): void
1305
-    {
1306
-        $current = strtolower(self::getPhingVersion());
1307
-        $current = trim(str_replace('phing', '', $current));
1308
-
1309
-        // make sure that version checks are not applied to trunk
1310
-        if ('dev' === $current) {
1311
-            return;
1312
-        }
1313
-
1314
-        if (-1 == version_compare($current, $version)) {
1315
-            throw new BuildException(
1316
-                sprintf('Incompatible Phing version (%s). Version "%s" required.', $current, $version)
1317
-            );
1318
-        }
1319
-    }
1320
-
1321
-    /**
1322
-     * Print the project description, if any.
1323
-     *
1324
-     * @throws IOException
1325
-     */
1326
-    public function printDescription(Project $project): void
1327
-    {
1328
-        if (null !== $project->getDescription()) {
1329
-            $project->log($project->getDescription());
1330
-        }
1331
-    }
1332
-
1333
-    /**
1334
-     * Print out a list of all targets in the current buildfile.
1335
-     */
1336
-    public function printTargets(Project $project)
1337
-    {
1338
-        $visibleTargets = array_filter($project->getTargets(), function (Target $target) {
1339
-            return !$target->isHidden() && !empty($target->getName());
1340
-        });
1341
-        $padding = array_reduce($visibleTargets, function (int $carry, Target $target) {
1342
-            return max(strlen($target->getName()), $carry);
1343
-        }, 0);
1344
-        $categories = [
1345
-            'Default target:' => array_filter($visibleTargets, function (Target $target) use ($project) {
1346
-                return trim(strval($target)) === $project->getDefaultTarget();
1347
-            }),
1348
-            'Main targets:' => array_filter($visibleTargets, function (Target $target) {
1349
-                return !empty($target->getDescription());
1350
-            }),
1351
-            'Subtargets:' => array_filter($visibleTargets, function (Target $target) {
1352
-                return empty($target->getDescription());
1353
-            }),
1354
-        ];
1355
-        foreach ($categories as $title => $targets) {
1356
-            $targetList = $this->generateTargetList($title, $targets, $padding);
1357
-            $project->log($targetList, Project::MSG_WARN);
1358
-        }
1359
-    }
1360
-
1361
-    /**
1362
-     * Returns a formatted list of target names with an optional description.
1363
-     *
1364
-     * @param string $title Title for this list
1365
-     * @param Target[] $targets Targets in this list
1366
-     * @param int $padding Padding for name column
1367
-     */
1368
-    private function generateTargetList(string $title, array $targets, int $padding): string
1369
-    {
1370
-        usort($targets, function (Target $a, Target $b) {
1371
-            return $a->getName() <=> $b->getName();
1372
-        });
1373
-
1374
-        $header = <<<HEADER
1375
-            {$title}
1376
-            -------------------------------------------------------------------------------
1377
-
1378
-            HEADER;
1379
-
1380
-        $getDetails = function (Target $target) use ($padding): string {
1381
-            $details = [];
1382
-            if (!empty($target->getDescription())) {
1383
-                $details[] = $target->getDescription();
1384
-            }
1385
-            if (!empty($target->getDependencies())) {
1386
-                $details[] = ' - depends on: ' . implode(', ', $target->getDependencies());
1387
-            }
1388
-            if (!empty($target->getIf())) {
1389
-                $details[] = ' - if property: ' . $target->getIf();
1390
-            }
1391
-            if (!empty($target->getUnless())) {
1392
-                $details[] = ' - unless property: ' . $target->getUnless();
1393
-            }
1394
-            $detailsToString = function (?string $name, ?string $detail) use ($padding): string {
1395
-                return sprintf(" %-{$padding}s  %s", $name, $detail);
1396
-            };
1397
-
1398
-            return implode(PHP_EOL, array_map($detailsToString, [$target->getName()], $details));
1399
-        };
1400
-
1401
-        return $header . implode(PHP_EOL, array_map($getDetails, $targets)) . PHP_EOL;
1402
-    }
1403
-
1404
-    /**
1405
-     * Unsets the current Project.
1406
-     */
1407
-    public static function unsetCurrentProject(): void
1408
-    {
1409
-        self::$currentProject = null;
1410
-    }
1411
-
1412
-    /**
1413
-     * Error handler for PHP errors encountered during the build.
1414
-     * This uses the logging for the currently configured project.
1415
-     *
1416
-     * @param $level
1417
-     * @param string $message
1418
-     * @param $file
1419
-     * @param $line
1420
-     */
1421
-    public static function handlePhpError($level, $message, $file, $line)
1422
-    {
1423
-        // don't want to print suppressed errors
1424
-        if (error_reporting() > 0) {
1425
-            if (self::$phpErrorCapture) {
1426
-                self::$capturedPhpErrors[] = [
1427
-                    'message' => $message,
1428
-                    'level' => $level,
1429
-                    'line' => $line,
1430
-                    'file' => $file,
1431
-                ];
1432
-            } else {
1433
-                $message = '[PHP Error] ' . $message;
1434
-                $message .= ' [line ' . $line . ' of ' . $file . ']';
1435
-
1436
-                switch ($level) {
1437
-                    case E_USER_DEPRECATED:
1438
-                    case E_DEPRECATED:
1439
-                    case E_STRICT:
1440
-                    case E_NOTICE:
1441
-                    case E_USER_NOTICE:
1442
-                        self::log($message, Project::MSG_VERBOSE);
1443
-
1444
-                        break;
1445
-
1446
-                    case E_WARNING:
1447
-                    case E_USER_WARNING:
1448
-                        self::log($message, Project::MSG_WARN);
1449
-
1450
-                        break;
1451
-
1452
-                    case E_ERROR:
1453
-                    case E_USER_ERROR:
1454
-                    default:
1455
-                        self::log($message, Project::MSG_ERR);
1456
-                } // switch
1457
-            } // if phpErrorCapture
1458
-        } // if not @
1459
-    }
1460
-
1461
-    /**
1462
-     * A static convenience method to send a log to the current (last-setup) Project.
1463
-     * If there is no currently-configured Project, then this will do nothing.
1464
-     *
1465
-     * @param string $message
1466
-     * @param int $priority project::MSG_INFO, etc
1467
-     */
1468
-    public static function log($message, $priority = Project::MSG_INFO): void
1469
-    {
1470
-        $p = self::getCurrentProject();
1471
-        if ($p) {
1472
-            $p->log($message, $priority);
1473
-        }
1474
-    }
1475
-
1476
-    /**
1477
-     * Gets the current Project.
1478
-     *
1479
-     * @return Project current Project or NULL if none is set yet/still
1480
-     */
1481
-    public static function getCurrentProject()
1482
-    {
1483
-        return self::$currentProject;
1484
-    }
1485
-
1486
-    /**
1487
-     * Sets the current Project.
1488
-     *
1489
-     * @param Project $p
1490
-     */
1491
-    public static function setCurrentProject($p): void
1492
-    {
1493
-        self::$currentProject = $p;
1494
-    }
1495
-
1496
-    /**
1497
-     * Begins capturing PHP errors to a buffer.
1498
-     * While errors are being captured, they are not logged.
1499
-     */
1500
-    public static function startPhpErrorCapture(): void
1501
-    {
1502
-        self::$phpErrorCapture = true;
1503
-        self::$capturedPhpErrors = [];
1504
-    }
1505
-
1506
-    /**
1507
-     * Stops capturing PHP errors to a buffer.
1508
-     * The errors will once again be logged after calling this method.
1509
-     */
1510
-    public static function stopPhpErrorCapture(): void
1511
-    {
1512
-        self::$phpErrorCapture = false;
1513
-    }
1514
-
1515
-    /**
1516
-     * Clears the captured errors without affecting the starting/stopping of the capture.
1517
-     */
1518
-    public static function clearCapturedPhpErrors(): void
1519
-    {
1520
-        self::$capturedPhpErrors = [];
1521
-    }
1522
-
1523
-    /**
1524
-     * Gets any PHP errors that were captured to buffer.
1525
-     *
1526
-     * @return array array('message' => message, 'line' => line number, 'file' => file name, 'level' => error level)
1527
-     */
1528
-    public static function getCapturedPhpErrors()
1529
-    {
1530
-        return self::$capturedPhpErrors;
1531
-    }
1532
-
1533
-    /**
1534
-     * This gets a property that was set via command line or otherwise passed into Phing.
1535
-     * "Defined" in this case means "externally defined".  The reason this method exists is to
1536
-     * provide a public means of accessing commandline properties for (e.g.) logger or listener
1537
-     * scripts.  E.g. to specify which logfile to use, PearLogger needs to be able to access
1538
-     * the pear.log.name property.
1539
-     *
1540
-     * @param string $name
1541
-     *
1542
-     * @return string value of found property (or null, if none found)
1543
-     */
1544
-    public static function getDefinedProperty($name)
1545
-    {
1546
-        return self::$definedProps->getProperty($name);
1547
-    }
1548
-
1549
-    /**
1550
-     * Retuns reference to all properties.
1551
-     */
1552
-    public static function &getProperties()
1553
-    {
1554
-        return self::$properties;
1555
-    }
1556
-
1557
-    /**
1558
-     * Start up Phing.
1559
-     * Sets up the Phing environment but does not initiate the build process.
1560
-     *
1561
-     * @throws exception - If the Phing environment cannot be initialized
1562
-     */
1563
-    public static function startup(): void
1564
-    {
1565
-        // setup STDOUT and STDERR defaults
1566
-        self::initializeOutputStreams();
1567
-
1568
-        // some init stuff
1569
-        self::getTimer()->start();
1570
-
1571
-        self::setSystemConstants();
1572
-        self::setIncludePaths();
1573
-        self::setIni();
1574
-    }
1575
-
1576
-    /**
1577
-     * Set System constants which can be retrieved by calling Phing::getProperty($propName).
1578
-     */
1579
-    private static function setSystemConstants(): void
1580
-    {
1581
-        /*
1582
-         * PHP_OS returns on
1583
-         *   WindowsNT4.0sp6  => WINNT
1584
-         *   Windows2000      => WINNT
1585
-         *   Windows ME       => WIN32
1586
-         *   Windows 98SE     => WIN32
1587
-         *   FreeBSD 4.5p7    => FreeBSD
1588
-         *   Redhat Linux     => Linux
1589
-         *   Mac OS X         => Darwin
1590
-         */
1591
-        self::setProperty('host.os', PHP_OS);
1592
-
1593
-        // this is used by some tasks too
1594
-        self::setProperty('os.name', PHP_OS);
1595
-
1596
-        // it's still possible this won't be defined,
1597
-        // e.g. if Phing is being included in another app w/o
1598
-        // using the phing.php script.
1599
-        if (!defined('PHP_CLASSPATH')) {
1600
-            define('PHP_CLASSPATH', get_include_path());
1601
-        }
1602
-
1603
-        self::setProperty('php.classpath', PHP_CLASSPATH);
1604
-
1605
-        // try to determine the host filesystem and set system property
1606
-        // used by Fileself::getFileSystem to instantiate the correct
1607
-        // abstraction layer
1608
-
1609
-        if (PHP_OS_FAMILY === 'Windows') {
1610
-            self::setProperty('host.fstype', 'WINDOWS');
1611
-            self::setProperty('user.home', getenv('HOMEDRIVE') . getenv('HOMEPATH'));
1612
-        } else {
1613
-            self::setProperty('host.fstype', 'UNIX');
1614
-            self::setProperty('user.home', getenv('HOME'));
1615
-        }
1616
-        self::setProperty(self::PHP_INTERPRETER, PHP_BINARY);
1617
-        self::setProperty('file.separator', FileUtils::getSeparator());
1618
-        self::setProperty('line.separator', PHP_EOL);
1619
-        self::setProperty('path.separator', FileUtils::getPathSeparator());
1620
-        self::setProperty(self::PHP_VERSION, PHP_VERSION);
1621
-        self::setProperty('php.tmpdir', sys_get_temp_dir());
1622
-        self::setProperty('application.startdir', getcwd());
1623
-        self::setProperty('phing.startTime', gmdate('D, d M Y H:i:s', time()) . ' GMT');
1624
-
1625
-        // try to detect machine dependent information
1626
-        $sysInfo = [];
1627
-        if (function_exists('posix_uname') && 0 !== stripos(PHP_OS, 'WIN')) {
1628
-            $sysInfo = posix_uname();
1629
-        } else {
1630
-            $sysInfo['nodename'] = php_uname('n');
1631
-            $sysInfo['machine'] = php_uname('m');
1632
-            //this is a not so ideal substition, but maybe better than nothing
1633
-            $sysInfo['domain'] = $_SERVER['SERVER_NAME'] ?? 'unknown';
1634
-            $sysInfo['release'] = php_uname('r');
1635
-            $sysInfo['version'] = php_uname('v');
1636
-        }
1637
-
1638
-        self::setProperty('host.name', $sysInfo['nodename'] ?? 'unknown');
1639
-        self::setProperty('host.arch', $sysInfo['machine'] ?? 'unknown');
1640
-        self::setProperty('host.domain', $sysInfo['domain'] ?? 'unknown');
1641
-        self::setProperty('host.os.release', $sysInfo['release'] ?? 'unknown');
1642
-        self::setProperty('host.os.version', $sysInfo['version'] ?? 'unknown');
1643
-        unset($sysInfo);
1644
-    }
1645
-
1646
-    /**
1647
-     * @param $propName
1648
-     * @param $propValue
1649
-     *
1650
-     * @return string
1651
-     */
1652
-    public static function setProperty($propName, $propValue)
1653
-    {
1654
-        $propName = (string) $propName;
1655
-        $oldValue = self::getProperty($propName);
1656
-        self::$properties[$propName] = $propValue;
1657
-
1658
-        return $oldValue;
1659
-    }
1660
-
1661
-    /**
1662
-     * Sets the include path to PHP_CLASSPATH constant (if this has been defined).
1663
-     *
1664
-     * @throws ConfigurationException - if the include_path could not be set (for some bizarre reason)
1665
-     */
1666
-    private static function setIncludePaths(): void
1667
-    {
1668
-        if (defined('PHP_CLASSPATH')) {
1669
-            $result = set_include_path(PHP_CLASSPATH);
1670
-            if (false === $result) {
1671
-                throw new ConfigurationException('Could not set PHP include_path.');
1672
-            }
1673
-            self::$origIniSettings['include_path'] = $result; // save original value for setting back later
1674
-        }
1675
-    }
1676
-
1677
-    /**
1678
-     * Sets PHP INI values that Phing needs.
1679
-     */
1680
-    private static function setIni(): void
1681
-    {
1682
-        self::$origIniSettings['error_reporting'] = error_reporting(E_ALL);
1683
-
1684
-        // We won't bother storing original max_execution_time, since 1) the value in
1685
-        // php.ini may be wrong (and there's no way to get the current value) and
1686
-        // 2) it would mean something very strange to set it to a value less than time script
1687
-        // has already been running, which would be the likely change.
1688
-
1689
-        set_time_limit(0);
1690
-
1691
-        self::$origIniSettings['short_open_tag'] = ini_set('short_open_tag', 'off');
1692
-        self::$origIniSettings['default_charset'] = ini_set('default_charset', 'iso-8859-1');
1693
-
1694
-        $mem_limit = (int) SizeHelper::fromHumanToBytes(ini_get('memory_limit'));
1695
-        if ($mem_limit < (32 * 1024 * 1024) && $mem_limit > -1) {
1696
-            // We do *not* need to save the original value here, since we don't plan to restore
1697
-            // this after shutdown (we don't trust the effectiveness of PHP's garbage collection).
1698
-            ini_set('memory_limit', '32M'); // nore: this may need to be higher for many projects
1699
-        }
1700
-    }
1701
-}
Please login to merge, or discard this patch.
Braces   -1616 removed lines patch added patch discarded remove patch
@@ -83,1619 +83,3 @@
 block discarded – undo
83 83
      */
84 84
     public const DEFAULT_BUILD_FILENAME = 'build.xml';
85 85
     public const DEFAULT_BUILD_CONTENT = <<<'XML'
86
-        <?xml version="1.0" encoding="UTF-8" ?>
87
-
88
-        <project name="" description="" default="">
89
-            
90
-            <target name="" description="">
91
-                
92
-            </target>
93
-            
94
-        </project>
95
-        XML;
96
-    public const PHING_HOME = 'phing.home';
97
-    public const PHP_VERSION = 'php.version';
98
-    public const PHP_INTERPRETER = 'php.interpreter';
99
-
100
-    /**
101
-     * Our current message output status. Follows Project::MSG_XXX.
102
-     */
103
-    private static $msgOutputLevel = Project::MSG_INFO;
104
-    /**
105
-     * Set of properties that are passed in from commandline or invoking code.
106
-     *
107
-     * @var Properties
108
-     */
109
-    private static $definedProps;
110
-    /**
111
-     * Used by utility function getResourcePath().
112
-     */
113
-    private static $importPaths;
114
-    /**
115
-     * System-wide static properties (moved from System).
116
-     */
117
-    private static $properties = [];
118
-    /**
119
-     * Static system timer.
120
-     */
121
-    private static $timer;
122
-    /**
123
-     * The current Project.
124
-     */
125
-    private static $currentProject;
126
-    /**
127
-     * Whether to capture PHP errors to buffer.
128
-     */
129
-    private static $phpErrorCapture = false;
130
-    /**
131
-     * Array of captured PHP errors.
132
-     */
133
-    private static $capturedPhpErrors = [];
134
-    /**
135
-     * @var OUtputStream stream for standard output
136
-     */
137
-    private static $out;
138
-    /**
139
-     * @var OutputStream stream for error output
140
-     */
141
-    private static $err;
142
-    /**
143
-     * @var bool whether we are using a logfile
144
-     */
145
-    private static $isLogFileUsed = false;
146
-    /**
147
-     * Array to hold original ini settings that Phing changes (and needs
148
-     * to restore in restoreIni() method).
149
-     *
150
-     * @var array Struct of array(setting-name => setting-value)
151
-     *
152
-     * @see restoreIni()
153
-     */
154
-    private static $origIniSettings = [];
155
-    /**
156
-     * PhingFile that we are using for configuration.
157
-     */
158
-    private $buildFile;
159
-    /**
160
-     * The build targets.
161
-     */
162
-    private $targets = [];
163
-    /**
164
-     * Names of classes to add as listeners to project.
165
-     */
166
-    private $listeners = [];
167
-    /**
168
-     * keep going mode.
169
-     *
170
-     * @var bool
171
-     */
172
-    private $keepGoingMode = false;
173
-    private $loggerClassname;
174
-    /**
175
-     * The class to handle input (can be only one).
176
-     */
177
-    private $inputHandlerClassname;
178
-    /**
179
-     * Whether or not log output should be reduced to the minimum.
180
-     *
181
-     * @var bool
182
-     */
183
-    private $silent = false;
184
-    /**
185
-     * Indicates whether phing should run in strict mode.
186
-     */
187
-    private $strictMode = false;
188
-    /**
189
-     * Indicates if this phing should be run.
190
-     */
191
-    private $readyToRun = false;
192
-    /**
193
-     * Indicates we should only parse and display the project help information.
194
-     */
195
-    private $projectHelp = false;
196
-    /**
197
-     * Whether to values in a property file should override existing values.
198
-     */
199
-    private $propertyFileOverride = false;
200
-    /**
201
-     * Whether or not output to the log is to be unadorned.
202
-     */
203
-    private $emacsMode = false;
204
-
205
-    /**
206
-     * @var string
207
-     */
208
-    private $searchForThis;
209
-    private $propertyFiles = [];
210
-
211
-    /**
212
-     * Gets the stream to use for standard (non-error) output.
213
-     *
214
-     * @return OutputStream
215
-     */
216
-    public static function getOutputStream()
217
-    {
218
-        return self::$out;
219
-    }
220
-
221
-    /**
222
-     * Gets the stream to use for error output.
223
-     *
224
-     * @return OutputStream
225
-     */
226
-    public static function getErrorStream()
227
-    {
228
-        return self::$err;
229
-    }
230
-
231
-    /**
232
-     * Command line entry point. This method kicks off the building
233
-     * of a project object and executes a build using either a given
234
-     * target or the default target.
235
-     *
236
-     * @param array $args command line args
237
-     * @throws Exception
238
-     */
239
-    public static function fire($args): void
240
-    {
241
-        self::start($args);
242
-    }
243
-
244
-    /**
245
-     * Entry point allowing for more options from other front ends.
246
-     *
247
-     * This method encapsulates the complete build lifecycle.
248
-     *
249
-     * @param array $args the commandline args passed to phing shell script
250
-     * @param array $additionalUserProperties Any additional properties to be passed to Phing (alternative front-end might implement this).
251
-     *                                        These additional properties will be available using the getDefinedProperty() method and will
252
-     *                                        be added to the project's "user" properties
253
-     *
254
-     * @throws Exception - if there is an error during build
255
-     * @see    runBuild()
256
-     *
257
-     * @see    execute()
258
-     */
259
-    public static function start($args, array $additionalUserProperties = null)
260
-    {
261
-        try {
262
-            $m = new self();
263
-            $m->execute($args);
264
-        } catch (Exception $exc) {
265
-            self::handleLogfile();
266
-            self::printMessage($exc);
267
-            self::statusExit(1);
268
-
269
-            return;
270
-        }
271
-
272
-        if (null !== $additionalUserProperties) {
273
-            foreach ($additionalUserProperties as $key => $value) {
274
-                $m::setDefinedProperty($key, $value);
275
-            }
276
-        }
277
-
278
-        // expect the worst
279
-        $exitCode = 1;
280
-
281
-        try {
282
-            try {
283
-                $m->runBuild();
284
-                $exitCode = 0;
285
-            } catch (ExitStatusException $ese) {
286
-                $exitCode = $ese->getCode();
287
-                if (0 !== $exitCode) {
288
-                    self::handleLogfile();
289
-
290
-                    throw $ese;
291
-                }
292
-            }
293
-        } catch (BuildException $exc) {
294
-            // avoid printing output twice: self::printMessage($exc);
295
-        } catch (Throwable $exc) {
296
-            self::printMessage($exc);
297
-        } finally {
298
-            self::handleLogfile();
299
-        }
300
-        self::statusExit($exitCode);
301
-    }
302
-
303
-    /**
304
-     * Setup/initialize Phing environment from commandline args.
305
-     *
306
-     * @param array $args commandline args passed to phing shell
307
-     *
308
-     * @throws ConfigurationException
309
-     */
310
-    public function execute($args): void
311
-    {
312
-        self::$definedProps = new Properties();
313
-        $this->searchForThis = null;
314
-
315
-        // 1) First handle any options which should always
316
-        // Note: The order in which these are executed is important (if multiple of these options are specified)
317
-
318
-        if (in_array('-help', $args) || in_array('-h', $args)) {
319
-            static::printUsage();
320
-
321
-            return;
322
-        }
323
-
324
-        if (in_array('-version', $args) || in_array('-v', $args)) {
325
-            static::printVersion();
326
-
327
-            return;
328
-        }
329
-
330
-        if (in_array('-init', $args) || in_array('-i', $args)) {
331
-            $key = array_search('-init', $args) ?: array_search('-i', $args);
332
-            $path = $args[$key + 1] ?? null;
333
-
334
-            self::init($path);
335
-
336
-            return;
337
-        }
338
-
339
-        if (in_array('-diagnostics', $args)) {
340
-            Diagnostics::doReport(new PrintStream(self::$out));
341
-
342
-            return;
343
-        }
344
-
345
-        // 2) Next pull out stand-alone args.
346
-        // Note: The order in which these are executed is important (if multiple of these options are specified)
347
-
348
-        if (
349
-            false !== ($key = array_search('-quiet', $args, true))
350
-            || false !== ($key = array_search(
351
-                '-q',
352
-                $args,
353
-                true
354
-            ))
355
-        ) {
356
-            self::$msgOutputLevel = Project::MSG_WARN;
357
-            unset($args[$key]);
358
-        }
359
-
360
-        if (
361
-            false !== ($key = array_search('-emacs', $args, true))
362
-            || false !== ($key = array_search('-e', $args, true))
363
-        ) {
364
-            $this->emacsMode = true;
365
-            unset($args[$key]);
366
-        }
367
-
368
-        if (false !== ($key = array_search('-verbose', $args, true))) {
369
-            self::$msgOutputLevel = Project::MSG_VERBOSE;
370
-            unset($args[$key]);
371
-        }
372
-
373
-        if (false !== ($key = array_search('-debug', $args, true))) {
374
-            self::$msgOutputLevel = Project::MSG_DEBUG;
375
-            unset($args[$key]);
376
-        }
377
-
378
-        if (
379
-            false !== ($key = array_search('-silent', $args, true))
380
-            || false !== ($key = array_search('-S', $args, true))
381
-        ) {
382
-            $this->silent = true;
383
-            unset($args[$key]);
384
-        }
385
-
386
-        if (false !== ($key = array_search('-propertyfileoverride', $args, true))) {
387
-            $this->propertyFileOverride = true;
388
-            unset($args[$key]);
389
-        }
390
-
391
-        // 3) Finally, cycle through to parse remaining args
392
-        //
393
-        $keys = array_keys($args); // Use keys and iterate to max(keys) since there may be some gaps
394
-        $max = $keys ? max($keys) : -1;
395
-        for ($i = 0; $i <= $max; ++$i) {
396
-            if (!array_key_exists($i, $args)) {
397
-                // skip this argument, since it must have been removed above.
398
-                continue;
399
-            }
400
-
401
-            $arg = $args[$i];
402
-
403
-            if ('-logfile' == $arg) {
404
-                try {
405
-                    // see: http://phing.info/trac/ticket/65
406
-                    if (!isset($args[$i + 1])) {
407
-                        $msg = "You must specify a log file when using the -logfile argument\n";
408
-
409
-                        throw new ConfigurationException($msg);
410
-                    }
411
-
412
-                    $logFile = new File($args[++$i]);
413
-                    $out = new FileOutputStream($logFile); // overwrite
414
-                    self::setOutputStream($out);
415
-                    self::setErrorStream($out);
416
-                    self::$isLogFileUsed = true;
417
-                } catch (IOException $ioe) {
418
-                    $msg = 'Cannot write on the specified log file. Make sure the path exists and you have write permissions.';
419
-
420
-                    throw new ConfigurationException($msg, $ioe);
421
-                }
422
-            } elseif ('-buildfile' == $arg || '-file' == $arg || '-f' == $arg) {
423
-                if (!isset($args[$i + 1])) {
424
-                    $msg = 'You must specify a buildfile when using the -buildfile argument.';
425
-
426
-                    throw new ConfigurationException($msg);
427
-                }
428
-
429
-                $this->buildFile = new File($args[++$i]);
430
-            } elseif ('-listener' == $arg) {
431
-                if (!isset($args[$i + 1])) {
432
-                    $msg = 'You must specify a listener class when using the -listener argument';
433
-
434
-                    throw new ConfigurationException($msg);
435
-                }
436
-
437
-                $this->listeners[] = $args[++$i];
438
-            } elseif (StringHelper::startsWith('-D', $arg)) {
439
-                // Evaluating the property information //
440
-                // Checking whether arg. is not just a switch, and next arg. does not starts with switch identifier
441
-                if (('-D' == $arg) && (!StringHelper::startsWith('-', $args[$i + 1]))) {
442
-                    $name = $args[++$i];
443
-                } else {
444
-                    $name = substr($arg, 2);
445
-                }
446
-
447
-                $value = null;
448
-                $posEq = strpos($name, '=');
449
-                if (false !== $posEq) {
450
-                    $value = substr($name, $posEq + 1);
451
-                    $name = substr($name, 0, $posEq);
452
-                } elseif ($i < count($args) - 1 && !StringHelper::startsWith('-D', $args[$i + 1])) {
453
-                    $value = $args[++$i];
454
-                }
455
-                self::$definedProps->setProperty($name, $value);
456
-            } elseif ('-logger' == $arg) {
457
-                if (!isset($args[$i + 1])) {
458
-                    $msg = 'You must specify a classname when using the -logger argument';
459
-
460
-                    throw new ConfigurationException($msg);
461
-                }
462
-
463
-                $this->loggerClassname = $args[++$i];
464
-            } elseif ('-no-strict' == $arg) {
465
-                $this->strictMode = false;
466
-            } elseif ('-strict' == $arg) {
467
-                $this->strictMode = true;
468
-            } elseif ('-inputhandler' == $arg) {
469
-                if (null !== $this->inputHandlerClassname) {
470
-                    throw new ConfigurationException('Only one input handler class may be specified.');
471
-                }
472
-                if (!isset($args[$i + 1])) {
473
-                    $msg = 'You must specify a classname when using the -inputhandler argument';
474
-
475
-                    throw new ConfigurationException($msg);
476
-                }
477
-
478
-                $this->inputHandlerClassname = $args[++$i];
479
-            } elseif ('-propertyfile' === $arg) {
480
-                $i = $this->handleArgPropertyFile($args, $i);
481
-            } elseif ('-keep-going' === $arg || '-k' === $arg) {
482
-                $this->keepGoingMode = true;
483
-            } elseif ('-longtargets' == $arg) {
484
-                self::$definedProps->setProperty('phing.showlongtargets', 1);
485
-            } elseif ('-projecthelp' == $arg || '-targets' == $arg || '-list' == $arg || '-l' == $arg || '-p' == $arg) {
486
-                // set the flag to display the targets and quit
487
-                $this->projectHelp = true;
488
-            } elseif ('-find' == $arg) {
489
-                // eat up next arg if present, default to build.xml
490
-                if ($i < count($args) - 1) {
491
-                    $this->searchForThis = $args[++$i];
492
-                } else {
493
-                    $this->searchForThis = self::DEFAULT_BUILD_FILENAME;
494
-                }
495
-            } elseif ('-' == substr($arg, 0, 1)) {
496
-                // we don't have any more args
497
-                self::printUsage();
498
-                self::$err->write(PHP_EOL);
499
-
500
-                throw new ConfigurationException('Unknown argument: ' . $arg);
501
-            } else {
502
-                // if it's no other arg, it may be the target
503
-                $this->targets[] = $arg;
504
-            }
505
-        }
506
-
507
-        // if buildFile was not specified on the command line,
508
-        if (null === $this->buildFile) {
509
-            // but -find then search for it
510
-            if (null !== $this->searchForThis) {
511
-                $this->buildFile = $this->findBuildFile(self::getProperty('user.dir'), $this->searchForThis);
512
-            } else {
513
-                $this->buildFile = new File(self::DEFAULT_BUILD_FILENAME);
514
-            }
515
-        }
516
-
517
-        try {
518
-            // make sure buildfile (or buildfile.dist) exists
519
-            if (!$this->buildFile->exists()) {
520
-                $distFile = new File($this->buildFile->getAbsolutePath() . '.dist');
521
-                if (!$distFile->exists()) {
522
-                    throw new ConfigurationException(
523
-                        'Buildfile: ' . $this->buildFile->__toString() . ' does not exist!'
524
-                    );
525
-                }
526
-                $this->buildFile = $distFile;
527
-            }
528
-
529
-            // make sure it's not a directory
530
-            if ($this->buildFile->isDirectory()) {
531
-                throw new ConfigurationException('Buildfile: ' . $this->buildFile->__toString() . ' is a dir!');
532
-            }
533
-        } catch (IOException $e) {
534
-            // something else happened, buildfile probably not readable
535
-            throw new ConfigurationException('Buildfile: ' . $this->buildFile->__toString() . ' is not readable!');
536
-        }
537
-
538
-        $this->loadPropertyFiles();
539
-
540
-        $this->readyToRun = true;
541
-    }
542
-
543
-    /**
544
-     * Prints the usage of how to use this class.
545
-     */
546
-    public static function printUsage()
547
-    {
548
-        $msg = '';
549
-        $msg .= 'phing [options] [target [target2 [target3] ...]]' . PHP_EOL;
550
-        $msg .= 'Options: ' . PHP_EOL;
551
-        $msg .= '  -h -help               print this message' . PHP_EOL;
552
-        $msg .= '  -l -list               list available targets in this project' . PHP_EOL;
553
-        $msg .= '  -i -init [file]        generates an initial buildfile' . PHP_EOL;
554
-        $msg .= '  -v -version            print the version information and exit' . PHP_EOL;
555
-        $msg .= '  -q -quiet              be extra quiet' . PHP_EOL;
556
-        $msg .= '  -S -silent             print nothing but task outputs and build failures' . PHP_EOL;
557
-        $msg .= '  -verbose               be extra verbose' . PHP_EOL;
558
-        $msg .= '  -debug                 print debugging information' . PHP_EOL;
559
-        $msg .= '  -emacs, -e             produce logging information without adornments' . PHP_EOL;
560
-        $msg .= '  -diagnostics           print diagnostics information' . PHP_EOL;
561
-        $msg .= '  -strict                runs build in strict mode, considering a warning as error' . PHP_EOL;
562
-        $msg .= '  -no-strict             runs build normally (overrides buildfile attribute)' . PHP_EOL;
563
-        $msg .= '  -longtargets           show target descriptions during build' . PHP_EOL;
564
-        $msg .= '  -logfile <file>        use given file for log' . PHP_EOL;
565
-        $msg .= '  -logger <classname>    the class which is to perform logging' . PHP_EOL;
566
-        $msg .= '  -listener <classname>  add an instance of class as a project listener' . PHP_EOL;
567
-        $msg .= '  -f -buildfile <file>   use given buildfile' . PHP_EOL;
568
-        $msg .= '  -D<property>=<value>   use value for given property' . PHP_EOL;
569
-        $msg .= '  -keep-going, -k        execute all targets that do not depend' . PHP_EOL;
570
-        $msg .= '                         on failed target(s)' . PHP_EOL;
571
-        $msg .= '  -propertyfile <file>   load all properties from file' . PHP_EOL;
572
-        $msg .= '  -propertyfileoverride  values in property file override existing values' . PHP_EOL;
573
-        $msg .= '  -find <file>           search for buildfile towards the root of the' . PHP_EOL;
574
-        $msg .= '                         filesystem and use it' . PHP_EOL;
575
-        $msg .= '  -inputhandler <file>   the class to use to handle user input' . PHP_EOL;
576
-        //$msg .= "  -recursive <file>      search for buildfile downwards and use it" . PHP_EOL;
577
-        $msg .= PHP_EOL;
578
-        $msg .= 'Report bugs to https://github.com/phingofficial/phing/issues' . PHP_EOL;
579
-        self::$err->write($msg);
580
-    }
581
-
582
-    /**
583
-     * Prints the current Phing version.
584
-     */
585
-    public static function printVersion()
586
-    {
587
-        self::$out->write(self::getPhingVersion() . PHP_EOL);
588
-    }
589
-
590
-    /**
591
-     * Gets the current Phing version based on VERSION.TXT file.
592
-     *
593
-     * @return string
594
-     * @throws ConfigurationException
595
-     *
596
-     */
597
-    public static function getPhingVersion(): string
598
-    {
599
-        $versionPath = self::getResourcePath('phing/etc/VERSION.TXT');
600
-        if (null === $versionPath) {
601
-            $versionPath = self::getResourcePath('etc/VERSION.TXT');
602
-        }
603
-        if (null === $versionPath) {
604
-            throw new ConfigurationException('No VERSION.TXT file found; try setting phing.home environment variable.');
605
-        }
606
-
607
-        try { // try to read file
608
-            $file = new File($versionPath);
609
-            $reader = new FileReader($file);
610
-            $phingVersion = trim($reader->read());
611
-        } catch (IOException $iox) {
612
-            throw new ConfigurationException("Can't read version information file");
613
-        }
614
-
615
-        $basePath = dirname(__DIR__, 2);
616
-
617
-        $version = new Version($phingVersion, $basePath);
618
-
619
-        return 'Phing ' . $version->getVersion();
620
-    }
621
-
622
-    /**
623
-     * Looks on include path for specified file.
624
-     *
625
-     * @param string $path
626
-     *
627
-     * @return string|null file found (null if no file found)
628
-     */
629
-    public static function getResourcePath($path): ?string
630
-    {
631
-        if (null === self::$importPaths) {
632
-            self::$importPaths = self::explodeIncludePath();
633
-        }
634
-
635
-        $path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $path);
636
-
637
-        foreach (self::$importPaths as $prefix) {
638
-            $testPath = $prefix . DIRECTORY_SEPARATOR . $path;
639
-            if (file_exists($testPath)) {
640
-                return $testPath;
641
-            }
642
-        }
643
-
644
-        // Check for the property phing.home
645
-        $homeDir = self::getProperty(self::PHING_HOME);
646
-        if ($homeDir) {
647
-            $testPath = $homeDir . DIRECTORY_SEPARATOR . $path;
648
-            if (file_exists($testPath)) {
649
-                return $testPath;
650
-            }
651
-        }
652
-
653
-        // Check for the phing home of phar archive
654
-        if (0 === strpos(self::$importPaths[0], 'phar://')) {
655
-            $testPath = self::$importPaths[0] . '/../' . $path;
656
-            if (file_exists($testPath)) {
657
-                return $testPath;
658
-            }
659
-        }
660
-
661
-        // Do one additional check based on path of current file (Phing.php)
662
-        $maybeHomeDir = realpath(__DIR__ . DIRECTORY_SEPARATOR);
663
-        $testPath = $maybeHomeDir . DIRECTORY_SEPARATOR . $path;
664
-        if (file_exists($testPath)) {
665
-            return $testPath;
666
-        }
667
-
668
-        return null;
669
-    }
670
-
671
-    /**
672
-     * Explode an include path into an array.
673
-     *
674
-     * If no path provided, uses current include_path. Works around issues that
675
-     * occur when the path includes stream schemas.
676
-     *
677
-     * Pulled from Zend_Loader::explodeIncludePath() in ZF1.
678
-     *
679
-     * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
680
-     * @license   http://framework.zend.com/license/new-bsd New BSD License
681
-     *
682
-     * @param null|string $path
683
-     *
684
-     * @return array
685
-     */
686
-    public static function explodeIncludePath($path = null)
687
-    {
688
-        if (null === $path) {
689
-            $path = get_include_path();
690
-        }
691
-
692
-        if (PATH_SEPARATOR === ':') {
693
-            // On *nix systems, include_paths which include paths with a stream
694
-            // schema cannot be safely explode'd, so we have to be a bit more
695
-            // intelligent in the approach.
696
-            $paths = preg_split('#:(?!//)#', $path);
697
-        } else {
698
-            $paths = explode(PATH_SEPARATOR, $path);
699
-        }
700
-
701
-        return $paths;
702
-    }
703
-
704
-    /**
705
-     * Returns property value for a System property.
706
-     * System properties are "global" properties like application.startdir,
707
-     * and user.dir.  Many of these correspond to similar properties in Java
708
-     * or Ant.
709
-     *
710
-     * @param string $propName
711
-     *
712
-     * @return string value of found property (or null, if none found)
713
-     */
714
-    public static function getProperty($propName)
715
-    {
716
-        // some properties are detemined on each access
717
-        // some are cached, see below
718
-
719
-        // default is the cached value:
720
-        $val = self::$properties[$propName] ?? null;
721
-
722
-        // special exceptions
723
-        switch ($propName) {
724
-            case 'user.dir':
725
-                $val = getcwd();
726
-
727
-                break;
728
-        }
729
-
730
-        return $val;
731
-    }
732
-
733
-    /**
734
-     * Creates generic buildfile.
735
-     *
736
-     * @param string $path
737
-     */
738
-    public static function init($path)
739
-    {
740
-        if ($buildfilePath = self::initPath($path)) {
741
-            self::initWrite($buildfilePath);
742
-        }
743
-    }
744
-
745
-    /**
746
-     * Returns buildfile's path.
747
-     *
748
-     * @param $path
749
-     *
750
-     * @return string
751
-     * @throws ConfigurationException
752
-     *
753
-     */
754
-    protected static function initPath($path)
755
-    {
756
-        // Fallback
757
-        if (empty($path)) {
758
-            $defaultDir = self::getProperty('application.startdir');
759
-            $path = $defaultDir . DIRECTORY_SEPARATOR . self::DEFAULT_BUILD_FILENAME;
760
-        }
761
-
762
-        // Adding filename if necessary
763
-        if (is_dir($path)) {
764
-            $path .= DIRECTORY_SEPARATOR . self::DEFAULT_BUILD_FILENAME;
765
-        }
766
-
767
-        // Check if path is available
768
-        $dirname = dirname($path);
769
-        if (is_dir($dirname) && !is_file($path)) {
770
-            return $path;
771
-        }
772
-
773
-        // Path is valid, but buildfile already exists
774
-        if (is_file($path)) {
775
-            throw new ConfigurationException('Buildfile already exists.');
776
-        }
777
-
778
-        throw new ConfigurationException('Invalid path for sample buildfile.');
779
-    }
780
-
781
-    /**
782
-     * Writes sample buildfile.
783
-     *
784
-     * If $buildfilePath does not exist, the buildfile is created.
785
-     *
786
-     * @param $buildfilePath buildfile's location
787
-     *
788
-     * @throws ConfigurationException
789
-     */
790
-    protected static function initWrite($buildfilePath): void
791
-    {
792
-        // Overwriting protection
793
-        if (file_exists($buildfilePath)) {
794
-            throw new ConfigurationException('Cannot overwrite existing file.');
795
-        }
796
-
797
-        file_put_contents($buildfilePath, self::DEFAULT_BUILD_CONTENT);
798
-    }
799
-
800
-    /**
801
-     * Sets the stream to use for standard (non-error) output.
802
-     *
803
-     * @param OutputStream $stream the stream to use for standard output
804
-     */
805
-    public static function setOutputStream(OutputStream $stream)
806
-    {
807
-        self::$out = $stream;
808
-    }
809
-
810
-    /**
811
-     * Sets the stream to use for error output.
812
-     *
813
-     * @param OutputStream $stream the stream to use for error output
814
-     */
815
-    public static function setErrorStream(OutputStream $stream): void
816
-    {
817
-        self::$err = $stream;
818
-    }
819
-
820
-    /**
821
-     * Handle the -propertyfile argument.
822
-     *
823
-     * @throws ConfigurationException
824
-     * @throws IOException
825
-     */
826
-    private function handleArgPropertyFile(array $args, int $pos): int
827
-    {
828
-        if (!isset($args[$pos + 1])) {
829
-            throw new ConfigurationException('You must specify a filename when using the -propertyfile argument');
830
-        }
831
-
832
-        $this->propertyFiles[] = $args[++$pos];
833
-
834
-        return $pos;
835
-    }
836
-
837
-    /**
838
-     * Search parent directories for the build file.
839
-     *
840
-     * Takes the given target as a suffix to append to each
841
-     * parent directory in search of a build file.  Once the
842
-     * root of the file-system has been reached an exception
843
-     * is thrown.
844
-     *
845
-     * @param string $start start file path
846
-     * @param string $suffix suffix filename to look for in parents
847
-     *
848
-     * @return File A handle to the build file
849
-     * @throws ConfigurationException
850
-     *
851
-     */
852
-    private function findBuildFile($start, $suffix)
853
-    {
854
-        if (self::getMsgOutputLevel() >= Project::MSG_INFO) {
855
-            self::$out->write('Searching for ' . $suffix . ' ...' . PHP_EOL);
856
-        }
857
-
858
-        $parent = new File((new File($start))->getAbsolutePath());
859
-        $file = new File($parent, $suffix);
860
-
861
-        // check if the target file exists in the current directory
862
-        while (!$file->exists()) {
863
-            // change to parent directory
864
-            $parent = $parent->getParentFile();
865
-
866
-            // if parent is null, then we are at the root of the fs,
867
-            // complain that we can't find the build file.
868
-            if (null === $parent) {
869
-                throw new ConfigurationException('Could not locate a build file!');
870
-            }
871
-            // refresh our file handle
872
-            $file = new File($parent, $suffix);
873
-        }
874
-
875
-        return $file;
876
-    }
877
-
878
-    /**
879
-     * Making output level a static property so that this property
880
-     * can be accessed by other parts of the system, enabling
881
-     * us to display more information -- e.g. backtraces -- for "debug" level.
882
-     *
883
-     * @return int
884
-     */
885
-    public static function getMsgOutputLevel()
886
-    {
887
-        return self::$msgOutputLevel;
888
-    }
889
-
890
-    /**
891
-     * @throws IOException
892
-     */
893
-    private function loadPropertyFiles(): void
894
-    {
895
-        foreach ($this->propertyFiles as $filename) {
896
-            $fileParserFactory = new FileParserFactory();
897
-            $fileParser = $fileParserFactory->createParser(pathinfo($filename, PATHINFO_EXTENSION));
898
-            $p = new Properties(null, $fileParser);
899
-
900
-            try {
901
-                $p->load(new File($filename));
902
-            } catch (IOException $e) {
903
-                self::$out->write('Could not load property file ' . $filename . ': ' . $e->getMessage());
904
-            }
905
-            foreach ($p->getProperties() as $prop => $value) {
906
-                self::$definedProps->setProperty($prop, $value);
907
-            }
908
-        }
909
-    }
910
-
911
-    /**
912
-     * Close logfiles, if we have been writing to them.
913
-     *
914
-     * @since Phing 2.3.0
915
-     */
916
-    private static function handleLogfile(): void
917
-    {
918
-        if (self::$isLogFileUsed) {
919
-            self::$err->close();
920
-            self::$out->close();
921
-        }
922
-    }
923
-
924
-    /**
925
-     * Prints the message of the Exception if it's not null.
926
-     */
927
-    public static function printMessage(Throwable $t): void
928
-    {
929
-        if (null === self::$err) { // Make sure our error output is initialized
930
-            self::initializeOutputStreams();
931
-        }
932
-        if (self::getMsgOutputLevel() >= Project::MSG_VERBOSE) {
933
-            self::$err->write((string) $t . PHP_EOL);
934
-        } else {
935
-            self::$err->write($t->getMessage() . PHP_EOL);
936
-        }
937
-    }
938
-
939
-    /**
940
-     * Sets the stdout and stderr streams if they are not already set.
941
-     */
942
-    private static function initializeOutputStreams()
943
-    {
944
-        if (null === self::$out) {
945
-            if (!defined('STDOUT')) {
946
-                self::$out = new OutputStream(fopen('php://stdout', 'w'));
947
-            } else {
948
-                self::$out = new OutputStream(STDOUT);
949
-            }
950
-        }
951
-        if (null === self::$err) {
952
-            if (!defined('STDERR')) {
953
-                self::$err = new OutputStream(fopen('php://stderr', 'w'));
954
-            } else {
955
-                self::$err = new OutputStream(STDERR);
956
-            }
957
-        }
958
-    }
959
-
960
-    /**
961
-     * This operation is expected to call `exit($int)`, which
962
-     * is what the base version does.
963
-     * However, it is possible to do something else.
964
-     *
965
-     * @param int $exitCode code to exit with
966
-     */
967
-    protected static function statusExit($exitCode): void
968
-    {
969
-        Phing::shutdown();
970
-
971
-        exit($exitCode);
972
-    }
973
-
974
-    /**
975
-     * Performs any shutdown routines, such as stopping timers.
976
-     *
977
-     * @throws IOException
978
-     */
979
-    public static function shutdown(): void
980
-    {
981
-        FileSystem::getFileSystem()::deleteFilesOnExit();
982
-        self::$msgOutputLevel = Project::MSG_INFO;
983
-        self::restoreIni();
984
-        self::getTimer()->stop();
985
-    }
986
-
987
-    /**
988
-     * Restores [most] PHP INI values to their pre-Phing state.
989
-     *
990
-     * Currently the following settings are not restored:
991
-     *  - max_execution_time (because getting current time limit is not possible)
992
-     *  - memory_limit (which may have been increased by Phing)
993
-     */
994
-    private static function restoreIni(): void
995
-    {
996
-        foreach (self::$origIniSettings as $settingName => $settingValue) {
997
-            switch ($settingName) {
998
-                case 'error_reporting':
999
-                    error_reporting($settingValue);
1000
-
1001
-                    break;
1002
-
1003
-                default:
1004
-                    ini_set($settingName, $settingValue);
1005
-            }
1006
-        }
1007
-    }
1008
-
1009
-    /**
1010
-     * Returns reference to DefaultClock object.
1011
-     */
1012
-    public static function getTimer(): DefaultClock
1013
-    {
1014
-        if (null === self::$timer) {
1015
-            self::$timer = new DefaultClock();
1016
-        }
1017
-
1018
-        return self::$timer;
1019
-    }
1020
-
1021
-    /**
1022
-     * This sets a property that was set via command line or otherwise passed into Phing.
1023
-     *
1024
-     * @param string $name
1025
-     * @param mixed $value
1026
-     *
1027
-     * @return mixed value of found property (or null, if none found)
1028
-     */
1029
-    public static function setDefinedProperty($name, $value)
1030
-    {
1031
-        return self::$definedProps->setProperty($name, $value);
1032
-    }
1033
-
1034
-    /**
1035
-     * Executes the build.
1036
-     *
1037
-     * @throws IOException
1038
-     * @throws Throwable
1039
-     */
1040
-    public function runBuild(): void
1041
-    {
1042
-        if (!$this->readyToRun) {
1043
-            return;
1044
-        }
1045
-
1046
-        $project = new Project();
1047
-
1048
-        self::setCurrentProject($project);
1049
-        set_error_handler(['Phing\Phing', 'handlePhpError']);
1050
-
1051
-        $error = null;
1052
-
1053
-        try {
1054
-            $this->addBuildListeners($project);
1055
-            $this->addInputHandler($project);
1056
-
1057
-            // set this right away, so that it can be used in logging.
1058
-            $project->setUserProperty('phing.file', $this->buildFile->getAbsolutePath());
1059
-            $project->setUserProperty('phing.dir', dirname($this->buildFile->getAbsolutePath()));
1060
-            $project->setUserProperty('phing.version', static::getPhingVersion());
1061
-            $project->fireBuildStarted();
1062
-            $project->init();
1063
-            $project->setKeepGoingMode($this->keepGoingMode);
1064
-
1065
-            $e = self::$definedProps->keys();
1066
-            while (count($e)) {
1067
-                $arg = (string) array_shift($e);
1068
-                $value = (string) self::$definedProps->getProperty($arg);
1069
-                $project->setUserProperty($arg, $value);
1070
-            }
1071
-            unset($e);
1072
-
1073
-            // first use the Configurator to create the project object
1074
-            // from the given build file.
1075
-
1076
-            ProjectConfigurator::configureProject($project, $this->buildFile);
1077
-
1078
-            // Set the project mode
1079
-            $project->setStrictMode(StringHelper::booleanValue($this->strictMode));
1080
-
1081
-            // make sure that minimum required phing version is satisfied
1082
-            $this->comparePhingVersion($project->getPhingVersion());
1083
-
1084
-            if ($this->projectHelp) {
1085
-                $this->printDescription($project);
1086
-                $this->printTargets($project);
1087
-
1088
-                return;
1089
-            }
1090
-
1091
-            // make sure that we have a target to execute
1092
-            if (0 === count($this->targets)) {
1093
-                $this->targets[] = $project->getDefaultTarget();
1094
-            }
1095
-
1096
-            $project->executeTargets($this->targets);
1097
-        } catch (Throwable $t) {
1098
-            $error = $t;
1099
-
1100
-            throw $t;
1101
-        } finally {
1102
-            if (!$this->projectHelp) {
1103
-                try {
1104
-                    $project->fireBuildFinished($error);
1105
-                } catch (Exception $e) {
1106
-                    self::$err->write('Caught an exception while logging the end of the build.  Exception was:' . PHP_EOL);
1107
-                    self::$err->write($e->getTraceAsString());
1108
-                    if (null !== $error) {
1109
-                        self::$err->write('There has been an error prior to that:' . PHP_EOL);
1110
-                        self::$err->write($error->getTraceAsString());
1111
-                    }
1112
-
1113
-                    throw new BuildException($error);
1114
-                }
1115
-            } elseif (null !== $error) {
1116
-                $project->log($error->getMessage(), Project::MSG_ERR);
1117
-            }
1118
-
1119
-            restore_error_handler();
1120
-            self::unsetCurrentProject();
1121
-        }
1122
-    }
1123
-
1124
-    /**
1125
-     * Bind any registered build listeners to this project.
1126
-     *
1127
-     * This means adding the logger and any build listeners that were specified
1128
-     * with -listener arg.
1129
-     *
1130
-     * @throws BuildException
1131
-     * @throws ConfigurationException
1132
-     */
1133
-    private function addBuildListeners(Project $project)
1134
-    {
1135
-        // Add the default listener
1136
-        $project->addBuildListener($this->createLogger());
1137
-
1138
-        foreach ($this->listeners as $listenerClassname) {
1139
-            try {
1140
-                $clz = Phing::import($listenerClassname);
1141
-            } catch (Exception $e) {
1142
-                $msg = 'Unable to instantiate specified listener '
1143
-                    . 'class ' . $listenerClassname . ' : '
1144
-                    . $e->getMessage();
1145
-
1146
-                throw new ConfigurationException($msg);
1147
-            }
1148
-
1149
-            $listener = new $clz();
1150
-
1151
-            if ($listener instanceof StreamRequiredBuildLogger) {
1152
-                throw new ConfigurationException('Unable to add ' . $listenerClassname . ' as a listener, since it requires explicit error/output streams. (You can specify it as a -logger.)');
1153
-            }
1154
-            $project->addBuildListener($listener);
1155
-        }
1156
-    }
1157
-
1158
-    /**
1159
-     * Creates the default build logger for sending build events to the log.
1160
-     *
1161
-     * @return BuildLogger The created Logger
1162
-     * @throws BuildException
1163
-     *
1164
-     */
1165
-    private function createLogger()
1166
-    {
1167
-        if ($this->silent) {
1168
-            $logger = new SilentLogger();
1169
-            self::$msgOutputLevel = Project::MSG_WARN;
1170
-        } elseif (null !== $this->loggerClassname) {
1171
-            self::import($this->loggerClassname);
1172
-            // get class name part
1173
-            $classname = self::import($this->loggerClassname);
1174
-            $logger = new $classname();
1175
-            if (!($logger instanceof BuildLogger)) {
1176
-                throw new BuildException($classname . ' does not implement the BuildLogger interface.');
1177
-            }
1178
-        } else {
1179
-            $logger = new DefaultLogger();
1180
-        }
1181
-        $logger->setMessageOutputLevel(self::$msgOutputLevel);
1182
-        $logger->setOutputStream(self::$out);
1183
-        $logger->setErrorStream(self::$err);
1184
-        $logger->setEmacsMode($this->emacsMode);
1185
-
1186
-        return $logger;
1187
-    }
1188
-
1189
-    /**
1190
-     * Import a class, supporting the following conventions:
1191
-     * - PEAR style (@see http://pear.php.net/manual/en/standards.naming.php)
1192
-     * - PSR-0 (@see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md).
1193
-     *
1194
-     * @param string $classname Name of class
1195
-     * @param mixed $classpath String or object supporting __toString()
1196
-     *
1197
-     * @throws BuildException - if cannot find the specified file
1198
-     *
1199
-     * @return string the unqualified classname (which can be instantiated)
1200
-     */
1201
-    public static function import($classname, $classpath = null)
1202
-    {
1203
-        // first check to see that the class specified hasn't already been included.
1204
-        if (class_exists($classname)) {
1205
-            return $classname;
1206
-        }
1207
-
1208
-        $filename = strtr($classname, ['_' => DIRECTORY_SEPARATOR, '\\' => DIRECTORY_SEPARATOR]) . '.php';
1209
-
1210
-        Phing::importFile($filename, $classpath);
1211
-
1212
-        return $classname;
1213
-    }
1214
-
1215
-    /**
1216
-     * Import a PHP file.
1217
-     *
1218
-     * This used to be named __import, however PHP has reserved all method names
1219
-     * with a double underscore prefix for future use.
1220
-     *
1221
-     * @param string $path Path to the PHP file
1222
-     * @param mixed $classpath String or object supporting __toString()
1223
-     *
1224
-     * @throws ConfigurationException
1225
-     */
1226
-    public static function importFile($path, $classpath = null)
1227
-    {
1228
-        if ($classpath) {
1229
-            // Apparently casting to (string) no longer invokes __toString() automatically.
1230
-            if (is_object($classpath)) {
1231
-                $classpath = $classpath->__toString();
1232
-            }
1233
-
1234
-            // classpaths are currently additive, but we also don't want to just
1235
-            // indiscriminantly prepand/append stuff to the include_path.  This means
1236
-            // we need to parse current incldue_path, and prepend any
1237
-            // specified classpath locations that are not already in the include_path.
1238
-            //
1239
-            // NOTE:  the reason why we do it this way instead of just changing include_path
1240
-            // and then changing it back, is that in many cases applications (e.g. Propel) will
1241
-            // include/require class files from within method calls.  This means that not all
1242
-            // necessary files will be included in this import() call, and hence we can't
1243
-            // change the include_path back without breaking those apps.  While this method could
1244
-            // be more expensive than switching & switching back (not sure, but maybe), it makes it
1245
-            // possible to write far less expensive run-time applications (e.g. using Propel), which is
1246
-            // really where speed matters more.
1247
-
1248
-            $curr_parts = Phing::explodeIncludePath();
1249
-            $add_parts = Phing::explodeIncludePath($classpath);
1250
-            $new_parts = array_diff($add_parts, $curr_parts);
1251
-            if ($new_parts) {
1252
-                set_include_path(implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts)));
1253
-            }
1254
-        }
1255
-
1256
-        $ret = include_once $path;
1257
-
1258
-        if (false === $ret) {
1259
-            $msg = "Error importing {$path}";
1260
-            if (self::getMsgOutputLevel() >= Project::MSG_DEBUG) {
1261
-                $x = new Exception('for-path-trace-only');
1262
-                $msg .= $x->getTraceAsString();
1263
-            }
1264
-
1265
-            throw new ConfigurationException($msg);
1266
-        }
1267
-    }
1268
-
1269
-    /**
1270
-     * Creates the InputHandler and adds it to the project.
1271
-     *
1272
-     * @param Project $project the project instance
1273
-     *
1274
-     * @throws ConfigurationException
1275
-     */
1276
-    private function addInputHandler(Project $project): void
1277
-    {
1278
-        if (null === $this->inputHandlerClassname) {
1279
-            $handler = new ConsoleInputHandler(STDIN, new ConsoleOutput());
1280
-        } else {
1281
-            try {
1282
-                $clz = Phing::import($this->inputHandlerClassname);
1283
-                $handler = new $clz();
1284
-                if (null !== $project && method_exists($handler, 'setProject')) {
1285
-                    $handler->setProject($project);
1286
-                }
1287
-            } catch (Exception $e) {
1288
-                $msg = 'Unable to instantiate specified input handler '
1289
-                    . 'class ' . $this->inputHandlerClassname . ' : '
1290
-                    . $e->getMessage();
1291
-
1292
-                throw new ConfigurationException($msg);
1293
-            }
1294
-        }
1295
-        $project->setInputHandler($handler);
1296
-    }
1297
-
1298
-    /**
1299
-     * @param string $version
1300
-     *
1301
-     * @throws BuildException
1302
-     * @throws ConfigurationException
1303
-     */
1304
-    private function comparePhingVersion($version): void
1305
-    {
1306
-        $current = strtolower(self::getPhingVersion());
1307
-        $current = trim(str_replace('phing', '', $current));
1308
-
1309
-        // make sure that version checks are not applied to trunk
1310
-        if ('dev' === $current) {
1311
-            return;
1312
-        }
1313
-
1314
-        if (-1 == version_compare($current, $version)) {
1315
-            throw new BuildException(
1316
-                sprintf('Incompatible Phing version (%s). Version "%s" required.', $current, $version)
1317
-            );
1318
-        }
1319
-    }
1320
-
1321
-    /**
1322
-     * Print the project description, if any.
1323
-     *
1324
-     * @throws IOException
1325
-     */
1326
-    public function printDescription(Project $project): void
1327
-    {
1328
-        if (null !== $project->getDescription()) {
1329
-            $project->log($project->getDescription());
1330
-        }
1331
-    }
1332
-
1333
-    /**
1334
-     * Print out a list of all targets in the current buildfile.
1335
-     */
1336
-    public function printTargets(Project $project)
1337
-    {
1338
-        $visibleTargets = array_filter($project->getTargets(), function (Target $target) {
1339
-            return !$target->isHidden() && !empty($target->getName());
1340
-        });
1341
-        $padding = array_reduce($visibleTargets, function (int $carry, Target $target) {
1342
-            return max(strlen($target->getName()), $carry);
1343
-        }, 0);
1344
-        $categories = [
1345
-            'Default target:' => array_filter($visibleTargets, function (Target $target) use ($project) {
1346
-                return trim(strval($target)) === $project->getDefaultTarget();
1347
-            }),
1348
-            'Main targets:' => array_filter($visibleTargets, function (Target $target) {
1349
-                return !empty($target->getDescription());
1350
-            }),
1351
-            'Subtargets:' => array_filter($visibleTargets, function (Target $target) {
1352
-                return empty($target->getDescription());
1353
-            }),
1354
-        ];
1355
-        foreach ($categories as $title => $targets) {
1356
-            $targetList = $this->generateTargetList($title, $targets, $padding);
1357
-            $project->log($targetList, Project::MSG_WARN);
1358
-        }
1359
-    }
1360
-
1361
-    /**
1362
-     * Returns a formatted list of target names with an optional description.
1363
-     *
1364
-     * @param string $title Title for this list
1365
-     * @param Target[] $targets Targets in this list
1366
-     * @param int $padding Padding for name column
1367
-     */
1368
-    private function generateTargetList(string $title, array $targets, int $padding): string
1369
-    {
1370
-        usort($targets, function (Target $a, Target $b) {
1371
-            return $a->getName() <=> $b->getName();
1372
-        });
1373
-
1374
-        $header = <<<HEADER
1375
-            {$title}
1376
-            -------------------------------------------------------------------------------
1377
-
1378
-            HEADER;
1379
-
1380
-        $getDetails = function (Target $target) use ($padding): string {
1381
-            $details = [];
1382
-            if (!empty($target->getDescription())) {
1383
-                $details[] = $target->getDescription();
1384
-            }
1385
-            if (!empty($target->getDependencies())) {
1386
-                $details[] = ' - depends on: ' . implode(', ', $target->getDependencies());
1387
-            }
1388
-            if (!empty($target->getIf())) {
1389
-                $details[] = ' - if property: ' . $target->getIf();
1390
-            }
1391
-            if (!empty($target->getUnless())) {
1392
-                $details[] = ' - unless property: ' . $target->getUnless();
1393
-            }
1394
-            $detailsToString = function (?string $name, ?string $detail) use ($padding): string {
1395
-                return sprintf(" %-{$padding}s  %s", $name, $detail);
1396
-            };
1397
-
1398
-            return implode(PHP_EOL, array_map($detailsToString, [$target->getName()], $details));
1399
-        };
1400
-
1401
-        return $header . implode(PHP_EOL, array_map($getDetails, $targets)) . PHP_EOL;
1402
-    }
1403
-
1404
-    /**
1405
-     * Unsets the current Project.
1406
-     */
1407
-    public static function unsetCurrentProject(): void
1408
-    {
1409
-        self::$currentProject = null;
1410
-    }
1411
-
1412
-    /**
1413
-     * Error handler for PHP errors encountered during the build.
1414
-     * This uses the logging for the currently configured project.
1415
-     *
1416
-     * @param $level
1417
-     * @param string $message
1418
-     * @param $file
1419
-     * @param $line
1420
-     */
1421
-    public static function handlePhpError($level, $message, $file, $line)
1422
-    {
1423
-        // don't want to print suppressed errors
1424
-        if (error_reporting() > 0) {
1425
-            if (self::$phpErrorCapture) {
1426
-                self::$capturedPhpErrors[] = [
1427
-                    'message' => $message,
1428
-                    'level' => $level,
1429
-                    'line' => $line,
1430
-                    'file' => $file,
1431
-                ];
1432
-            } else {
1433
-                $message = '[PHP Error] ' . $message;
1434
-                $message .= ' [line ' . $line . ' of ' . $file . ']';
1435
-
1436
-                switch ($level) {
1437
-                    case E_USER_DEPRECATED:
1438
-                    case E_DEPRECATED:
1439
-                    case E_STRICT:
1440
-                    case E_NOTICE:
1441
-                    case E_USER_NOTICE:
1442
-                        self::log($message, Project::MSG_VERBOSE);
1443
-
1444
-                        break;
1445
-
1446
-                    case E_WARNING:
1447
-                    case E_USER_WARNING:
1448
-                        self::log($message, Project::MSG_WARN);
1449
-
1450
-                        break;
1451
-
1452
-                    case E_ERROR:
1453
-                    case E_USER_ERROR:
1454
-                    default:
1455
-                        self::log($message, Project::MSG_ERR);
1456
-                } // switch
1457
-            } // if phpErrorCapture
1458
-        } // if not @
1459
-    }
1460
-
1461
-    /**
1462
-     * A static convenience method to send a log to the current (last-setup) Project.
1463
-     * If there is no currently-configured Project, then this will do nothing.
1464
-     *
1465
-     * @param string $message
1466
-     * @param int $priority project::MSG_INFO, etc
1467
-     */
1468
-    public static function log($message, $priority = Project::MSG_INFO): void
1469
-    {
1470
-        $p = self::getCurrentProject();
1471
-        if ($p) {
1472
-            $p->log($message, $priority);
1473
-        }
1474
-    }
1475
-
1476
-    /**
1477
-     * Gets the current Project.
1478
-     *
1479
-     * @return Project current Project or NULL if none is set yet/still
1480
-     */
1481
-    public static function getCurrentProject()
1482
-    {
1483
-        return self::$currentProject;
1484
-    }
1485
-
1486
-    /**
1487
-     * Sets the current Project.
1488
-     *
1489
-     * @param Project $p
1490
-     */
1491
-    public static function setCurrentProject($p): void
1492
-    {
1493
-        self::$currentProject = $p;
1494
-    }
1495
-
1496
-    /**
1497
-     * Begins capturing PHP errors to a buffer.
1498
-     * While errors are being captured, they are not logged.
1499
-     */
1500
-    public static function startPhpErrorCapture(): void
1501
-    {
1502
-        self::$phpErrorCapture = true;
1503
-        self::$capturedPhpErrors = [];
1504
-    }
1505
-
1506
-    /**
1507
-     * Stops capturing PHP errors to a buffer.
1508
-     * The errors will once again be logged after calling this method.
1509
-     */
1510
-    public static function stopPhpErrorCapture(): void
1511
-    {
1512
-        self::$phpErrorCapture = false;
1513
-    }
1514
-
1515
-    /**
1516
-     * Clears the captured errors without affecting the starting/stopping of the capture.
1517
-     */
1518
-    public static function clearCapturedPhpErrors(): void
1519
-    {
1520
-        self::$capturedPhpErrors = [];
1521
-    }
1522
-
1523
-    /**
1524
-     * Gets any PHP errors that were captured to buffer.
1525
-     *
1526
-     * @return array array('message' => message, 'line' => line number, 'file' => file name, 'level' => error level)
1527
-     */
1528
-    public static function getCapturedPhpErrors()
1529
-    {
1530
-        return self::$capturedPhpErrors;
1531
-    }
1532
-
1533
-    /**
1534
-     * This gets a property that was set via command line or otherwise passed into Phing.
1535
-     * "Defined" in this case means "externally defined".  The reason this method exists is to
1536
-     * provide a public means of accessing commandline properties for (e.g.) logger or listener
1537
-     * scripts.  E.g. to specify which logfile to use, PearLogger needs to be able to access
1538
-     * the pear.log.name property.
1539
-     *
1540
-     * @param string $name
1541
-     *
1542
-     * @return string value of found property (or null, if none found)
1543
-     */
1544
-    public static function getDefinedProperty($name)
1545
-    {
1546
-        return self::$definedProps->getProperty($name);
1547
-    }
1548
-
1549
-    /**
1550
-     * Retuns reference to all properties.
1551
-     */
1552
-    public static function &getProperties()
1553
-    {
1554
-        return self::$properties;
1555
-    }
1556
-
1557
-    /**
1558
-     * Start up Phing.
1559
-     * Sets up the Phing environment but does not initiate the build process.
1560
-     *
1561
-     * @throws exception - If the Phing environment cannot be initialized
1562
-     */
1563
-    public static function startup(): void
1564
-    {
1565
-        // setup STDOUT and STDERR defaults
1566
-        self::initializeOutputStreams();
1567
-
1568
-        // some init stuff
1569
-        self::getTimer()->start();
1570
-
1571
-        self::setSystemConstants();
1572
-        self::setIncludePaths();
1573
-        self::setIni();
1574
-    }
1575
-
1576
-    /**
1577
-     * Set System constants which can be retrieved by calling Phing::getProperty($propName).
1578
-     */
1579
-    private static function setSystemConstants(): void
1580
-    {
1581
-        /*
1582
-         * PHP_OS returns on
1583
-         *   WindowsNT4.0sp6  => WINNT
1584
-         *   Windows2000      => WINNT
1585
-         *   Windows ME       => WIN32
1586
-         *   Windows 98SE     => WIN32
1587
-         *   FreeBSD 4.5p7    => FreeBSD
1588
-         *   Redhat Linux     => Linux
1589
-         *   Mac OS X         => Darwin
1590
-         */
1591
-        self::setProperty('host.os', PHP_OS);
1592
-
1593
-        // this is used by some tasks too
1594
-        self::setProperty('os.name', PHP_OS);
1595
-
1596
-        // it's still possible this won't be defined,
1597
-        // e.g. if Phing is being included in another app w/o
1598
-        // using the phing.php script.
1599
-        if (!defined('PHP_CLASSPATH')) {
1600
-            define('PHP_CLASSPATH', get_include_path());
1601
-        }
1602
-
1603
-        self::setProperty('php.classpath', PHP_CLASSPATH);
1604
-
1605
-        // try to determine the host filesystem and set system property
1606
-        // used by Fileself::getFileSystem to instantiate the correct
1607
-        // abstraction layer
1608
-
1609
-        if (PHP_OS_FAMILY === 'Windows') {
1610
-            self::setProperty('host.fstype', 'WINDOWS');
1611
-            self::setProperty('user.home', getenv('HOMEDRIVE') . getenv('HOMEPATH'));
1612
-        } else {
1613
-            self::setProperty('host.fstype', 'UNIX');
1614
-            self::setProperty('user.home', getenv('HOME'));
1615
-        }
1616
-        self::setProperty(self::PHP_INTERPRETER, PHP_BINARY);
1617
-        self::setProperty('file.separator', FileUtils::getSeparator());
1618
-        self::setProperty('line.separator', PHP_EOL);
1619
-        self::setProperty('path.separator', FileUtils::getPathSeparator());
1620
-        self::setProperty(self::PHP_VERSION, PHP_VERSION);
1621
-        self::setProperty('php.tmpdir', sys_get_temp_dir());
1622
-        self::setProperty('application.startdir', getcwd());
1623
-        self::setProperty('phing.startTime', gmdate('D, d M Y H:i:s', time()) . ' GMT');
1624
-
1625
-        // try to detect machine dependent information
1626
-        $sysInfo = [];
1627
-        if (function_exists('posix_uname') && 0 !== stripos(PHP_OS, 'WIN')) {
1628
-            $sysInfo = posix_uname();
1629
-        } else {
1630
-            $sysInfo['nodename'] = php_uname('n');
1631
-            $sysInfo['machine'] = php_uname('m');
1632
-            //this is a not so ideal substition, but maybe better than nothing
1633
-            $sysInfo['domain'] = $_SERVER['SERVER_NAME'] ?? 'unknown';
1634
-            $sysInfo['release'] = php_uname('r');
1635
-            $sysInfo['version'] = php_uname('v');
1636
-        }
1637
-
1638
-        self::setProperty('host.name', $sysInfo['nodename'] ?? 'unknown');
1639
-        self::setProperty('host.arch', $sysInfo['machine'] ?? 'unknown');
1640
-        self::setProperty('host.domain', $sysInfo['domain'] ?? 'unknown');
1641
-        self::setProperty('host.os.release', $sysInfo['release'] ?? 'unknown');
1642
-        self::setProperty('host.os.version', $sysInfo['version'] ?? 'unknown');
1643
-        unset($sysInfo);
1644
-    }
1645
-
1646
-    /**
1647
-     * @param $propName
1648
-     * @param $propValue
1649
-     *
1650
-     * @return string
1651
-     */
1652
-    public static function setProperty($propName, $propValue)
1653
-    {
1654
-        $propName = (string) $propName;
1655
-        $oldValue = self::getProperty($propName);
1656
-        self::$properties[$propName] = $propValue;
1657
-
1658
-        return $oldValue;
1659
-    }
1660
-
1661
-    /**
1662
-     * Sets the include path to PHP_CLASSPATH constant (if this has been defined).
1663
-     *
1664
-     * @throws ConfigurationException - if the include_path could not be set (for some bizarre reason)
1665
-     */
1666
-    private static function setIncludePaths(): void
1667
-    {
1668
-        if (defined('PHP_CLASSPATH')) {
1669
-            $result = set_include_path(PHP_CLASSPATH);
1670
-            if (false === $result) {
1671
-                throw new ConfigurationException('Could not set PHP include_path.');
1672
-            }
1673
-            self::$origIniSettings['include_path'] = $result; // save original value for setting back later
1674
-        }
1675
-    }
1676
-
1677
-    /**
1678
-     * Sets PHP INI values that Phing needs.
1679
-     */
1680
-    private static function setIni(): void
1681
-    {
1682
-        self::$origIniSettings['error_reporting'] = error_reporting(E_ALL);
1683
-
1684
-        // We won't bother storing original max_execution_time, since 1) the value in
1685
-        // php.ini may be wrong (and there's no way to get the current value) and
1686
-        // 2) it would mean something very strange to set it to a value less than time script
1687
-        // has already been running, which would be the likely change.
1688
-
1689
-        set_time_limit(0);
1690
-
1691
-        self::$origIniSettings['short_open_tag'] = ini_set('short_open_tag', 'off');
1692
-        self::$origIniSettings['default_charset'] = ini_set('default_charset', 'iso-8859-1');
1693
-
1694
-        $mem_limit = (int) SizeHelper::fromHumanToBytes(ini_get('memory_limit'));
1695
-        if ($mem_limit < (32 * 1024 * 1024) && $mem_limit > -1) {
1696
-            // We do *not* need to save the original value here, since we don't plan to restore
1697
-            // this after shutdown (we don't trust the effectiveness of PHP's garbage collection).
1698
-            ini_set('memory_limit', '32M'); // nore: this may need to be higher for many projects
1699
-        }
1700
-    }
1701
-}
Please login to merge, or discard this patch.
Upper-Lower-Casing   -1616 removed lines patch added patch discarded remove patch
@@ -83,1619 +83,3 @@
 block discarded – undo
83 83
      */
84 84
     public const DEFAULT_BUILD_FILENAME = 'build.xml';
85 85
     public const DEFAULT_BUILD_CONTENT = <<<'XML'
86
-        <?xml version="1.0" encoding="UTF-8" ?>
87
-
88
-        <project name="" description="" default="">
89
-            
90
-            <target name="" description="">
91
-                
92
-            </target>
93
-            
94
-        </project>
95
-        XML;
96
-    public const PHING_HOME = 'phing.home';
97
-    public const PHP_VERSION = 'php.version';
98
-    public const PHP_INTERPRETER = 'php.interpreter';
99
-
100
-    /**
101
-     * Our current message output status. Follows Project::MSG_XXX.
102
-     */
103
-    private static $msgOutputLevel = Project::MSG_INFO;
104
-    /**
105
-     * Set of properties that are passed in from commandline or invoking code.
106
-     *
107
-     * @var Properties
108
-     */
109
-    private static $definedProps;
110
-    /**
111
-     * Used by utility function getResourcePath().
112
-     */
113
-    private static $importPaths;
114
-    /**
115
-     * System-wide static properties (moved from System).
116
-     */
117
-    private static $properties = [];
118
-    /**
119
-     * Static system timer.
120
-     */
121
-    private static $timer;
122
-    /**
123
-     * The current Project.
124
-     */
125
-    private static $currentProject;
126
-    /**
127
-     * Whether to capture PHP errors to buffer.
128
-     */
129
-    private static $phpErrorCapture = false;
130
-    /**
131
-     * Array of captured PHP errors.
132
-     */
133
-    private static $capturedPhpErrors = [];
134
-    /**
135
-     * @var OUtputStream stream for standard output
136
-     */
137
-    private static $out;
138
-    /**
139
-     * @var OutputStream stream for error output
140
-     */
141
-    private static $err;
142
-    /**
143
-     * @var bool whether we are using a logfile
144
-     */
145
-    private static $isLogFileUsed = false;
146
-    /**
147
-     * Array to hold original ini settings that Phing changes (and needs
148
-     * to restore in restoreIni() method).
149
-     *
150
-     * @var array Struct of array(setting-name => setting-value)
151
-     *
152
-     * @see restoreIni()
153
-     */
154
-    private static $origIniSettings = [];
155
-    /**
156
-     * PhingFile that we are using for configuration.
157
-     */
158
-    private $buildFile;
159
-    /**
160
-     * The build targets.
161
-     */
162
-    private $targets = [];
163
-    /**
164
-     * Names of classes to add as listeners to project.
165
-     */
166
-    private $listeners = [];
167
-    /**
168
-     * keep going mode.
169
-     *
170
-     * @var bool
171
-     */
172
-    private $keepGoingMode = false;
173
-    private $loggerClassname;
174
-    /**
175
-     * The class to handle input (can be only one).
176
-     */
177
-    private $inputHandlerClassname;
178
-    /**
179
-     * Whether or not log output should be reduced to the minimum.
180
-     *
181
-     * @var bool
182
-     */
183
-    private $silent = false;
184
-    /**
185
-     * Indicates whether phing should run in strict mode.
186
-     */
187
-    private $strictMode = false;
188
-    /**
189
-     * Indicates if this phing should be run.
190
-     */
191
-    private $readyToRun = false;
192
-    /**
193
-     * Indicates we should only parse and display the project help information.
194
-     */
195
-    private $projectHelp = false;
196
-    /**
197
-     * Whether to values in a property file should override existing values.
198
-     */
199
-    private $propertyFileOverride = false;
200
-    /**
201
-     * Whether or not output to the log is to be unadorned.
202
-     */
203
-    private $emacsMode = false;
204
-
205
-    /**
206
-     * @var string
207
-     */
208
-    private $searchForThis;
209
-    private $propertyFiles = [];
210
-
211
-    /**
212
-     * Gets the stream to use for standard (non-error) output.
213
-     *
214
-     * @return OutputStream
215
-     */
216
-    public static function getOutputStream()
217
-    {
218
-        return self::$out;
219
-    }
220
-
221
-    /**
222
-     * Gets the stream to use for error output.
223
-     *
224
-     * @return OutputStream
225
-     */
226
-    public static function getErrorStream()
227
-    {
228
-        return self::$err;
229
-    }
230
-
231
-    /**
232
-     * Command line entry point. This method kicks off the building
233
-     * of a project object and executes a build using either a given
234
-     * target or the default target.
235
-     *
236
-     * @param array $args command line args
237
-     * @throws Exception
238
-     */
239
-    public static function fire($args): void
240
-    {
241
-        self::start($args);
242
-    }
243
-
244
-    /**
245
-     * Entry point allowing for more options from other front ends.
246
-     *
247
-     * This method encapsulates the complete build lifecycle.
248
-     *
249
-     * @param array $args the commandline args passed to phing shell script
250
-     * @param array $additionalUserProperties Any additional properties to be passed to Phing (alternative front-end might implement this).
251
-     *                                        These additional properties will be available using the getDefinedProperty() method and will
252
-     *                                        be added to the project's "user" properties
253
-     *
254
-     * @throws Exception - if there is an error during build
255
-     * @see    runBuild()
256
-     *
257
-     * @see    execute()
258
-     */
259
-    public static function start($args, array $additionalUserProperties = null)
260
-    {
261
-        try {
262
-            $m = new self();
263
-            $m->execute($args);
264
-        } catch (Exception $exc) {
265
-            self::handleLogfile();
266
-            self::printMessage($exc);
267
-            self::statusExit(1);
268
-
269
-            return;
270
-        }
271
-
272
-        if (null !== $additionalUserProperties) {
273
-            foreach ($additionalUserProperties as $key => $value) {
274
-                $m::setDefinedProperty($key, $value);
275
-            }
276
-        }
277
-
278
-        // expect the worst
279
-        $exitCode = 1;
280
-
281
-        try {
282
-            try {
283
-                $m->runBuild();
284
-                $exitCode = 0;
285
-            } catch (ExitStatusException $ese) {
286
-                $exitCode = $ese->getCode();
287
-                if (0 !== $exitCode) {
288
-                    self::handleLogfile();
289
-
290
-                    throw $ese;
291
-                }
292
-            }
293
-        } catch (BuildException $exc) {
294
-            // avoid printing output twice: self::printMessage($exc);
295
-        } catch (Throwable $exc) {
296
-            self::printMessage($exc);
297
-        } finally {
298
-            self::handleLogfile();
299
-        }
300
-        self::statusExit($exitCode);
301
-    }
302
-
303
-    /**
304
-     * Setup/initialize Phing environment from commandline args.
305
-     *
306
-     * @param array $args commandline args passed to phing shell
307
-     *
308
-     * @throws ConfigurationException
309
-     */
310
-    public function execute($args): void
311
-    {
312
-        self::$definedProps = new Properties();
313
-        $this->searchForThis = null;
314
-
315
-        // 1) First handle any options which should always
316
-        // Note: The order in which these are executed is important (if multiple of these options are specified)
317
-
318
-        if (in_array('-help', $args) || in_array('-h', $args)) {
319
-            static::printUsage();
320
-
321
-            return;
322
-        }
323
-
324
-        if (in_array('-version', $args) || in_array('-v', $args)) {
325
-            static::printVersion();
326
-
327
-            return;
328
-        }
329
-
330
-        if (in_array('-init', $args) || in_array('-i', $args)) {
331
-            $key = array_search('-init', $args) ?: array_search('-i', $args);
332
-            $path = $args[$key + 1] ?? null;
333
-
334
-            self::init($path);
335
-
336
-            return;
337
-        }
338
-
339
-        if (in_array('-diagnostics', $args)) {
340
-            Diagnostics::doReport(new PrintStream(self::$out));
341
-
342
-            return;
343
-        }
344
-
345
-        // 2) Next pull out stand-alone args.
346
-        // Note: The order in which these are executed is important (if multiple of these options are specified)
347
-
348
-        if (
349
-            false !== ($key = array_search('-quiet', $args, true))
350
-            || false !== ($key = array_search(
351
-                '-q',
352
-                $args,
353
-                true
354
-            ))
355
-        ) {
356
-            self::$msgOutputLevel = Project::MSG_WARN;
357
-            unset($args[$key]);
358
-        }
359
-
360
-        if (
361
-            false !== ($key = array_search('-emacs', $args, true))
362
-            || false !== ($key = array_search('-e', $args, true))
363
-        ) {
364
-            $this->emacsMode = true;
365
-            unset($args[$key]);
366
-        }
367
-
368
-        if (false !== ($key = array_search('-verbose', $args, true))) {
369
-            self::$msgOutputLevel = Project::MSG_VERBOSE;
370
-            unset($args[$key]);
371
-        }
372
-
373
-        if (false !== ($key = array_search('-debug', $args, true))) {
374
-            self::$msgOutputLevel = Project::MSG_DEBUG;
375
-            unset($args[$key]);
376
-        }
377
-
378
-        if (
379
-            false !== ($key = array_search('-silent', $args, true))
380
-            || false !== ($key = array_search('-S', $args, true))
381
-        ) {
382
-            $this->silent = true;
383
-            unset($args[$key]);
384
-        }
385
-
386
-        if (false !== ($key = array_search('-propertyfileoverride', $args, true))) {
387
-            $this->propertyFileOverride = true;
388
-            unset($args[$key]);
389
-        }
390
-
391
-        // 3) Finally, cycle through to parse remaining args
392
-        //
393
-        $keys = array_keys($args); // Use keys and iterate to max(keys) since there may be some gaps
394
-        $max = $keys ? max($keys) : -1;
395
-        for ($i = 0; $i <= $max; ++$i) {
396
-            if (!array_key_exists($i, $args)) {
397
-                // skip this argument, since it must have been removed above.
398
-                continue;
399
-            }
400
-
401
-            $arg = $args[$i];
402
-
403
-            if ('-logfile' == $arg) {
404
-                try {
405
-                    // see: http://phing.info/trac/ticket/65
406
-                    if (!isset($args[$i + 1])) {
407
-                        $msg = "You must specify a log file when using the -logfile argument\n";
408
-
409
-                        throw new ConfigurationException($msg);
410
-                    }
411
-
412
-                    $logFile = new File($args[++$i]);
413
-                    $out = new FileOutputStream($logFile); // overwrite
414
-                    self::setOutputStream($out);
415
-                    self::setErrorStream($out);
416
-                    self::$isLogFileUsed = true;
417
-                } catch (IOException $ioe) {
418
-                    $msg = 'Cannot write on the specified log file. Make sure the path exists and you have write permissions.';
419
-
420
-                    throw new ConfigurationException($msg, $ioe);
421
-                }
422
-            } elseif ('-buildfile' == $arg || '-file' == $arg || '-f' == $arg) {
423
-                if (!isset($args[$i + 1])) {
424
-                    $msg = 'You must specify a buildfile when using the -buildfile argument.';
425
-
426
-                    throw new ConfigurationException($msg);
427
-                }
428
-
429
-                $this->buildFile = new File($args[++$i]);
430
-            } elseif ('-listener' == $arg) {
431
-                if (!isset($args[$i + 1])) {
432
-                    $msg = 'You must specify a listener class when using the -listener argument';
433
-
434
-                    throw new ConfigurationException($msg);
435
-                }
436
-
437
-                $this->listeners[] = $args[++$i];
438
-            } elseif (StringHelper::startsWith('-D', $arg)) {
439
-                // Evaluating the property information //
440
-                // Checking whether arg. is not just a switch, and next arg. does not starts with switch identifier
441
-                if (('-D' == $arg) && (!StringHelper::startsWith('-', $args[$i + 1]))) {
442
-                    $name = $args[++$i];
443
-                } else {
444
-                    $name = substr($arg, 2);
445
-                }
446
-
447
-                $value = null;
448
-                $posEq = strpos($name, '=');
449
-                if (false !== $posEq) {
450
-                    $value = substr($name, $posEq + 1);
451
-                    $name = substr($name, 0, $posEq);
452
-                } elseif ($i < count($args) - 1 && !StringHelper::startsWith('-D', $args[$i + 1])) {
453
-                    $value = $args[++$i];
454
-                }
455
-                self::$definedProps->setProperty($name, $value);
456
-            } elseif ('-logger' == $arg) {
457
-                if (!isset($args[$i + 1])) {
458
-                    $msg = 'You must specify a classname when using the -logger argument';
459
-
460
-                    throw new ConfigurationException($msg);
461
-                }
462
-
463
-                $this->loggerClassname = $args[++$i];
464
-            } elseif ('-no-strict' == $arg) {
465
-                $this->strictMode = false;
466
-            } elseif ('-strict' == $arg) {
467
-                $this->strictMode = true;
468
-            } elseif ('-inputhandler' == $arg) {
469
-                if (null !== $this->inputHandlerClassname) {
470
-                    throw new ConfigurationException('Only one input handler class may be specified.');
471
-                }
472
-                if (!isset($args[$i + 1])) {
473
-                    $msg = 'You must specify a classname when using the -inputhandler argument';
474
-
475
-                    throw new ConfigurationException($msg);
476
-                }
477
-
478
-                $this->inputHandlerClassname = $args[++$i];
479
-            } elseif ('-propertyfile' === $arg) {
480
-                $i = $this->handleArgPropertyFile($args, $i);
481
-            } elseif ('-keep-going' === $arg || '-k' === $arg) {
482
-                $this->keepGoingMode = true;
483
-            } elseif ('-longtargets' == $arg) {
484
-                self::$definedProps->setProperty('phing.showlongtargets', 1);
485
-            } elseif ('-projecthelp' == $arg || '-targets' == $arg || '-list' == $arg || '-l' == $arg || '-p' == $arg) {
486
-                // set the flag to display the targets and quit
487
-                $this->projectHelp = true;
488
-            } elseif ('-find' == $arg) {
489
-                // eat up next arg if present, default to build.xml
490
-                if ($i < count($args) - 1) {
491
-                    $this->searchForThis = $args[++$i];
492
-                } else {
493
-                    $this->searchForThis = self::DEFAULT_BUILD_FILENAME;
494
-                }
495
-            } elseif ('-' == substr($arg, 0, 1)) {
496
-                // we don't have any more args
497
-                self::printUsage();
498
-                self::$err->write(PHP_EOL);
499
-
500
-                throw new ConfigurationException('Unknown argument: ' . $arg);
501
-            } else {
502
-                // if it's no other arg, it may be the target
503
-                $this->targets[] = $arg;
504
-            }
505
-        }
506
-
507
-        // if buildFile was not specified on the command line,
508
-        if (null === $this->buildFile) {
509
-            // but -find then search for it
510
-            if (null !== $this->searchForThis) {
511
-                $this->buildFile = $this->findBuildFile(self::getProperty('user.dir'), $this->searchForThis);
512
-            } else {
513
-                $this->buildFile = new File(self::DEFAULT_BUILD_FILENAME);
514
-            }
515
-        }
516
-
517
-        try {
518
-            // make sure buildfile (or buildfile.dist) exists
519
-            if (!$this->buildFile->exists()) {
520
-                $distFile = new File($this->buildFile->getAbsolutePath() . '.dist');
521
-                if (!$distFile->exists()) {
522
-                    throw new ConfigurationException(
523
-                        'Buildfile: ' . $this->buildFile->__toString() . ' does not exist!'
524
-                    );
525
-                }
526
-                $this->buildFile = $distFile;
527
-            }
528
-
529
-            // make sure it's not a directory
530
-            if ($this->buildFile->isDirectory()) {
531
-                throw new ConfigurationException('Buildfile: ' . $this->buildFile->__toString() . ' is a dir!');
532
-            }
533
-        } catch (IOException $e) {
534
-            // something else happened, buildfile probably not readable
535
-            throw new ConfigurationException('Buildfile: ' . $this->buildFile->__toString() . ' is not readable!');
536
-        }
537
-
538
-        $this->loadPropertyFiles();
539
-
540
-        $this->readyToRun = true;
541
-    }
542
-
543
-    /**
544
-     * Prints the usage of how to use this class.
545
-     */
546
-    public static function printUsage()
547
-    {
548
-        $msg = '';
549
-        $msg .= 'phing [options] [target [target2 [target3] ...]]' . PHP_EOL;
550
-        $msg .= 'Options: ' . PHP_EOL;
551
-        $msg .= '  -h -help               print this message' . PHP_EOL;
552
-        $msg .= '  -l -list               list available targets in this project' . PHP_EOL;
553
-        $msg .= '  -i -init [file]        generates an initial buildfile' . PHP_EOL;
554
-        $msg .= '  -v -version            print the version information and exit' . PHP_EOL;
555
-        $msg .= '  -q -quiet              be extra quiet' . PHP_EOL;
556
-        $msg .= '  -S -silent             print nothing but task outputs and build failures' . PHP_EOL;
557
-        $msg .= '  -verbose               be extra verbose' . PHP_EOL;
558
-        $msg .= '  -debug                 print debugging information' . PHP_EOL;
559
-        $msg .= '  -emacs, -e             produce logging information without adornments' . PHP_EOL;
560
-        $msg .= '  -diagnostics           print diagnostics information' . PHP_EOL;
561
-        $msg .= '  -strict                runs build in strict mode, considering a warning as error' . PHP_EOL;
562
-        $msg .= '  -no-strict             runs build normally (overrides buildfile attribute)' . PHP_EOL;
563
-        $msg .= '  -longtargets           show target descriptions during build' . PHP_EOL;
564
-        $msg .= '  -logfile <file>        use given file for log' . PHP_EOL;
565
-        $msg .= '  -logger <classname>    the class which is to perform logging' . PHP_EOL;
566
-        $msg .= '  -listener <classname>  add an instance of class as a project listener' . PHP_EOL;
567
-        $msg .= '  -f -buildfile <file>   use given buildfile' . PHP_EOL;
568
-        $msg .= '  -D<property>=<value>   use value for given property' . PHP_EOL;
569
-        $msg .= '  -keep-going, -k        execute all targets that do not depend' . PHP_EOL;
570
-        $msg .= '                         on failed target(s)' . PHP_EOL;
571
-        $msg .= '  -propertyfile <file>   load all properties from file' . PHP_EOL;
572
-        $msg .= '  -propertyfileoverride  values in property file override existing values' . PHP_EOL;
573
-        $msg .= '  -find <file>           search for buildfile towards the root of the' . PHP_EOL;
574
-        $msg .= '                         filesystem and use it' . PHP_EOL;
575
-        $msg .= '  -inputhandler <file>   the class to use to handle user input' . PHP_EOL;
576
-        //$msg .= "  -recursive <file>      search for buildfile downwards and use it" . PHP_EOL;
577
-        $msg .= PHP_EOL;
578
-        $msg .= 'Report bugs to https://github.com/phingofficial/phing/issues' . PHP_EOL;
579
-        self::$err->write($msg);
580
-    }
581
-
582
-    /**
583
-     * Prints the current Phing version.
584
-     */
585
-    public static function printVersion()
586
-    {
587
-        self::$out->write(self::getPhingVersion() . PHP_EOL);
588
-    }
589
-
590
-    /**
591
-     * Gets the current Phing version based on VERSION.TXT file.
592
-     *
593
-     * @return string
594
-     * @throws ConfigurationException
595
-     *
596
-     */
597
-    public static function getPhingVersion(): string
598
-    {
599
-        $versionPath = self::getResourcePath('phing/etc/VERSION.TXT');
600
-        if (null === $versionPath) {
601
-            $versionPath = self::getResourcePath('etc/VERSION.TXT');
602
-        }
603
-        if (null === $versionPath) {
604
-            throw new ConfigurationException('No VERSION.TXT file found; try setting phing.home environment variable.');
605
-        }
606
-
607
-        try { // try to read file
608
-            $file = new File($versionPath);
609
-            $reader = new FileReader($file);
610
-            $phingVersion = trim($reader->read());
611
-        } catch (IOException $iox) {
612
-            throw new ConfigurationException("Can't read version information file");
613
-        }
614
-
615
-        $basePath = dirname(__DIR__, 2);
616
-
617
-        $version = new Version($phingVersion, $basePath);
618
-
619
-        return 'Phing ' . $version->getVersion();
620
-    }
621
-
622
-    /**
623
-     * Looks on include path for specified file.
624
-     *
625
-     * @param string $path
626
-     *
627
-     * @return string|null file found (null if no file found)
628
-     */
629
-    public static function getResourcePath($path): ?string
630
-    {
631
-        if (null === self::$importPaths) {
632
-            self::$importPaths = self::explodeIncludePath();
633
-        }
634
-
635
-        $path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $path);
636
-
637
-        foreach (self::$importPaths as $prefix) {
638
-            $testPath = $prefix . DIRECTORY_SEPARATOR . $path;
639
-            if (file_exists($testPath)) {
640
-                return $testPath;
641
-            }
642
-        }
643
-
644
-        // Check for the property phing.home
645
-        $homeDir = self::getProperty(self::PHING_HOME);
646
-        if ($homeDir) {
647
-            $testPath = $homeDir . DIRECTORY_SEPARATOR . $path;
648
-            if (file_exists($testPath)) {
649
-                return $testPath;
650
-            }
651
-        }
652
-
653
-        // Check for the phing home of phar archive
654
-        if (0 === strpos(self::$importPaths[0], 'phar://')) {
655
-            $testPath = self::$importPaths[0] . '/../' . $path;
656
-            if (file_exists($testPath)) {
657
-                return $testPath;
658
-            }
659
-        }
660
-
661
-        // Do one additional check based on path of current file (Phing.php)
662
-        $maybeHomeDir = realpath(__DIR__ . DIRECTORY_SEPARATOR);
663
-        $testPath = $maybeHomeDir . DIRECTORY_SEPARATOR . $path;
664
-        if (file_exists($testPath)) {
665
-            return $testPath;
666
-        }
667
-
668
-        return null;
669
-    }
670
-
671
-    /**
672
-     * Explode an include path into an array.
673
-     *
674
-     * If no path provided, uses current include_path. Works around issues that
675
-     * occur when the path includes stream schemas.
676
-     *
677
-     * Pulled from Zend_Loader::explodeIncludePath() in ZF1.
678
-     *
679
-     * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
680
-     * @license   http://framework.zend.com/license/new-bsd New BSD License
681
-     *
682
-     * @param null|string $path
683
-     *
684
-     * @return array
685
-     */
686
-    public static function explodeIncludePath($path = null)
687
-    {
688
-        if (null === $path) {
689
-            $path = get_include_path();
690
-        }
691
-
692
-        if (PATH_SEPARATOR === ':') {
693
-            // On *nix systems, include_paths which include paths with a stream
694
-            // schema cannot be safely explode'd, so we have to be a bit more
695
-            // intelligent in the approach.
696
-            $paths = preg_split('#:(?!//)#', $path);
697
-        } else {
698
-            $paths = explode(PATH_SEPARATOR, $path);
699
-        }
700
-
701
-        return $paths;
702
-    }
703
-
704
-    /**
705
-     * Returns property value for a System property.
706
-     * System properties are "global" properties like application.startdir,
707
-     * and user.dir.  Many of these correspond to similar properties in Java
708
-     * or Ant.
709
-     *
710
-     * @param string $propName
711
-     *
712
-     * @return string value of found property (or null, if none found)
713
-     */
714
-    public static function getProperty($propName)
715
-    {
716
-        // some properties are detemined on each access
717
-        // some are cached, see below
718
-
719
-        // default is the cached value:
720
-        $val = self::$properties[$propName] ?? null;
721
-
722
-        // special exceptions
723
-        switch ($propName) {
724
-            case 'user.dir':
725
-                $val = getcwd();
726
-
727
-                break;
728
-        }
729
-
730
-        return $val;
731
-    }
732
-
733
-    /**
734
-     * Creates generic buildfile.
735
-     *
736
-     * @param string $path
737
-     */
738
-    public static function init($path)
739
-    {
740
-        if ($buildfilePath = self::initPath($path)) {
741
-            self::initWrite($buildfilePath);
742
-        }
743
-    }
744
-
745
-    /**
746
-     * Returns buildfile's path.
747
-     *
748
-     * @param $path
749
-     *
750
-     * @return string
751
-     * @throws ConfigurationException
752
-     *
753
-     */
754
-    protected static function initPath($path)
755
-    {
756
-        // Fallback
757
-        if (empty($path)) {
758
-            $defaultDir = self::getProperty('application.startdir');
759
-            $path = $defaultDir . DIRECTORY_SEPARATOR . self::DEFAULT_BUILD_FILENAME;
760
-        }
761
-
762
-        // Adding filename if necessary
763
-        if (is_dir($path)) {
764
-            $path .= DIRECTORY_SEPARATOR . self::DEFAULT_BUILD_FILENAME;
765
-        }
766
-
767
-        // Check if path is available
768
-        $dirname = dirname($path);
769
-        if (is_dir($dirname) && !is_file($path)) {
770
-            return $path;
771
-        }
772
-
773
-        // Path is valid, but buildfile already exists
774
-        if (is_file($path)) {
775
-            throw new ConfigurationException('Buildfile already exists.');
776
-        }
777
-
778
-        throw new ConfigurationException('Invalid path for sample buildfile.');
779
-    }
780
-
781
-    /**
782
-     * Writes sample buildfile.
783
-     *
784
-     * If $buildfilePath does not exist, the buildfile is created.
785
-     *
786
-     * @param $buildfilePath buildfile's location
787
-     *
788
-     * @throws ConfigurationException
789
-     */
790
-    protected static function initWrite($buildfilePath): void
791
-    {
792
-        // Overwriting protection
793
-        if (file_exists($buildfilePath)) {
794
-            throw new ConfigurationException('Cannot overwrite existing file.');
795
-        }
796
-
797
-        file_put_contents($buildfilePath, self::DEFAULT_BUILD_CONTENT);
798
-    }
799
-
800
-    /**
801
-     * Sets the stream to use for standard (non-error) output.
802
-     *
803
-     * @param OutputStream $stream the stream to use for standard output
804
-     */
805
-    public static function setOutputStream(OutputStream $stream)
806
-    {
807
-        self::$out = $stream;
808
-    }
809
-
810
-    /**
811
-     * Sets the stream to use for error output.
812
-     *
813
-     * @param OutputStream $stream the stream to use for error output
814
-     */
815
-    public static function setErrorStream(OutputStream $stream): void
816
-    {
817
-        self::$err = $stream;
818
-    }
819
-
820
-    /**
821
-     * Handle the -propertyfile argument.
822
-     *
823
-     * @throws ConfigurationException
824
-     * @throws IOException
825
-     */
826
-    private function handleArgPropertyFile(array $args, int $pos): int
827
-    {
828
-        if (!isset($args[$pos + 1])) {
829
-            throw new ConfigurationException('You must specify a filename when using the -propertyfile argument');
830
-        }
831
-
832
-        $this->propertyFiles[] = $args[++$pos];
833
-
834
-        return $pos;
835
-    }
836
-
837
-    /**
838
-     * Search parent directories for the build file.
839
-     *
840
-     * Takes the given target as a suffix to append to each
841
-     * parent directory in search of a build file.  Once the
842
-     * root of the file-system has been reached an exception
843
-     * is thrown.
844
-     *
845
-     * @param string $start start file path
846
-     * @param string $suffix suffix filename to look for in parents
847
-     *
848
-     * @return File A handle to the build file
849
-     * @throws ConfigurationException
850
-     *
851
-     */
852
-    private function findBuildFile($start, $suffix)
853
-    {
854
-        if (self::getMsgOutputLevel() >= Project::MSG_INFO) {
855
-            self::$out->write('Searching for ' . $suffix . ' ...' . PHP_EOL);
856
-        }
857
-
858
-        $parent = new File((new File($start))->getAbsolutePath());
859
-        $file = new File($parent, $suffix);
860
-
861
-        // check if the target file exists in the current directory
862
-        while (!$file->exists()) {
863
-            // change to parent directory
864
-            $parent = $parent->getParentFile();
865
-
866
-            // if parent is null, then we are at the root of the fs,
867
-            // complain that we can't find the build file.
868
-            if (null === $parent) {
869
-                throw new ConfigurationException('Could not locate a build file!');
870
-            }
871
-            // refresh our file handle
872
-            $file = new File($parent, $suffix);
873
-        }
874
-
875
-        return $file;
876
-    }
877
-
878
-    /**
879
-     * Making output level a static property so that this property
880
-     * can be accessed by other parts of the system, enabling
881
-     * us to display more information -- e.g. backtraces -- for "debug" level.
882
-     *
883
-     * @return int
884
-     */
885
-    public static function getMsgOutputLevel()
886
-    {
887
-        return self::$msgOutputLevel;
888
-    }
889
-
890
-    /**
891
-     * @throws IOException
892
-     */
893
-    private function loadPropertyFiles(): void
894
-    {
895
-        foreach ($this->propertyFiles as $filename) {
896
-            $fileParserFactory = new FileParserFactory();
897
-            $fileParser = $fileParserFactory->createParser(pathinfo($filename, PATHINFO_EXTENSION));
898
-            $p = new Properties(null, $fileParser);
899
-
900
-            try {
901
-                $p->load(new File($filename));
902
-            } catch (IOException $e) {
903
-                self::$out->write('Could not load property file ' . $filename . ': ' . $e->getMessage());
904
-            }
905
-            foreach ($p->getProperties() as $prop => $value) {
906
-                self::$definedProps->setProperty($prop, $value);
907
-            }
908
-        }
909
-    }
910
-
911
-    /**
912
-     * Close logfiles, if we have been writing to them.
913
-     *
914
-     * @since Phing 2.3.0
915
-     */
916
-    private static function handleLogfile(): void
917
-    {
918
-        if (self::$isLogFileUsed) {
919
-            self::$err->close();
920
-            self::$out->close();
921
-        }
922
-    }
923
-
924
-    /**
925
-     * Prints the message of the Exception if it's not null.
926
-     */
927
-    public static function printMessage(Throwable $t): void
928
-    {
929
-        if (null === self::$err) { // Make sure our error output is initialized
930
-            self::initializeOutputStreams();
931
-        }
932
-        if (self::getMsgOutputLevel() >= Project::MSG_VERBOSE) {
933
-            self::$err->write((string) $t . PHP_EOL);
934
-        } else {
935
-            self::$err->write($t->getMessage() . PHP_EOL);
936
-        }
937
-    }
938
-
939
-    /**
940
-     * Sets the stdout and stderr streams if they are not already set.
941
-     */
942
-    private static function initializeOutputStreams()
943
-    {
944
-        if (null === self::$out) {
945
-            if (!defined('STDOUT')) {
946
-                self::$out = new OutputStream(fopen('php://stdout', 'w'));
947
-            } else {
948
-                self::$out = new OutputStream(STDOUT);
949
-            }
950
-        }
951
-        if (null === self::$err) {
952
-            if (!defined('STDERR')) {
953
-                self::$err = new OutputStream(fopen('php://stderr', 'w'));
954
-            } else {
955
-                self::$err = new OutputStream(STDERR);
956
-            }
957
-        }
958
-    }
959
-
960
-    /**
961
-     * This operation is expected to call `exit($int)`, which
962
-     * is what the base version does.
963
-     * However, it is possible to do something else.
964
-     *
965
-     * @param int $exitCode code to exit with
966
-     */
967
-    protected static function statusExit($exitCode): void
968
-    {
969
-        Phing::shutdown();
970
-
971
-        exit($exitCode);
972
-    }
973
-
974
-    /**
975
-     * Performs any shutdown routines, such as stopping timers.
976
-     *
977
-     * @throws IOException
978
-     */
979
-    public static function shutdown(): void
980
-    {
981
-        FileSystem::getFileSystem()::deleteFilesOnExit();
982
-        self::$msgOutputLevel = Project::MSG_INFO;
983
-        self::restoreIni();
984
-        self::getTimer()->stop();
985
-    }
986
-
987
-    /**
988
-     * Restores [most] PHP INI values to their pre-Phing state.
989
-     *
990
-     * Currently the following settings are not restored:
991
-     *  - max_execution_time (because getting current time limit is not possible)
992
-     *  - memory_limit (which may have been increased by Phing)
993
-     */
994
-    private static function restoreIni(): void
995
-    {
996
-        foreach (self::$origIniSettings as $settingName => $settingValue) {
997
-            switch ($settingName) {
998
-                case 'error_reporting':
999
-                    error_reporting($settingValue);
1000
-
1001
-                    break;
1002
-
1003
-                default:
1004
-                    ini_set($settingName, $settingValue);
1005
-            }
1006
-        }
1007
-    }
1008
-
1009
-    /**
1010
-     * Returns reference to DefaultClock object.
1011
-     */
1012
-    public static function getTimer(): DefaultClock
1013
-    {
1014
-        if (null === self::$timer) {
1015
-            self::$timer = new DefaultClock();
1016
-        }
1017
-
1018
-        return self::$timer;
1019
-    }
1020
-
1021
-    /**
1022
-     * This sets a property that was set via command line or otherwise passed into Phing.
1023
-     *
1024
-     * @param string $name
1025
-     * @param mixed $value
1026
-     *
1027
-     * @return mixed value of found property (or null, if none found)
1028
-     */
1029
-    public static function setDefinedProperty($name, $value)
1030
-    {
1031
-        return self::$definedProps->setProperty($name, $value);
1032
-    }
1033
-
1034
-    /**
1035
-     * Executes the build.
1036
-     *
1037
-     * @throws IOException
1038
-     * @throws Throwable
1039
-     */
1040
-    public function runBuild(): void
1041
-    {
1042
-        if (!$this->readyToRun) {
1043
-            return;
1044
-        }
1045
-
1046
-        $project = new Project();
1047
-
1048
-        self::setCurrentProject($project);
1049
-        set_error_handler(['Phing\Phing', 'handlePhpError']);
1050
-
1051
-        $error = null;
1052
-
1053
-        try {
1054
-            $this->addBuildListeners($project);
1055
-            $this->addInputHandler($project);
1056
-
1057
-            // set this right away, so that it can be used in logging.
1058
-            $project->setUserProperty('phing.file', $this->buildFile->getAbsolutePath());
1059
-            $project->setUserProperty('phing.dir', dirname($this->buildFile->getAbsolutePath()));
1060
-            $project->setUserProperty('phing.version', static::getPhingVersion());
1061
-            $project->fireBuildStarted();
1062
-            $project->init();
1063
-            $project->setKeepGoingMode($this->keepGoingMode);
1064
-
1065
-            $e = self::$definedProps->keys();
1066
-            while (count($e)) {
1067
-                $arg = (string) array_shift($e);
1068
-                $value = (string) self::$definedProps->getProperty($arg);
1069
-                $project->setUserProperty($arg, $value);
1070
-            }
1071
-            unset($e);
1072
-
1073
-            // first use the Configurator to create the project object
1074
-            // from the given build file.
1075
-
1076
-            ProjectConfigurator::configureProject($project, $this->buildFile);
1077
-
1078
-            // Set the project mode
1079
-            $project->setStrictMode(StringHelper::booleanValue($this->strictMode));
1080
-
1081
-            // make sure that minimum required phing version is satisfied
1082
-            $this->comparePhingVersion($project->getPhingVersion());
1083
-
1084
-            if ($this->projectHelp) {
1085
-                $this->printDescription($project);
1086
-                $this->printTargets($project);
1087
-
1088
-                return;
1089
-            }
1090
-
1091
-            // make sure that we have a target to execute
1092
-            if (0 === count($this->targets)) {
1093
-                $this->targets[] = $project->getDefaultTarget();
1094
-            }
1095
-
1096
-            $project->executeTargets($this->targets);
1097
-        } catch (Throwable $t) {
1098
-            $error = $t;
1099
-
1100
-            throw $t;
1101
-        } finally {
1102
-            if (!$this->projectHelp) {
1103
-                try {
1104
-                    $project->fireBuildFinished($error);
1105
-                } catch (Exception $e) {
1106
-                    self::$err->write('Caught an exception while logging the end of the build.  Exception was:' . PHP_EOL);
1107
-                    self::$err->write($e->getTraceAsString());
1108
-                    if (null !== $error) {
1109
-                        self::$err->write('There has been an error prior to that:' . PHP_EOL);
1110
-                        self::$err->write($error->getTraceAsString());
1111
-                    }
1112
-
1113
-                    throw new BuildException($error);
1114
-                }
1115
-            } elseif (null !== $error) {
1116
-                $project->log($error->getMessage(), Project::MSG_ERR);
1117
-            }
1118
-
1119
-            restore_error_handler();
1120
-            self::unsetCurrentProject();
1121
-        }
1122
-    }
1123
-
1124
-    /**
1125
-     * Bind any registered build listeners to this project.
1126
-     *
1127
-     * This means adding the logger and any build listeners that were specified
1128
-     * with -listener arg.
1129
-     *
1130
-     * @throws BuildException
1131
-     * @throws ConfigurationException
1132
-     */
1133
-    private function addBuildListeners(Project $project)
1134
-    {
1135
-        // Add the default listener
1136
-        $project->addBuildListener($this->createLogger());
1137
-
1138
-        foreach ($this->listeners as $listenerClassname) {
1139
-            try {
1140
-                $clz = Phing::import($listenerClassname);
1141
-            } catch (Exception $e) {
1142
-                $msg = 'Unable to instantiate specified listener '
1143
-                    . 'class ' . $listenerClassname . ' : '
1144
-                    . $e->getMessage();
1145
-
1146
-                throw new ConfigurationException($msg);
1147
-            }
1148
-
1149
-            $listener = new $clz();
1150
-
1151
-            if ($listener instanceof StreamRequiredBuildLogger) {
1152
-                throw new ConfigurationException('Unable to add ' . $listenerClassname . ' as a listener, since it requires explicit error/output streams. (You can specify it as a -logger.)');
1153
-            }
1154
-            $project->addBuildListener($listener);
1155
-        }
1156
-    }
1157
-
1158
-    /**
1159
-     * Creates the default build logger for sending build events to the log.
1160
-     *
1161
-     * @return BuildLogger The created Logger
1162
-     * @throws BuildException
1163
-     *
1164
-     */
1165
-    private function createLogger()
1166
-    {
1167
-        if ($this->silent) {
1168
-            $logger = new SilentLogger();
1169
-            self::$msgOutputLevel = Project::MSG_WARN;
1170
-        } elseif (null !== $this->loggerClassname) {
1171
-            self::import($this->loggerClassname);
1172
-            // get class name part
1173
-            $classname = self::import($this->loggerClassname);
1174
-            $logger = new $classname();
1175
-            if (!($logger instanceof BuildLogger)) {
1176
-                throw new BuildException($classname . ' does not implement the BuildLogger interface.');
1177
-            }
1178
-        } else {
1179
-            $logger = new DefaultLogger();
1180
-        }
1181
-        $logger->setMessageOutputLevel(self::$msgOutputLevel);
1182
-        $logger->setOutputStream(self::$out);
1183
-        $logger->setErrorStream(self::$err);
1184
-        $logger->setEmacsMode($this->emacsMode);
1185
-
1186
-        return $logger;
1187
-    }
1188
-
1189
-    /**
1190
-     * Import a class, supporting the following conventions:
1191
-     * - PEAR style (@see http://pear.php.net/manual/en/standards.naming.php)
1192
-     * - PSR-0 (@see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md).
1193
-     *
1194
-     * @param string $classname Name of class
1195
-     * @param mixed $classpath String or object supporting __toString()
1196
-     *
1197
-     * @throws BuildException - if cannot find the specified file
1198
-     *
1199
-     * @return string the unqualified classname (which can be instantiated)
1200
-     */
1201
-    public static function import($classname, $classpath = null)
1202
-    {
1203
-        // first check to see that the class specified hasn't already been included.
1204
-        if (class_exists($classname)) {
1205
-            return $classname;
1206
-        }
1207
-
1208
-        $filename = strtr($classname, ['_' => DIRECTORY_SEPARATOR, '\\' => DIRECTORY_SEPARATOR]) . '.php';
1209
-
1210
-        Phing::importFile($filename, $classpath);
1211
-
1212
-        return $classname;
1213
-    }
1214
-
1215
-    /**
1216
-     * Import a PHP file.
1217
-     *
1218
-     * This used to be named __import, however PHP has reserved all method names
1219
-     * with a double underscore prefix for future use.
1220
-     *
1221
-     * @param string $path Path to the PHP file
1222
-     * @param mixed $classpath String or object supporting __toString()
1223
-     *
1224
-     * @throws ConfigurationException
1225
-     */
1226
-    public static function importFile($path, $classpath = null)
1227
-    {
1228
-        if ($classpath) {
1229
-            // Apparently casting to (string) no longer invokes __toString() automatically.
1230
-            if (is_object($classpath)) {
1231
-                $classpath = $classpath->__toString();
1232
-            }
1233
-
1234
-            // classpaths are currently additive, but we also don't want to just
1235
-            // indiscriminantly prepand/append stuff to the include_path.  This means
1236
-            // we need to parse current incldue_path, and prepend any
1237
-            // specified classpath locations that are not already in the include_path.
1238
-            //
1239
-            // NOTE:  the reason why we do it this way instead of just changing include_path
1240
-            // and then changing it back, is that in many cases applications (e.g. Propel) will
1241
-            // include/require class files from within method calls.  This means that not all
1242
-            // necessary files will be included in this import() call, and hence we can't
1243
-            // change the include_path back without breaking those apps.  While this method could
1244
-            // be more expensive than switching & switching back (not sure, but maybe), it makes it
1245
-            // possible to write far less expensive run-time applications (e.g. using Propel), which is
1246
-            // really where speed matters more.
1247
-
1248
-            $curr_parts = Phing::explodeIncludePath();
1249
-            $add_parts = Phing::explodeIncludePath($classpath);
1250
-            $new_parts = array_diff($add_parts, $curr_parts);
1251
-            if ($new_parts) {
1252
-                set_include_path(implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts)));
1253
-            }
1254
-        }
1255
-
1256
-        $ret = include_once $path;
1257
-
1258
-        if (false === $ret) {
1259
-            $msg = "Error importing {$path}";
1260
-            if (self::getMsgOutputLevel() >= Project::MSG_DEBUG) {
1261
-                $x = new Exception('for-path-trace-only');
1262
-                $msg .= $x->getTraceAsString();
1263
-            }
1264
-
1265
-            throw new ConfigurationException($msg);
1266
-        }
1267
-    }
1268
-
1269
-    /**
1270
-     * Creates the InputHandler and adds it to the project.
1271
-     *
1272
-     * @param Project $project the project instance
1273
-     *
1274
-     * @throws ConfigurationException
1275
-     */
1276
-    private function addInputHandler(Project $project): void
1277
-    {
1278
-        if (null === $this->inputHandlerClassname) {
1279
-            $handler = new ConsoleInputHandler(STDIN, new ConsoleOutput());
1280
-        } else {
1281
-            try {
1282
-                $clz = Phing::import($this->inputHandlerClassname);
1283
-                $handler = new $clz();
1284
-                if (null !== $project && method_exists($handler, 'setProject')) {
1285
-                    $handler->setProject($project);
1286
-                }
1287
-            } catch (Exception $e) {
1288
-                $msg = 'Unable to instantiate specified input handler '
1289
-                    . 'class ' . $this->inputHandlerClassname . ' : '
1290
-                    . $e->getMessage();
1291
-
1292
-                throw new ConfigurationException($msg);
1293
-            }
1294
-        }
1295
-        $project->setInputHandler($handler);
1296
-    }
1297
-
1298
-    /**
1299
-     * @param string $version
1300
-     *
1301
-     * @throws BuildException
1302
-     * @throws ConfigurationException
1303
-     */
1304
-    private function comparePhingVersion($version): void
1305
-    {
1306
-        $current = strtolower(self::getPhingVersion());
1307
-        $current = trim(str_replace('phing', '', $current));
1308
-
1309
-        // make sure that version checks are not applied to trunk
1310
-        if ('dev' === $current) {
1311
-            return;
1312
-        }
1313
-
1314
-        if (-1 == version_compare($current, $version)) {
1315
-            throw new BuildException(
1316
-                sprintf('Incompatible Phing version (%s). Version "%s" required.', $current, $version)
1317
-            );
1318
-        }
1319
-    }
1320
-
1321
-    /**
1322
-     * Print the project description, if any.
1323
-     *
1324
-     * @throws IOException
1325
-     */
1326
-    public function printDescription(Project $project): void
1327
-    {
1328
-        if (null !== $project->getDescription()) {
1329
-            $project->log($project->getDescription());
1330
-        }
1331
-    }
1332
-
1333
-    /**
1334
-     * Print out a list of all targets in the current buildfile.
1335
-     */
1336
-    public function printTargets(Project $project)
1337
-    {
1338
-        $visibleTargets = array_filter($project->getTargets(), function (Target $target) {
1339
-            return !$target->isHidden() && !empty($target->getName());
1340
-        });
1341
-        $padding = array_reduce($visibleTargets, function (int $carry, Target $target) {
1342
-            return max(strlen($target->getName()), $carry);
1343
-        }, 0);
1344
-        $categories = [
1345
-            'Default target:' => array_filter($visibleTargets, function (Target $target) use ($project) {
1346
-                return trim(strval($target)) === $project->getDefaultTarget();
1347
-            }),
1348
-            'Main targets:' => array_filter($visibleTargets, function (Target $target) {
1349
-                return !empty($target->getDescription());
1350
-            }),
1351
-            'Subtargets:' => array_filter($visibleTargets, function (Target $target) {
1352
-                return empty($target->getDescription());
1353
-            }),
1354
-        ];
1355
-        foreach ($categories as $title => $targets) {
1356
-            $targetList = $this->generateTargetList($title, $targets, $padding);
1357
-            $project->log($targetList, Project::MSG_WARN);
1358
-        }
1359
-    }
1360
-
1361
-    /**
1362
-     * Returns a formatted list of target names with an optional description.
1363
-     *
1364
-     * @param string $title Title for this list
1365
-     * @param Target[] $targets Targets in this list
1366
-     * @param int $padding Padding for name column
1367
-     */
1368
-    private function generateTargetList(string $title, array $targets, int $padding): string
1369
-    {
1370
-        usort($targets, function (Target $a, Target $b) {
1371
-            return $a->getName() <=> $b->getName();
1372
-        });
1373
-
1374
-        $header = <<<HEADER
1375
-            {$title}
1376
-            -------------------------------------------------------------------------------
1377
-
1378
-            HEADER;
1379
-
1380
-        $getDetails = function (Target $target) use ($padding): string {
1381
-            $details = [];
1382
-            if (!empty($target->getDescription())) {
1383
-                $details[] = $target->getDescription();
1384
-            }
1385
-            if (!empty($target->getDependencies())) {
1386
-                $details[] = ' - depends on: ' . implode(', ', $target->getDependencies());
1387
-            }
1388
-            if (!empty($target->getIf())) {
1389
-                $details[] = ' - if property: ' . $target->getIf();
1390
-            }
1391
-            if (!empty($target->getUnless())) {
1392
-                $details[] = ' - unless property: ' . $target->getUnless();
1393
-            }
1394
-            $detailsToString = function (?string $name, ?string $detail) use ($padding): string {
1395
-                return sprintf(" %-{$padding}s  %s", $name, $detail);
1396
-            };
1397
-
1398
-            return implode(PHP_EOL, array_map($detailsToString, [$target->getName()], $details));
1399
-        };
1400
-
1401
-        return $header . implode(PHP_EOL, array_map($getDetails, $targets)) . PHP_EOL;
1402
-    }
1403
-
1404
-    /**
1405
-     * Unsets the current Project.
1406
-     */
1407
-    public static function unsetCurrentProject(): void
1408
-    {
1409
-        self::$currentProject = null;
1410
-    }
1411
-
1412
-    /**
1413
-     * Error handler for PHP errors encountered during the build.
1414
-     * This uses the logging for the currently configured project.
1415
-     *
1416
-     * @param $level
1417
-     * @param string $message
1418
-     * @param $file
1419
-     * @param $line
1420
-     */
1421
-    public static function handlePhpError($level, $message, $file, $line)
1422
-    {
1423
-        // don't want to print suppressed errors
1424
-        if (error_reporting() > 0) {
1425
-            if (self::$phpErrorCapture) {
1426
-                self::$capturedPhpErrors[] = [
1427
-                    'message' => $message,
1428
-                    'level' => $level,
1429
-                    'line' => $line,
1430
-                    'file' => $file,
1431
-                ];
1432
-            } else {
1433
-                $message = '[PHP Error] ' . $message;
1434
-                $message .= ' [line ' . $line . ' of ' . $file . ']';
1435
-
1436
-                switch ($level) {
1437
-                    case E_USER_DEPRECATED:
1438
-                    case E_DEPRECATED:
1439
-                    case E_STRICT:
1440
-                    case E_NOTICE:
1441
-                    case E_USER_NOTICE:
1442
-                        self::log($message, Project::MSG_VERBOSE);
1443
-
1444
-                        break;
1445
-
1446
-                    case E_WARNING:
1447
-                    case E_USER_WARNING:
1448
-                        self::log($message, Project::MSG_WARN);
1449
-
1450
-                        break;
1451
-
1452
-                    case E_ERROR:
1453
-                    case E_USER_ERROR:
1454
-                    default:
1455
-                        self::log($message, Project::MSG_ERR);
1456
-                } // switch
1457
-            } // if phpErrorCapture
1458
-        } // if not @
1459
-    }
1460
-
1461
-    /**
1462
-     * A static convenience method to send a log to the current (last-setup) Project.
1463
-     * If there is no currently-configured Project, then this will do nothing.
1464
-     *
1465
-     * @param string $message
1466
-     * @param int $priority project::MSG_INFO, etc
1467
-     */
1468
-    public static function log($message, $priority = Project::MSG_INFO): void
1469
-    {
1470
-        $p = self::getCurrentProject();
1471
-        if ($p) {
1472
-            $p->log($message, $priority);
1473
-        }
1474
-    }
1475
-
1476
-    /**
1477
-     * Gets the current Project.
1478
-     *
1479
-     * @return Project current Project or NULL if none is set yet/still
1480
-     */
1481
-    public static function getCurrentProject()
1482
-    {
1483
-        return self::$currentProject;
1484
-    }
1485
-
1486
-    /**
1487
-     * Sets the current Project.
1488
-     *
1489
-     * @param Project $p
1490
-     */
1491
-    public static function setCurrentProject($p): void
1492
-    {
1493
-        self::$currentProject = $p;
1494
-    }
1495
-
1496
-    /**
1497
-     * Begins capturing PHP errors to a buffer.
1498
-     * While errors are being captured, they are not logged.
1499
-     */
1500
-    public static function startPhpErrorCapture(): void
1501
-    {
1502
-        self::$phpErrorCapture = true;
1503
-        self::$capturedPhpErrors = [];
1504
-    }
1505
-
1506
-    /**
1507
-     * Stops capturing PHP errors to a buffer.
1508
-     * The errors will once again be logged after calling this method.
1509
-     */
1510
-    public static function stopPhpErrorCapture(): void
1511
-    {
1512
-        self::$phpErrorCapture = false;
1513
-    }
1514
-
1515
-    /**
1516
-     * Clears the captured errors without affecting the starting/stopping of the capture.
1517
-     */
1518
-    public static function clearCapturedPhpErrors(): void
1519
-    {
1520
-        self::$capturedPhpErrors = [];
1521
-    }
1522
-
1523
-    /**
1524
-     * Gets any PHP errors that were captured to buffer.
1525
-     *
1526
-     * @return array array('message' => message, 'line' => line number, 'file' => file name, 'level' => error level)
1527
-     */
1528
-    public static function getCapturedPhpErrors()
1529
-    {
1530
-        return self::$capturedPhpErrors;
1531
-    }
1532
-
1533
-    /**
1534
-     * This gets a property that was set via command line or otherwise passed into Phing.
1535
-     * "Defined" in this case means "externally defined".  The reason this method exists is to
1536
-     * provide a public means of accessing commandline properties for (e.g.) logger or listener
1537
-     * scripts.  E.g. to specify which logfile to use, PearLogger needs to be able to access
1538
-     * the pear.log.name property.
1539
-     *
1540
-     * @param string $name
1541
-     *
1542
-     * @return string value of found property (or null, if none found)
1543
-     */
1544
-    public static function getDefinedProperty($name)
1545
-    {
1546
-        return self::$definedProps->getProperty($name);
1547
-    }
1548
-
1549
-    /**
1550
-     * Retuns reference to all properties.
1551
-     */
1552
-    public static function &getProperties()
1553
-    {
1554
-        return self::$properties;
1555
-    }
1556
-
1557
-    /**
1558
-     * Start up Phing.
1559
-     * Sets up the Phing environment but does not initiate the build process.
1560
-     *
1561
-     * @throws exception - If the Phing environment cannot be initialized
1562
-     */
1563
-    public static function startup(): void
1564
-    {
1565
-        // setup STDOUT and STDERR defaults
1566
-        self::initializeOutputStreams();
1567
-
1568
-        // some init stuff
1569
-        self::getTimer()->start();
1570
-
1571
-        self::setSystemConstants();
1572
-        self::setIncludePaths();
1573
-        self::setIni();
1574
-    }
1575
-
1576
-    /**
1577
-     * Set System constants which can be retrieved by calling Phing::getProperty($propName).
1578
-     */
1579
-    private static function setSystemConstants(): void
1580
-    {
1581
-        /*
1582
-         * PHP_OS returns on
1583
-         *   WindowsNT4.0sp6  => WINNT
1584
-         *   Windows2000      => WINNT
1585
-         *   Windows ME       => WIN32
1586
-         *   Windows 98SE     => WIN32
1587
-         *   FreeBSD 4.5p7    => FreeBSD
1588
-         *   Redhat Linux     => Linux
1589
-         *   Mac OS X         => Darwin
1590
-         */
1591
-        self::setProperty('host.os', PHP_OS);
1592
-
1593
-        // this is used by some tasks too
1594
-        self::setProperty('os.name', PHP_OS);
1595
-
1596
-        // it's still possible this won't be defined,
1597
-        // e.g. if Phing is being included in another app w/o
1598
-        // using the phing.php script.
1599
-        if (!defined('PHP_CLASSPATH')) {
1600
-            define('PHP_CLASSPATH', get_include_path());
1601
-        }
1602
-
1603
-        self::setProperty('php.classpath', PHP_CLASSPATH);
1604
-
1605
-        // try to determine the host filesystem and set system property
1606
-        // used by Fileself::getFileSystem to instantiate the correct
1607
-        // abstraction layer
1608
-
1609
-        if (PHP_OS_FAMILY === 'Windows') {
1610
-            self::setProperty('host.fstype', 'WINDOWS');
1611
-            self::setProperty('user.home', getenv('HOMEDRIVE') . getenv('HOMEPATH'));
1612
-        } else {
1613
-            self::setProperty('host.fstype', 'UNIX');
1614
-            self::setProperty('user.home', getenv('HOME'));
1615
-        }
1616
-        self::setProperty(self::PHP_INTERPRETER, PHP_BINARY);
1617
-        self::setProperty('file.separator', FileUtils::getSeparator());
1618
-        self::setProperty('line.separator', PHP_EOL);
1619
-        self::setProperty('path.separator', FileUtils::getPathSeparator());
1620
-        self::setProperty(self::PHP_VERSION, PHP_VERSION);
1621
-        self::setProperty('php.tmpdir', sys_get_temp_dir());
1622
-        self::setProperty('application.startdir', getcwd());
1623
-        self::setProperty('phing.startTime', gmdate('D, d M Y H:i:s', time()) . ' GMT');
1624
-
1625
-        // try to detect machine dependent information
1626
-        $sysInfo = [];
1627
-        if (function_exists('posix_uname') && 0 !== stripos(PHP_OS, 'WIN')) {
1628
-            $sysInfo = posix_uname();
1629
-        } else {
1630
-            $sysInfo['nodename'] = php_uname('n');
1631
-            $sysInfo['machine'] = php_uname('m');
1632
-            //this is a not so ideal substition, but maybe better than nothing
1633
-            $sysInfo['domain'] = $_SERVER['SERVER_NAME'] ?? 'unknown';
1634
-            $sysInfo['release'] = php_uname('r');
1635
-            $sysInfo['version'] = php_uname('v');
1636
-        }
1637
-
1638
-        self::setProperty('host.name', $sysInfo['nodename'] ?? 'unknown');
1639
-        self::setProperty('host.arch', $sysInfo['machine'] ?? 'unknown');
1640
-        self::setProperty('host.domain', $sysInfo['domain'] ?? 'unknown');
1641
-        self::setProperty('host.os.release', $sysInfo['release'] ?? 'unknown');
1642
-        self::setProperty('host.os.version', $sysInfo['version'] ?? 'unknown');
1643
-        unset($sysInfo);
1644
-    }
1645
-
1646
-    /**
1647
-     * @param $propName
1648
-     * @param $propValue
1649
-     *
1650
-     * @return string
1651
-     */
1652
-    public static function setProperty($propName, $propValue)
1653
-    {
1654
-        $propName = (string) $propName;
1655
-        $oldValue = self::getProperty($propName);
1656
-        self::$properties[$propName] = $propValue;
1657
-
1658
-        return $oldValue;
1659
-    }
1660
-
1661
-    /**
1662
-     * Sets the include path to PHP_CLASSPATH constant (if this has been defined).
1663
-     *
1664
-     * @throws ConfigurationException - if the include_path could not be set (for some bizarre reason)
1665
-     */
1666
-    private static function setIncludePaths(): void
1667
-    {
1668
-        if (defined('PHP_CLASSPATH')) {
1669
-            $result = set_include_path(PHP_CLASSPATH);
1670
-            if (false === $result) {
1671
-                throw new ConfigurationException('Could not set PHP include_path.');
1672
-            }
1673
-            self::$origIniSettings['include_path'] = $result; // save original value for setting back later
1674
-        }
1675
-    }
1676
-
1677
-    /**
1678
-     * Sets PHP INI values that Phing needs.
1679
-     */
1680
-    private static function setIni(): void
1681
-    {
1682
-        self::$origIniSettings['error_reporting'] = error_reporting(E_ALL);
1683
-
1684
-        // We won't bother storing original max_execution_time, since 1) the value in
1685
-        // php.ini may be wrong (and there's no way to get the current value) and
1686
-        // 2) it would mean something very strange to set it to a value less than time script
1687
-        // has already been running, which would be the likely change.
1688
-
1689
-        set_time_limit(0);
1690
-
1691
-        self::$origIniSettings['short_open_tag'] = ini_set('short_open_tag', 'off');
1692
-        self::$origIniSettings['default_charset'] = ini_set('default_charset', 'iso-8859-1');
1693
-
1694
-        $mem_limit = (int) SizeHelper::fromHumanToBytes(ini_get('memory_limit'));
1695
-        if ($mem_limit < (32 * 1024 * 1024) && $mem_limit > -1) {
1696
-            // We do *not* need to save the original value here, since we don't plan to restore
1697
-            // this after shutdown (we don't trust the effectiveness of PHP's garbage collection).
1698
-            ini_set('memory_limit', '32M'); // nore: this may need to be higher for many projects
1699
-        }
1700
-    }
1701
-}
Please login to merge, or discard this patch.
tests/Phing/Task/Optional/PDODelimitersTest.php 5 patches
Indentation   -141 removed lines patch added patch discarded remove patch
@@ -70,144 +70,3 @@
 block discarded – undo
70 70
         // for some reason default splitter mangles spaces on subsequent lines
71 71
         $expected = [
72 72
             <<<'SQL'
73
-                insert into foo (bar, "strange;name""indeed") values ('bar''s value containing ;', 'a value for strange named column')
74
-                SQL,
75
-            <<<'SQL'
76
-                delete
77
-                 from
78
-                 foo where bar = 'some value'
79
-                SQL,
80
-            <<<'SQL'
81
-                update dump -- I should not be ignored
82
-                 set message = 'I am a string with \\ backslash \' escapes and semicolons;'
83
-                SQL,
84
-            <<<'SQL'
85
-                create procedure setfoo(newfoo int)
86
-                 begin
87
-                 set @foo = newfoo;
88
-                 end
89
-                SQL,
90
-            <<<'SQL'
91
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
92
-                SQL,
93
-        ];
94
-        // and insists on "\n" linebreaks
95
-        foreach ($expected as &$query) {
96
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
97
-        }
98
-
99
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-normal.sql'));
100
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_NORMAL);
101
-        $this->project->setProperty('bar.value', 'some value');
102
-        $this->project->executeTarget('test');
103
-
104
-        $this->assertEquals($expected, $this->queries);
105
-    }
106
-
107
-    public function testDelimiterTypeRow(): void
108
-    {
109
-        // for some reason default splitter mangles spaces on subsequent lines
110
-        $expected = [
111
-            <<<'SQL'
112
-                insert into "duh" (foo) values ('duh')
113
-                SQL,
114
-            <<<'SQL'
115
-                update "duh?" -- I should not be ignored
116
-                 set foo = 'some value'
117
-                SQL,
118
-            <<<'SQL'
119
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
120
-                SQL,
121
-        ];
122
-        // and insists on "\n" linebreaks
123
-        foreach ($expected as &$query) {
124
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
125
-        }
126
-
127
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-row.sql'));
128
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_ROW);
129
-        $this->mockTask->setDelimiter('duh');
130
-        $this->project->setProperty('foo.value', 'some value');
131
-        $this->project->executeTarget('test');
132
-
133
-        $this->assertEquals($expected, $this->queries);
134
-    }
135
-
136
-    /**
137
-     * Checks that PDOSQLExecTask properly understands PostgreSQL dialect
138
-     * (especially "dollar quoting") when working with 'pgsql:' URLs.
139
-     *
140
-     * @see http://www.phing.info/trac/ticket/499
141
-     * @see http://www.postgresql.org/docs/9.0/interactive/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING
142
-     */
143
-    public function testRequest499(): void
144
-    {
145
-        $expected = [
146
-            <<<'SQL'
147
-                select 1
148
-                # 2
149
-                SQL,
150
-            <<<'SQL'
151
-                select 'foo'
152
-                // 'bar'
153
-                SQL,
154
-            <<<'SQL'
155
-                insert into foo (bar, "strange;name""indeed") values ('bar''s value containing ;', 'a value for strange named column')
156
-                SQL,
157
-            <<<'SQL'
158
-                create function foo(text)
159
-                returns boolean as
160
-                $function$
161
-                BEGIN
162
-                    RETURN ($1 ~ $q$[\t\r\n\v\\]$q$);
163
-                END;
164
-                $function$
165
-                language plpgsql
166
-                SQL,
167
-            <<<'SQL'
168
-                CREATE FUNCTION phingPDOtest() RETURNS "trigger"
169
-                    AS $_X$
170
-                if (1)
171
-                {
172
-                    # All is well - just continue
173
-
174
-                    return;
175
-                }
176
-                else
177
-                {
178
-                    # Not good - this is probably a fatal error!
179
-                    elog(ERROR,"True is not true");
180
-
181
-                    return "SKIP";
182
-                }
183
-                $_X$
184
-                    LANGUAGE plperl
185
-                SQL,
186
-            "insert into foo (bar) \nvalues ('some value')",
187
-            <<<'SQL'
188
-                insert into foo (bar) values ($$ a dollar-quoted string containing a few quotes ' ", a $placeholder$ and a semicolon;$$)
189
-                SQL,
190
-            <<<'SQL'
191
-                create rule blah_insert
192
-                as on insert to blah do instead (
193
-                    insert into foo values (new.id, 'blah');
194
-                    insert into bar values (new.id, 'blah-blah');
195
-                )
196
-                SQL,
197
-            <<<'SQL'
198
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
199
-                SQL,
200
-        ];
201
-        foreach ($expected as &$query) {
202
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
203
-        }
204
-
205
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-pgsql.sql'));
206
-        $this->mockTask->setUrl('pgsql:host=localhost;dbname=phing');
207
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_NORMAL);
208
-        $this->project->setProperty('bar.value', 'some value');
209
-        $this->project->executeTarget('test');
210
-
211
-        $this->assertEquals($expected, $this->queries);
212
-    }
213
-}
Please login to merge, or discard this patch.
Switch Indentation   -141 removed lines patch added patch discarded remove patch
@@ -70,144 +70,3 @@
 block discarded – undo
70 70
         // for some reason default splitter mangles spaces on subsequent lines
71 71
         $expected = [
72 72
             <<<'SQL'
73
-                insert into foo (bar, "strange;name""indeed") values ('bar''s value containing ;', 'a value for strange named column')
74
-                SQL,
75
-            <<<'SQL'
76
-                delete
77
-                 from
78
-                 foo where bar = 'some value'
79
-                SQL,
80
-            <<<'SQL'
81
-                update dump -- I should not be ignored
82
-                 set message = 'I am a string with \\ backslash \' escapes and semicolons;'
83
-                SQL,
84
-            <<<'SQL'
85
-                create procedure setfoo(newfoo int)
86
-                 begin
87
-                 set @foo = newfoo;
88
-                 end
89
-                SQL,
90
-            <<<'SQL'
91
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
92
-                SQL,
93
-        ];
94
-        // and insists on "\n" linebreaks
95
-        foreach ($expected as &$query) {
96
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
97
-        }
98
-
99
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-normal.sql'));
100
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_NORMAL);
101
-        $this->project->setProperty('bar.value', 'some value');
102
-        $this->project->executeTarget('test');
103
-
104
-        $this->assertEquals($expected, $this->queries);
105
-    }
106
-
107
-    public function testDelimiterTypeRow(): void
108
-    {
109
-        // for some reason default splitter mangles spaces on subsequent lines
110
-        $expected = [
111
-            <<<'SQL'
112
-                insert into "duh" (foo) values ('duh')
113
-                SQL,
114
-            <<<'SQL'
115
-                update "duh?" -- I should not be ignored
116
-                 set foo = 'some value'
117
-                SQL,
118
-            <<<'SQL'
119
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
120
-                SQL,
121
-        ];
122
-        // and insists on "\n" linebreaks
123
-        foreach ($expected as &$query) {
124
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
125
-        }
126
-
127
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-row.sql'));
128
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_ROW);
129
-        $this->mockTask->setDelimiter('duh');
130
-        $this->project->setProperty('foo.value', 'some value');
131
-        $this->project->executeTarget('test');
132
-
133
-        $this->assertEquals($expected, $this->queries);
134
-    }
135
-
136
-    /**
137
-     * Checks that PDOSQLExecTask properly understands PostgreSQL dialect
138
-     * (especially "dollar quoting") when working with 'pgsql:' URLs.
139
-     *
140
-     * @see http://www.phing.info/trac/ticket/499
141
-     * @see http://www.postgresql.org/docs/9.0/interactive/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING
142
-     */
143
-    public function testRequest499(): void
144
-    {
145
-        $expected = [
146
-            <<<'SQL'
147
-                select 1
148
-                # 2
149
-                SQL,
150
-            <<<'SQL'
151
-                select 'foo'
152
-                // 'bar'
153
-                SQL,
154
-            <<<'SQL'
155
-                insert into foo (bar, "strange;name""indeed") values ('bar''s value containing ;', 'a value for strange named column')
156
-                SQL,
157
-            <<<'SQL'
158
-                create function foo(text)
159
-                returns boolean as
160
-                $function$
161
-                BEGIN
162
-                    RETURN ($1 ~ $q$[\t\r\n\v\\]$q$);
163
-                END;
164
-                $function$
165
-                language plpgsql
166
-                SQL,
167
-            <<<'SQL'
168
-                CREATE FUNCTION phingPDOtest() RETURNS "trigger"
169
-                    AS $_X$
170
-                if (1)
171
-                {
172
-                    # All is well - just continue
173
-
174
-                    return;
175
-                }
176
-                else
177
-                {
178
-                    # Not good - this is probably a fatal error!
179
-                    elog(ERROR,"True is not true");
180
-
181
-                    return "SKIP";
182
-                }
183
-                $_X$
184
-                    LANGUAGE plperl
185
-                SQL,
186
-            "insert into foo (bar) \nvalues ('some value')",
187
-            <<<'SQL'
188
-                insert into foo (bar) values ($$ a dollar-quoted string containing a few quotes ' ", a $placeholder$ and a semicolon;$$)
189
-                SQL,
190
-            <<<'SQL'
191
-                create rule blah_insert
192
-                as on insert to blah do instead (
193
-                    insert into foo values (new.id, 'blah');
194
-                    insert into bar values (new.id, 'blah-blah');
195
-                )
196
-                SQL,
197
-            <<<'SQL'
198
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
199
-                SQL,
200
-        ];
201
-        foreach ($expected as &$query) {
202
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
203
-        }
204
-
205
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-pgsql.sql'));
206
-        $this->mockTask->setUrl('pgsql:host=localhost;dbname=phing');
207
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_NORMAL);
208
-        $this->project->setProperty('bar.value', 'some value');
209
-        $this->project->executeTarget('test');
210
-
211
-        $this->assertEquals($expected, $this->queries);
212
-    }
213
-}
Please login to merge, or discard this patch.
Spacing   -141 removed lines patch added patch discarded remove patch
@@ -70,144 +70,3 @@
 block discarded – undo
70 70
         // for some reason default splitter mangles spaces on subsequent lines
71 71
         $expected = [
72 72
             <<<'SQL'
73
-                insert into foo (bar, "strange;name""indeed") values ('bar''s value containing ;', 'a value for strange named column')
74
-                SQL,
75
-            <<<'SQL'
76
-                delete
77
-                 from
78
-                 foo where bar = 'some value'
79
-                SQL,
80
-            <<<'SQL'
81
-                update dump -- I should not be ignored
82
-                 set message = 'I am a string with \\ backslash \' escapes and semicolons;'
83
-                SQL,
84
-            <<<'SQL'
85
-                create procedure setfoo(newfoo int)
86
-                 begin
87
-                 set @foo = newfoo;
88
-                 end
89
-                SQL,
90
-            <<<'SQL'
91
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
92
-                SQL,
93
-        ];
94
-        // and insists on "\n" linebreaks
95
-        foreach ($expected as &$query) {
96
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
97
-        }
98
-
99
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-normal.sql'));
100
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_NORMAL);
101
-        $this->project->setProperty('bar.value', 'some value');
102
-        $this->project->executeTarget('test');
103
-
104
-        $this->assertEquals($expected, $this->queries);
105
-    }
106
-
107
-    public function testDelimiterTypeRow(): void
108
-    {
109
-        // for some reason default splitter mangles spaces on subsequent lines
110
-        $expected = [
111
-            <<<'SQL'
112
-                insert into "duh" (foo) values ('duh')
113
-                SQL,
114
-            <<<'SQL'
115
-                update "duh?" -- I should not be ignored
116
-                 set foo = 'some value'
117
-                SQL,
118
-            <<<'SQL'
119
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
120
-                SQL,
121
-        ];
122
-        // and insists on "\n" linebreaks
123
-        foreach ($expected as &$query) {
124
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
125
-        }
126
-
127
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-row.sql'));
128
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_ROW);
129
-        $this->mockTask->setDelimiter('duh');
130
-        $this->project->setProperty('foo.value', 'some value');
131
-        $this->project->executeTarget('test');
132
-
133
-        $this->assertEquals($expected, $this->queries);
134
-    }
135
-
136
-    /**
137
-     * Checks that PDOSQLExecTask properly understands PostgreSQL dialect
138
-     * (especially "dollar quoting") when working with 'pgsql:' URLs.
139
-     *
140
-     * @see http://www.phing.info/trac/ticket/499
141
-     * @see http://www.postgresql.org/docs/9.0/interactive/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING
142
-     */
143
-    public function testRequest499(): void
144
-    {
145
-        $expected = [
146
-            <<<'SQL'
147
-                select 1
148
-                # 2
149
-                SQL,
150
-            <<<'SQL'
151
-                select 'foo'
152
-                // 'bar'
153
-                SQL,
154
-            <<<'SQL'
155
-                insert into foo (bar, "strange;name""indeed") values ('bar''s value containing ;', 'a value for strange named column')
156
-                SQL,
157
-            <<<'SQL'
158
-                create function foo(text)
159
-                returns boolean as
160
-                $function$
161
-                BEGIN
162
-                    RETURN ($1 ~ $q$[\t\r\n\v\\]$q$);
163
-                END;
164
-                $function$
165
-                language plpgsql
166
-                SQL,
167
-            <<<'SQL'
168
-                CREATE FUNCTION phingPDOtest() RETURNS "trigger"
169
-                    AS $_X$
170
-                if (1)
171
-                {
172
-                    # All is well - just continue
173
-
174
-                    return;
175
-                }
176
-                else
177
-                {
178
-                    # Not good - this is probably a fatal error!
179
-                    elog(ERROR,"True is not true");
180
-
181
-                    return "SKIP";
182
-                }
183
-                $_X$
184
-                    LANGUAGE plperl
185
-                SQL,
186
-            "insert into foo (bar) \nvalues ('some value')",
187
-            <<<'SQL'
188
-                insert into foo (bar) values ($$ a dollar-quoted string containing a few quotes ' ", a $placeholder$ and a semicolon;$$)
189
-                SQL,
190
-            <<<'SQL'
191
-                create rule blah_insert
192
-                as on insert to blah do instead (
193
-                    insert into foo values (new.id, 'blah');
194
-                    insert into bar values (new.id, 'blah-blah');
195
-                )
196
-                SQL,
197
-            <<<'SQL'
198
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
199
-                SQL,
200
-        ];
201
-        foreach ($expected as &$query) {
202
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
203
-        }
204
-
205
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-pgsql.sql'));
206
-        $this->mockTask->setUrl('pgsql:host=localhost;dbname=phing');
207
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_NORMAL);
208
-        $this->project->setProperty('bar.value', 'some value');
209
-        $this->project->executeTarget('test');
210
-
211
-        $this->assertEquals($expected, $this->queries);
212
-    }
213
-}
Please login to merge, or discard this patch.
Braces   -141 removed lines patch added patch discarded remove patch
@@ -70,144 +70,3 @@
 block discarded – undo
70 70
         // for some reason default splitter mangles spaces on subsequent lines
71 71
         $expected = [
72 72
             <<<'SQL'
73
-                insert into foo (bar, "strange;name""indeed") values ('bar''s value containing ;', 'a value for strange named column')
74
-                SQL,
75
-            <<<'SQL'
76
-                delete
77
-                 from
78
-                 foo where bar = 'some value'
79
-                SQL,
80
-            <<<'SQL'
81
-                update dump -- I should not be ignored
82
-                 set message = 'I am a string with \\ backslash \' escapes and semicolons;'
83
-                SQL,
84
-            <<<'SQL'
85
-                create procedure setfoo(newfoo int)
86
-                 begin
87
-                 set @foo = newfoo;
88
-                 end
89
-                SQL,
90
-            <<<'SQL'
91
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
92
-                SQL,
93
-        ];
94
-        // and insists on "\n" linebreaks
95
-        foreach ($expected as &$query) {
96
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
97
-        }
98
-
99
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-normal.sql'));
100
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_NORMAL);
101
-        $this->project->setProperty('bar.value', 'some value');
102
-        $this->project->executeTarget('test');
103
-
104
-        $this->assertEquals($expected, $this->queries);
105
-    }
106
-
107
-    public function testDelimiterTypeRow(): void
108
-    {
109
-        // for some reason default splitter mangles spaces on subsequent lines
110
-        $expected = [
111
-            <<<'SQL'
112
-                insert into "duh" (foo) values ('duh')
113
-                SQL,
114
-            <<<'SQL'
115
-                update "duh?" -- I should not be ignored
116
-                 set foo = 'some value'
117
-                SQL,
118
-            <<<'SQL'
119
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
120
-                SQL,
121
-        ];
122
-        // and insists on "\n" linebreaks
123
-        foreach ($expected as &$query) {
124
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
125
-        }
126
-
127
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-row.sql'));
128
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_ROW);
129
-        $this->mockTask->setDelimiter('duh');
130
-        $this->project->setProperty('foo.value', 'some value');
131
-        $this->project->executeTarget('test');
132
-
133
-        $this->assertEquals($expected, $this->queries);
134
-    }
135
-
136
-    /**
137
-     * Checks that PDOSQLExecTask properly understands PostgreSQL dialect
138
-     * (especially "dollar quoting") when working with 'pgsql:' URLs.
139
-     *
140
-     * @see http://www.phing.info/trac/ticket/499
141
-     * @see http://www.postgresql.org/docs/9.0/interactive/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING
142
-     */
143
-    public function testRequest499(): void
144
-    {
145
-        $expected = [
146
-            <<<'SQL'
147
-                select 1
148
-                # 2
149
-                SQL,
150
-            <<<'SQL'
151
-                select 'foo'
152
-                // 'bar'
153
-                SQL,
154
-            <<<'SQL'
155
-                insert into foo (bar, "strange;name""indeed") values ('bar''s value containing ;', 'a value for strange named column')
156
-                SQL,
157
-            <<<'SQL'
158
-                create function foo(text)
159
-                returns boolean as
160
-                $function$
161
-                BEGIN
162
-                    RETURN ($1 ~ $q$[\t\r\n\v\\]$q$);
163
-                END;
164
-                $function$
165
-                language plpgsql
166
-                SQL,
167
-            <<<'SQL'
168
-                CREATE FUNCTION phingPDOtest() RETURNS "trigger"
169
-                    AS $_X$
170
-                if (1)
171
-                {
172
-                    # All is well - just continue
173
-
174
-                    return;
175
-                }
176
-                else
177
-                {
178
-                    # Not good - this is probably a fatal error!
179
-                    elog(ERROR,"True is not true");
180
-
181
-                    return "SKIP";
182
-                }
183
-                $_X$
184
-                    LANGUAGE plperl
185
-                SQL,
186
-            "insert into foo (bar) \nvalues ('some value')",
187
-            <<<'SQL'
188
-                insert into foo (bar) values ($$ a dollar-quoted string containing a few quotes ' ", a $placeholder$ and a semicolon;$$)
189
-                SQL,
190
-            <<<'SQL'
191
-                create rule blah_insert
192
-                as on insert to blah do instead (
193
-                    insert into foo values (new.id, 'blah');
194
-                    insert into bar values (new.id, 'blah-blah');
195
-                )
196
-                SQL,
197
-            <<<'SQL'
198
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
199
-                SQL,
200
-        ];
201
-        foreach ($expected as &$query) {
202
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
203
-        }
204
-
205
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-pgsql.sql'));
206
-        $this->mockTask->setUrl('pgsql:host=localhost;dbname=phing');
207
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_NORMAL);
208
-        $this->project->setProperty('bar.value', 'some value');
209
-        $this->project->executeTarget('test');
210
-
211
-        $this->assertEquals($expected, $this->queries);
212
-    }
213
-}
Please login to merge, or discard this patch.
Upper-Lower-Casing   -141 removed lines patch added patch discarded remove patch
@@ -70,144 +70,3 @@
 block discarded – undo
70 70
         // for some reason default splitter mangles spaces on subsequent lines
71 71
         $expected = [
72 72
             <<<'SQL'
73
-                insert into foo (bar, "strange;name""indeed") values ('bar''s value containing ;', 'a value for strange named column')
74
-                SQL,
75
-            <<<'SQL'
76
-                delete
77
-                 from
78
-                 foo where bar = 'some value'
79
-                SQL,
80
-            <<<'SQL'
81
-                update dump -- I should not be ignored
82
-                 set message = 'I am a string with \\ backslash \' escapes and semicolons;'
83
-                SQL,
84
-            <<<'SQL'
85
-                create procedure setfoo(newfoo int)
86
-                 begin
87
-                 set @foo = newfoo;
88
-                 end
89
-                SQL,
90
-            <<<'SQL'
91
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
92
-                SQL,
93
-        ];
94
-        // and insists on "\n" linebreaks
95
-        foreach ($expected as &$query) {
96
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
97
-        }
98
-
99
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-normal.sql'));
100
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_NORMAL);
101
-        $this->project->setProperty('bar.value', 'some value');
102
-        $this->project->executeTarget('test');
103
-
104
-        $this->assertEquals($expected, $this->queries);
105
-    }
106
-
107
-    public function testDelimiterTypeRow(): void
108
-    {
109
-        // for some reason default splitter mangles spaces on subsequent lines
110
-        $expected = [
111
-            <<<'SQL'
112
-                insert into "duh" (foo) values ('duh')
113
-                SQL,
114
-            <<<'SQL'
115
-                update "duh?" -- I should not be ignored
116
-                 set foo = 'some value'
117
-                SQL,
118
-            <<<'SQL'
119
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
120
-                SQL,
121
-        ];
122
-        // and insists on "\n" linebreaks
123
-        foreach ($expected as &$query) {
124
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
125
-        }
126
-
127
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-row.sql'));
128
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_ROW);
129
-        $this->mockTask->setDelimiter('duh');
130
-        $this->project->setProperty('foo.value', 'some value');
131
-        $this->project->executeTarget('test');
132
-
133
-        $this->assertEquals($expected, $this->queries);
134
-    }
135
-
136
-    /**
137
-     * Checks that PDOSQLExecTask properly understands PostgreSQL dialect
138
-     * (especially "dollar quoting") when working with 'pgsql:' URLs.
139
-     *
140
-     * @see http://www.phing.info/trac/ticket/499
141
-     * @see http://www.postgresql.org/docs/9.0/interactive/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING
142
-     */
143
-    public function testRequest499(): void
144
-    {
145
-        $expected = [
146
-            <<<'SQL'
147
-                select 1
148
-                # 2
149
-                SQL,
150
-            <<<'SQL'
151
-                select 'foo'
152
-                // 'bar'
153
-                SQL,
154
-            <<<'SQL'
155
-                insert into foo (bar, "strange;name""indeed") values ('bar''s value containing ;', 'a value for strange named column')
156
-                SQL,
157
-            <<<'SQL'
158
-                create function foo(text)
159
-                returns boolean as
160
-                $function$
161
-                BEGIN
162
-                    RETURN ($1 ~ $q$[\t\r\n\v\\]$q$);
163
-                END;
164
-                $function$
165
-                language plpgsql
166
-                SQL,
167
-            <<<'SQL'
168
-                CREATE FUNCTION phingPDOtest() RETURNS "trigger"
169
-                    AS $_X$
170
-                if (1)
171
-                {
172
-                    # All is well - just continue
173
-
174
-                    return;
175
-                }
176
-                else
177
-                {
178
-                    # Not good - this is probably a fatal error!
179
-                    elog(ERROR,"True is not true");
180
-
181
-                    return "SKIP";
182
-                }
183
-                $_X$
184
-                    LANGUAGE plperl
185
-                SQL,
186
-            "insert into foo (bar) \nvalues ('some value')",
187
-            <<<'SQL'
188
-                insert into foo (bar) values ($$ a dollar-quoted string containing a few quotes ' ", a $placeholder$ and a semicolon;$$)
189
-                SQL,
190
-            <<<'SQL'
191
-                create rule blah_insert
192
-                as on insert to blah do instead (
193
-                    insert into foo values (new.id, 'blah');
194
-                    insert into bar values (new.id, 'blah-blah');
195
-                )
196
-                SQL,
197
-            <<<'SQL'
198
-                insert into dump (message) values ('I am a statement not ending with a delimiter')
199
-                SQL,
200
-        ];
201
-        foreach ($expected as &$query) {
202
-            $query = str_replace(["\n\n", "\r"], ["\n", ''], $query);
203
-        }
204
-
205
-        $this->mockTask->setSrc(new File(PHING_TEST_BASE . '/etc/tasks/ext/pdo/delimiters-pgsql.sql'));
206
-        $this->mockTask->setUrl('pgsql:host=localhost;dbname=phing');
207
-        $this->mockTask->setDelimiterType(PDOSQLExecTask::DELIM_NORMAL);
208
-        $this->project->setProperty('bar.value', 'some value');
209
-        $this->project->executeTarget('test');
210
-
211
-        $this->assertEquals($expected, $this->queries);
212
-    }
213
-}
Please login to merge, or discard this patch.