Completed
Branch development (b1b115)
by Ashutosh
10:00
created

PHPUnit_Util_Configuration::getTestSuite()   F

Complexity

Conditions 21
Paths 1656

Size

Total Lines 111

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 111
rs 0
cc 21
nc 1656
nop 2

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/*
3
 * This file is part of PHPUnit.
4
 *
5
 * (c) Sebastian Bergmann <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
/**
12
 * Wrapper for the PHPUnit XML configuration file.
13
 *
14
 * Example XML configuration file:
15
 * <code>
16
 * <?xml version="1.0" encoding="utf-8" ?>
17
 *
18
 * <phpunit backupGlobals="true"
19
 *          backupStaticAttributes="false"
20
 *          bootstrap="/path/to/bootstrap.php"
21
 *          cacheTokens="false"
22
 *          columns="80"
23
 *          colors="false"
24
 *          stderr="false"
25
 *          convertErrorsToExceptions="true"
26
 *          convertNoticesToExceptions="true"
27
 *          convertWarningsToExceptions="true"
28
 *          forceCoversAnnotation="false"
29
 *          processIsolation="false"
30
 *          stopOnError="false"
31
 *          stopOnFailure="false"
32
 *          stopOnWarning="false"
33
 *          stopOnIncomplete="false"
34
 *          stopOnRisky="false"
35
 *          stopOnSkipped="false"
36
 *          failOnWarning="false"
37
 *          failOnRisky="false"
38
 *          extensionsDirectory="tools/phpunit.d"
39
 *          printerClass="PHPUnit_TextUI_ResultPrinter"
40
 *          testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
41
 *          beStrictAboutChangesToGlobalState="false"
42
 *          beStrictAboutCoversAnnotation="false"
43
 *          beStrictAboutOutputDuringTests="false"
44
 *          beStrictAboutResourceUsageDuringSmallTests="false"
45
 *          beStrictAboutTestsThatDoNotTestAnything="false"
46
 *          beStrictAboutTodoAnnotatedTests="false"
47
 *          checkForUnintentionallyCoveredCode="false"
48
 *          enforceTimeLimit="false"
49
 *          timeoutForSmallTests="1"
50
 *          timeoutForMediumTests="10"
51
 *          timeoutForLargeTests="60"
52
 *          verbose="false"
53
 *          reverseDefectList="false"
54
 *          registerMockObjectsFromTestArgumentsRecursively="false">
55
 *   <testsuites>
56
 *     <testsuite name="My Test Suite">
57
 *       <directory suffix="Test.php" phpVersion="5.3.0" phpVersionOperator=">=">/path/to/files</directory>
58
 *       <file phpVersion="5.3.0" phpVersionOperator=">=">/path/to/MyTest.php</file>
59
 *       <exclude>/path/to/files/exclude</exclude>
60
 *     </testsuite>
61
 *   </testsuites>
62
 *
63
 *   <groups>
64
 *     <include>
65
 *       <group>name</group>
66
 *     </include>
67
 *     <exclude>
68
 *       <group>name</group>
69
 *     </exclude>
70
 *   </groups>
71
 *
72
 *   <testdoxGroups>
73
 *     <include>
74
 *       <group>name</group>
75
 *     </include>
76
 *     <exclude>
77
 *       <group>name</group>
78
 *     </exclude>
79
 *   </testdoxGroups>
80
 *
81
 *   <filter>
82
 *     <whitelist addUncoveredFilesFromWhitelist="true"
83
 *                processUncoveredFilesFromWhitelist="false">
84
 *       <directory suffix=".php">/path/to/files</directory>
85
 *       <file>/path/to/file</file>
86
 *       <exclude>
87
 *         <directory suffix=".php">/path/to/files</directory>
88
 *         <file>/path/to/file</file>
89
 *       </exclude>
90
 *     </whitelist>
91
 *   </filter>
92
 *
93
 *   <listeners>
94
 *     <listener class="MyListener" file="/optional/path/to/MyListener.php">
95
 *       <arguments>
96
 *         <array>
97
 *           <element key="0">
98
 *             <string>Sebastian</string>
99
 *           </element>
100
 *         </array>
101
 *         <integer>22</integer>
102
 *         <string>April</string>
103
 *         <double>19.78</double>
104
 *         <null/>
105
 *         <object class="stdClass"/>
106
 *         <file>MyRelativeFile.php</file>
107
 *         <directory>MyRelativeDir</directory>
108
 *       </arguments>
109
 *     </listener>
110
 *   </listeners>
111
 *
112
 *   <logging>
113
 *     <log type="coverage-html" target="/tmp/report" lowUpperBound="50" highLowerBound="90"/>
114
 *     <log type="coverage-clover" target="/tmp/clover.xml"/>
115
 *     <log type="coverage-crap4j" target="/tmp/crap.xml" threshold="30"/>
116
 *     <log type="json" target="/tmp/logfile.json"/>
117
 *     <log type="plain" target="/tmp/logfile.txt"/>
118
 *     <log type="tap" target="/tmp/logfile.tap"/>
119
 *     <log type="teamcity" target="/tmp/logfile.txt"/>
120
 *     <log type="junit" target="/tmp/logfile.xml" logIncompleteSkipped="false"/>
121
 *     <log type="testdox-html" target="/tmp/testdox.html"/>
122
 *     <log type="testdox-text" target="/tmp/testdox.txt"/>
123
 *     <log type="testdox-xml" target="/tmp/testdox.xml"/>
124
 *   </logging>
125
 *
126
 *   <php>
127
 *     <includePath>.</includePath>
128
 *     <ini name="foo" value="bar"/>
129
 *     <const name="foo" value="bar"/>
130
 *     <var name="foo" value="bar"/>
131
 *     <env name="foo" value="bar"/>
132
 *     <post name="foo" value="bar"/>
133
 *     <get name="foo" value="bar"/>
134
 *     <cookie name="foo" value="bar"/>
135
 *     <server name="foo" value="bar"/>
136
 *     <files name="foo" value="bar"/>
137
 *     <request name="foo" value="bar"/>
138
 *   </php>
139
 * </phpunit>
140
 * </code>
141
 */
142
class PHPUnit_Util_Configuration
143
{
144
    private static $instances = [];
145
146
    protected $document;
147
    protected $xpath;
148
    protected $filename;
149
150
    /**
151
     * Loads a PHPUnit configuration file.
152
     *
153
     * @param string $filename
154
     */
155
    protected function __construct($filename)
156
    {
157
        $this->filename = $filename;
158
        $this->document = PHPUnit_Util_XML::loadFile($filename, false, true, true);
159
        $this->xpath    = new DOMXPath($this->document);
160
    }
161
162
    final private function __clone()
163
    {
164
    }
165
166
    /**
167
     * Returns a PHPUnit configuration object.
168
     *
169
     * @param string $filename
170
     *
171
     * @return PHPUnit_Util_Configuration
172
     */
173
    public static function getInstance($filename)
174
    {
175
        $realpath = realpath($filename);
176
177
        if ($realpath === false) {
178
            throw new PHPUnit_Framework_Exception(
179
                sprintf(
180
                    'Could not read "%s".',
181
                    $filename
182
                )
183
            );
184
        }
185
186
        if (!isset(self::$instances[$realpath])) {
187
            self::$instances[$realpath] = new self($realpath);
188
        }
189
190
        return self::$instances[$realpath];
191
    }
192
193
    /**
194
     * Returns the realpath to the configuration file.
195
     *
196
     * @return string
197
     */
198
    public function getFilename()
199
    {
200
        return $this->filename;
201
    }
202
203
    /**
204
     * Returns the configuration for SUT filtering.
205
     *
206
     * @return array
207
     */
208
    public function getFilterConfiguration()
209
    {
210
        $addUncoveredFilesFromWhitelist     = true;
211
        $processUncoveredFilesFromWhitelist = false;
212
213
        $tmp = $this->xpath->query('filter/whitelist');
214
215
        if ($tmp->length == 1) {
216
            if ($tmp->item(0)->hasAttribute('addUncoveredFilesFromWhitelist')) {
217
                $addUncoveredFilesFromWhitelist = $this->getBoolean(
218
                    (string) $tmp->item(0)->getAttribute(
219
                        'addUncoveredFilesFromWhitelist'
220
                    ),
221
                    true
222
                );
223
            }
224
225
            if ($tmp->item(0)->hasAttribute('processUncoveredFilesFromWhitelist')) {
226
                $processUncoveredFilesFromWhitelist = $this->getBoolean(
227
                    (string) $tmp->item(0)->getAttribute(
228
                        'processUncoveredFilesFromWhitelist'
229
                    ),
230
                    false
231
                );
232
            }
233
        }
234
235
        return [
236
          'whitelist' => [
237
            'addUncoveredFilesFromWhitelist'     => $addUncoveredFilesFromWhitelist,
238
            'processUncoveredFilesFromWhitelist' => $processUncoveredFilesFromWhitelist,
239
            'include'                            => [
240
              'directory' => $this->readFilterDirectories(
241
                  'filter/whitelist/directory'
242
              ),
243
              'file' => $this->readFilterFiles(
244
                  'filter/whitelist/file'
245
              )
246
            ],
247
            'exclude' => [
248
              'directory' => $this->readFilterDirectories(
249
                  'filter/whitelist/exclude/directory'
250
              ),
251
              'file' => $this->readFilterFiles(
252
                  'filter/whitelist/exclude/file'
253
              )
254
            ]
255
          ]
256
        ];
257
    }
258
259
    /**
260
     * Returns the configuration for groups.
261
     *
262
     * @return array
263
     */
264
    public function getGroupConfiguration()
265
    {
266
        return $this->parseGroupConfiguration('groups');
267
    }
268
269
    /**
270
     * Returns the configuration for testdox groups.
271
     *
272
     * @return array
273
     */
274
    public function getTestdoxGroupConfiguration()
275
    {
276
        return $this->parseGroupConfiguration('testdoxGroups');
277
    }
278
279
    /**
280
     * @param string $root
281
     *
282
     * @return array
283
     */
284
    private function parseGroupConfiguration($root)
285
    {
286
        $groups = [
287
            'include' => [],
288
            'exclude' => []
289
        ];
290
291
        foreach ($this->xpath->query($root . '/include/group') as $group) {
292
            $groups['include'][] = (string) $group->textContent;
293
        }
294
295
        foreach ($this->xpath->query($root . '/exclude/group') as $group) {
296
            $groups['exclude'][] = (string) $group->textContent;
297
        }
298
299
        return $groups;
300
    }
301
302
    /**
303
     * Returns the configuration for listeners.
304
     *
305
     * @return array
306
     */
307
    public function getListenerConfiguration()
308
    {
309
        $result = [];
310
311
        foreach ($this->xpath->query('listeners/listener') as $listener) {
312
            $class     = (string) $listener->getAttribute('class');
313
            $file      = '';
314
            $arguments = [];
315
316
            if ($listener->getAttribute('file')) {
317
                $file = $this->toAbsolutePath(
318
                    (string) $listener->getAttribute('file'),
319
                    true
320
                );
321
            }
322
323
            foreach ($listener->childNodes as $node) {
324
                if ($node instanceof DOMElement && $node->tagName == 'arguments') {
325
                    foreach ($node->childNodes as $argument) {
326
                        if ($argument instanceof DOMElement) {
327
                            if ($argument->tagName == 'file' ||
328
                            $argument->tagName == 'directory') {
329
                                $arguments[] = $this->toAbsolutePath((string) $argument->textContent);
330
                            } else {
331
                                $arguments[] = PHPUnit_Util_XML::xmlToVariable($argument);
332
                            }
333
                        }
334
                    }
335
                }
336
            }
337
338
            $result[] = [
339
              'class'     => $class,
340
              'file'      => $file,
341
              'arguments' => $arguments
342
            ];
343
        }
344
345
        return $result;
346
    }
347
348
    /**
349
     * Returns the logging configuration.
350
     *
351
     * @return array
352
     */
353
    public function getLoggingConfiguration()
354
    {
355
        $result = [];
356
357
        foreach ($this->xpath->query('logging/log') as $log) {
358
            $type   = (string) $log->getAttribute('type');
359
            $target = (string) $log->getAttribute('target');
360
361
            if (!$target) {
362
                continue;
363
            }
364
365
            $target = $this->toAbsolutePath($target);
366
367
            if ($type == 'coverage-html') {
368
                if ($log->hasAttribute('lowUpperBound')) {
369
                    $result['lowUpperBound'] = $this->getInteger(
370
                        (string) $log->getAttribute('lowUpperBound'),
371
                        50
372
                    );
373
                }
374
375
                if ($log->hasAttribute('highLowerBound')) {
376
                    $result['highLowerBound'] = $this->getInteger(
377
                        (string) $log->getAttribute('highLowerBound'),
378
                        90
379
                    );
380
                }
381
            } elseif ($type == 'coverage-crap4j') {
382
                if ($log->hasAttribute('threshold')) {
383
                    $result['crap4jThreshold'] = $this->getInteger(
384
                        (string) $log->getAttribute('threshold'),
385
                        30
386
                    );
387
                }
388
            } elseif ($type == 'junit') {
389
                if ($log->hasAttribute('logIncompleteSkipped')) {
390
                    $result['logIncompleteSkipped'] = $this->getBoolean(
391
                        (string) $log->getAttribute('logIncompleteSkipped'),
392
                        false
393
                    );
394
                }
395
            } elseif ($type == 'coverage-text') {
396
                if ($log->hasAttribute('showUncoveredFiles')) {
397
                    $result['coverageTextShowUncoveredFiles'] = $this->getBoolean(
398
                        (string) $log->getAttribute('showUncoveredFiles'),
399
                        false
400
                    );
401
                }
402
                if ($log->hasAttribute('showOnlySummary')) {
403
                    $result['coverageTextShowOnlySummary'] = $this->getBoolean(
404
                        (string) $log->getAttribute('showOnlySummary'),
405
                        false
406
                    );
407
                }
408
            }
409
410
            $result[$type] = $target;
411
        }
412
413
        return $result;
414
    }
415
416
    /**
417
     * Returns the PHP configuration.
418
     *
419
     * @return array
420
     */
421
    public function getPHPConfiguration()
422
    {
423
        $result = [
424
          'include_path' => [],
425
          'ini'          => [],
426
          'const'        => [],
427
          'var'          => [],
428
          'env'          => [],
429
          'post'         => [],
430
          'get'          => [],
431
          'cookie'       => [],
432
          'server'       => [],
433
          'files'        => [],
434
          'request'      => []
435
        ];
436
437
        foreach ($this->xpath->query('php/includePath') as $includePath) {
438
            $path = (string) $includePath->textContent;
439
            if ($path) {
440
                $result['include_path'][] = $this->toAbsolutePath($path);
441
            }
442
        }
443
444
        foreach ($this->xpath->query('php/ini') as $ini) {
445
            $name  = (string) $ini->getAttribute('name');
446
            $value = (string) $ini->getAttribute('value');
447
448
            $result['ini'][$name] = $value;
449
        }
450
451
        foreach ($this->xpath->query('php/const') as $const) {
452
            $name  = (string) $const->getAttribute('name');
453
            $value = (string) $const->getAttribute('value');
454
455
            $result['const'][$name] = $this->getBoolean($value, $value);
456
        }
457
458
        foreach (['var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request'] as $array) {
459
            foreach ($this->xpath->query('php/' . $array) as $var) {
460
                $name  = (string) $var->getAttribute('name');
461
                $value = (string) $var->getAttribute('value');
462
463
                $result[$array][$name] = $this->getBoolean($value, $value);
464
            }
465
        }
466
467
        return $result;
468
    }
469
470
    /**
471
     * Handles the PHP configuration.
472
     */
473
    public function handlePHPConfiguration()
474
    {
475
        $configuration = $this->getPHPConfiguration();
476
477
        if (! empty($configuration['include_path'])) {
478
            ini_set(
479
                'include_path',
480
                implode(PATH_SEPARATOR, $configuration['include_path']) .
481
                PATH_SEPARATOR .
482
                ini_get('include_path')
483
            );
484
        }
485
486
        foreach ($configuration['ini'] as $name => $value) {
487
            if (defined($value)) {
488
                $value = constant($value);
489
            }
490
491
            ini_set($name, $value);
492
        }
493
494
        foreach ($configuration['const'] as $name => $value) {
495
            if (!defined($name)) {
496
                define($name, $value);
497
            }
498
        }
499
500
        foreach (['var', 'post', 'get', 'cookie', 'server', 'files', 'request'] as $array) {
501
            // See https://github.com/sebastianbergmann/phpunit/issues/277
502
            switch ($array) {
503
                case 'var':
504
                    $target = &$GLOBALS;
505
                    break;
506
507
                case 'server':
508
                    $target = &$_SERVER;
509
                    break;
510
511
                default:
512
                    $target = &$GLOBALS['_' . strtoupper($array)];
513
                    break;
514
            }
515
516
            foreach ($configuration[$array] as $name => $value) {
517
                $target[$name] = $value;
518
            }
519
        }
520
521
        foreach ($configuration['env'] as $name => $value) {
522
            if (false === getenv($name)) {
523
                putenv("{$name}={$value}");
524
            }
525
            if (!isset($_ENV[$name])) {
526
                $_ENV[$name] = $value;
527
            }
528
        }
529
    }
530
531
    /**
532
     * Returns the PHPUnit configuration.
533
     *
534
     * @return array
535
     */
536
    public function getPHPUnitConfiguration()
537
    {
538
        $result = [];
539
        $root   = $this->document->documentElement;
540
541
        if ($root->hasAttribute('cacheTokens')) {
542
            $result['cacheTokens'] = $this->getBoolean(
543
                (string) $root->getAttribute('cacheTokens'),
544
                false
545
            );
546
        }
547
548
        if ($root->hasAttribute('columns')) {
549
            $columns = (string) $root->getAttribute('columns');
550
551
            if ($columns == 'max') {
552
                $result['columns'] = 'max';
553
            } else {
554
                $result['columns'] = $this->getInteger($columns, 80);
555
            }
556
        }
557
558
        if ($root->hasAttribute('colors')) {
559
            /* only allow boolean for compatibility with previous versions
560
              'always' only allowed from command line */
561
            if ($this->getBoolean($root->getAttribute('colors'), false)) {
562
                $result['colors'] = PHPUnit_TextUI_ResultPrinter::COLOR_AUTO;
563
            } else {
564
                $result['colors'] = PHPUnit_TextUI_ResultPrinter::COLOR_NEVER;
565
            }
566
        }
567
568
        /*
569
         * Issue #657
570
         */
571
        if ($root->hasAttribute('stderr')) {
572
            $result['stderr'] = $this->getBoolean(
573
                (string) $root->getAttribute('stderr'),
574
                false
575
            );
576
        }
577
578
        if ($root->hasAttribute('backupGlobals')) {
579
            $result['backupGlobals'] = $this->getBoolean(
580
                (string) $root->getAttribute('backupGlobals'),
581
                true
582
            );
583
        }
584
585
        if ($root->hasAttribute('backupStaticAttributes')) {
586
            $result['backupStaticAttributes'] = $this->getBoolean(
587
                (string) $root->getAttribute('backupStaticAttributes'),
588
                false
589
            );
590
        }
591
592
        if ($root->getAttribute('bootstrap')) {
593
            $result['bootstrap'] = $this->toAbsolutePath(
594
                (string) $root->getAttribute('bootstrap')
595
            );
596
        }
597
598
        if ($root->hasAttribute('convertErrorsToExceptions')) {
599
            $result['convertErrorsToExceptions'] = $this->getBoolean(
600
                (string) $root->getAttribute('convertErrorsToExceptions'),
601
                true
602
            );
603
        }
604
605
        if ($root->hasAttribute('convertNoticesToExceptions')) {
606
            $result['convertNoticesToExceptions'] = $this->getBoolean(
607
                (string) $root->getAttribute('convertNoticesToExceptions'),
608
                true
609
            );
610
        }
611
612
        if ($root->hasAttribute('convertWarningsToExceptions')) {
613
            $result['convertWarningsToExceptions'] = $this->getBoolean(
614
                (string) $root->getAttribute('convertWarningsToExceptions'),
615
                true
616
            );
617
        }
618
619
        if ($root->hasAttribute('forceCoversAnnotation')) {
620
            $result['forceCoversAnnotation'] = $this->getBoolean(
621
                (string) $root->getAttribute('forceCoversAnnotation'),
622
                false
623
            );
624
        }
625
626
        if ($root->hasAttribute('disableCodeCoverageIgnore')) {
627
            $result['disableCodeCoverageIgnore'] = $this->getBoolean(
628
                (string) $root->getAttribute('disableCodeCoverageIgnore'),
629
                false
630
            );
631
        }
632
633
        if ($root->hasAttribute('processIsolation')) {
634
            $result['processIsolation'] = $this->getBoolean(
635
                (string) $root->getAttribute('processIsolation'),
636
                false
637
            );
638
        }
639
640
        if ($root->hasAttribute('stopOnError')) {
641
            $result['stopOnError'] = $this->getBoolean(
642
                (string) $root->getAttribute('stopOnError'),
643
                false
644
            );
645
        }
646
647
        if ($root->hasAttribute('stopOnFailure')) {
648
            $result['stopOnFailure'] = $this->getBoolean(
649
                (string) $root->getAttribute('stopOnFailure'),
650
                false
651
            );
652
        }
653
654
        if ($root->hasAttribute('stopOnWarning')) {
655
            $result['stopOnWarning'] = $this->getBoolean(
656
                (string) $root->getAttribute('stopOnWarning'),
657
                false
658
            );
659
        }
660
661
        if ($root->hasAttribute('stopOnIncomplete')) {
662
            $result['stopOnIncomplete'] = $this->getBoolean(
663
                (string) $root->getAttribute('stopOnIncomplete'),
664
                false
665
            );
666
        }
667
668
        if ($root->hasAttribute('stopOnRisky')) {
669
            $result['stopOnRisky'] = $this->getBoolean(
670
                (string) $root->getAttribute('stopOnRisky'),
671
                false
672
            );
673
        }
674
675
        if ($root->hasAttribute('stopOnSkipped')) {
676
            $result['stopOnSkipped'] = $this->getBoolean(
677
                (string) $root->getAttribute('stopOnSkipped'),
678
                false
679
            );
680
        }
681
682
        if ($root->hasAttribute('failOnWarning')) {
683
            $result['failOnWarning'] = $this->getBoolean(
684
                (string) $root->getAttribute('failOnWarning'),
685
                false
686
            );
687
        }
688
689
        if ($root->hasAttribute('failOnRisky')) {
690
            $result['failOnRisky'] = $this->getBoolean(
691
                (string) $root->getAttribute('failOnRisky'),
692
                false
693
            );
694
        }
695
696
        if ($root->hasAttribute('testSuiteLoaderClass')) {
697
            $result['testSuiteLoaderClass'] = (string) $root->getAttribute(
698
                'testSuiteLoaderClass'
699
            );
700
        }
701
702
        if ($root->getAttribute('testSuiteLoaderFile')) {
703
            $result['testSuiteLoaderFile'] = $this->toAbsolutePath(
704
                (string) $root->getAttribute('testSuiteLoaderFile')
705
            );
706
        }
707
708
        if ($root->hasAttribute('printerClass')) {
709
            $result['printerClass'] = (string) $root->getAttribute(
710
                'printerClass'
711
            );
712
        }
713
714
        if ($root->getAttribute('printerFile')) {
715
            $result['printerFile'] = $this->toAbsolutePath(
716
                (string) $root->getAttribute('printerFile')
717
            );
718
        }
719
720
        if ($root->hasAttribute('beStrictAboutChangesToGlobalState')) {
721
            $result['beStrictAboutChangesToGlobalState'] = $this->getBoolean(
722
                (string) $root->getAttribute('beStrictAboutChangesToGlobalState'),
723
                false
724
            );
725
        }
726
727
        if ($root->hasAttribute('beStrictAboutOutputDuringTests')) {
728
            $result['disallowTestOutput'] = $this->getBoolean(
729
                (string) $root->getAttribute('beStrictAboutOutputDuringTests'),
730
                false
731
            );
732
        }
733
734
        if ($root->hasAttribute('beStrictAboutResourceUsageDuringSmallTests')) {
735
            $result['beStrictAboutResourceUsageDuringSmallTests'] = $this->getBoolean(
736
                (string) $root->getAttribute('beStrictAboutResourceUsageDuringSmallTests'),
737
                false
738
            );
739
        }
740
741
        if ($root->hasAttribute('beStrictAboutTestsThatDoNotTestAnything')) {
742
            $result['reportUselessTests'] = $this->getBoolean(
743
                (string) $root->getAttribute('beStrictAboutTestsThatDoNotTestAnything'),
744
                false
745
            );
746
        }
747
748
        if ($root->hasAttribute('beStrictAboutTodoAnnotatedTests')) {
749
            $result['disallowTodoAnnotatedTests'] = $this->getBoolean(
750
                (string) $root->getAttribute('beStrictAboutTodoAnnotatedTests'),
751
                false
752
            );
753
        }
754
755
        if ($root->hasAttribute('beStrictAboutCoversAnnotation')) {
756
            $result['strictCoverage'] = $this->getBoolean(
757
                (string) $root->getAttribute('beStrictAboutCoversAnnotation'),
758
                false
759
            );
760
        } elseif ($root->hasAttribute('checkForUnintentionallyCoveredCode')) {
761
            $result['strictCoverage'] = $this->getBoolean(
762
                (string) $root->getAttribute('checkForUnintentionallyCoveredCode'),
763
                false
764
            );
765
766
            $result['deprecatedCheckForUnintentionallyCoveredCodeSettingUsed'] = true;
767
        }
768
769
        if ($root->hasAttribute('enforceTimeLimit')) {
770
            $result['enforceTimeLimit'] = $this->getBoolean(
771
                (string) $root->getAttribute('enforceTimeLimit'),
772
                false
773
            );
774
        }
775
776
        if ($root->hasAttribute('timeoutForSmallTests')) {
777
            $result['timeoutForSmallTests'] = $this->getInteger(
778
                (string) $root->getAttribute('timeoutForSmallTests'),
779
                1
780
            );
781
        }
782
783
        if ($root->hasAttribute('timeoutForMediumTests')) {
784
            $result['timeoutForMediumTests'] = $this->getInteger(
785
                (string) $root->getAttribute('timeoutForMediumTests'),
786
                10
787
            );
788
        }
789
790
        if ($root->hasAttribute('timeoutForLargeTests')) {
791
            $result['timeoutForLargeTests'] = $this->getInteger(
792
                (string) $root->getAttribute('timeoutForLargeTests'),
793
                60
794
            );
795
        }
796
797
        if ($root->hasAttribute('reverseDefectList')) {
798
            $result['reverseDefectList'] = $this->getBoolean(
799
                (string) $root->getAttribute('reverseDefectList'),
800
                false
801
            );
802
        }
803
804
        if ($root->hasAttribute('verbose')) {
805
            $result['verbose'] = $this->getBoolean(
806
                (string) $root->getAttribute('verbose'),
807
                false
808
            );
809
        }
810
811
        if ($root->hasAttribute('registerMockObjectsFromTestArgumentsRecursively')) {
812
            $result['registerMockObjectsFromTestArgumentsRecursively'] = $this->getBoolean(
813
                (string) $root->getAttribute('registerMockObjectsFromTestArgumentsRecursively'),
814
                false
815
            );
816
        }
817
818
        if ($root->hasAttribute('extensionsDirectory')) {
819
            $result['extensionsDirectory'] = $this->toAbsolutePath(
820
                    (string) $root->getAttribute(
821
                        'extensionsDirectory'
822
                    )
823
            );
824
        }
825
826
        return $result;
827
    }
828
829
    /**
830
     * Returns the test suite configuration.
831
     *
832
     * @return PHPUnit_Framework_TestSuite
833
     */
834
    public function getTestSuiteConfiguration($testSuiteFilter = null)
835
    {
836
        $testSuiteNodes = $this->xpath->query('testsuites/testsuite');
837
838
        if ($testSuiteNodes->length == 0) {
839
            $testSuiteNodes = $this->xpath->query('testsuite');
840
        }
841
842
        if ($testSuiteNodes->length == 1) {
843
            return $this->getTestSuite($testSuiteNodes->item(0), $testSuiteFilter);
844
        }
845
846
        if ($testSuiteNodes->length > 1) {
847
            $suite = new PHPUnit_Framework_TestSuite;
848
849
            foreach ($testSuiteNodes as $testSuiteNode) {
850
                $suite->addTestSuite(
851
                    $this->getTestSuite($testSuiteNode, $testSuiteFilter)
852
                );
853
            }
854
855
            return $suite;
856
        }
857
    }
858
859
    /**
860
     * Returns the test suite names from the configuration.
861
     *
862
     * @return array
863
     */
864
    public function getTestSuiteNames()
865
    {
866
        $names = [];
867
        $nodes = $this->xpath->query('*/testsuite');
868
        foreach ($nodes as $node) {
869
            $names[] = $node->getAttribute('name');
870
        }
871
872
        return $names;
873
    }
874
875
    /**
876
     * @param DOMElement $testSuiteNode
877
     *
878
     * @return PHPUnit_Framework_TestSuite
879
     */
880
    protected function getTestSuite(DOMElement $testSuiteNode, $testSuiteFilter = null)
881
    {
882
        if ($testSuiteNode->hasAttribute('name')) {
883
            $suite = new PHPUnit_Framework_TestSuite(
884
                (string) $testSuiteNode->getAttribute('name')
885
            );
886
        } else {
887
            $suite = new PHPUnit_Framework_TestSuite;
888
        }
889
890
        $exclude = [];
891
892
        foreach ($testSuiteNode->getElementsByTagName('exclude') as $excludeNode) {
893
            $excludeFile = (string) $excludeNode->textContent;
894
            if ($excludeFile) {
895
                $exclude[] = $this->toAbsolutePath($excludeFile);
896
            }
897
        }
898
899
        $fileIteratorFacade = new File_Iterator_Facade;
900
901
        foreach ($testSuiteNode->getElementsByTagName('directory') as $directoryNode) {
902
            if ($testSuiteFilter && $directoryNode->parentNode->getAttribute('name') != $testSuiteFilter) {
903
                continue;
904
            }
905
906
            $directory = (string) $directoryNode->textContent;
907
908
            if (empty($directory)) {
909
                continue;
910
            }
911
912
            if ($directoryNode->hasAttribute('phpVersion')) {
913
                $phpVersion = (string) $directoryNode->getAttribute('phpVersion');
914
            } else {
915
                $phpVersion = PHP_VERSION;
916
            }
917
918
            if ($directoryNode->hasAttribute('phpVersionOperator')) {
919
                $phpVersionOperator = (string) $directoryNode->getAttribute('phpVersionOperator');
920
            } else {
921
                $phpVersionOperator = '>=';
922
            }
923
924
            if (!version_compare(PHP_VERSION, $phpVersion, $phpVersionOperator)) {
925
                continue;
926
            }
927
928
            if ($directoryNode->hasAttribute('prefix')) {
929
                $prefix = (string) $directoryNode->getAttribute('prefix');
930
            } else {
931
                $prefix = '';
932
            }
933
934
            if ($directoryNode->hasAttribute('suffix')) {
935
                $suffix = (string) $directoryNode->getAttribute('suffix');
936
            } else {
937
                $suffix = 'Test.php';
938
            }
939
940
            $files = $fileIteratorFacade->getFilesAsArray(
941
                $this->toAbsolutePath($directory),
942
                $suffix,
943
                $prefix,
944
                $exclude
945
            );
946
            $suite->addTestFiles($files);
947
        }
948
949
        foreach ($testSuiteNode->getElementsByTagName('file') as $fileNode) {
950
            if ($testSuiteFilter && $fileNode->parentNode->getAttribute('name') != $testSuiteFilter) {
951
                continue;
952
            }
953
954
            $file = (string) $fileNode->textContent;
955
956
            if (empty($file)) {
957
                continue;
958
            }
959
960
            // Get the absolute path to the file
961
            $file = $fileIteratorFacade->getFilesAsArray(
962
                $this->toAbsolutePath($file)
963
            );
964
965
            if (!isset($file[0])) {
966
                continue;
967
            }
968
969
            $file = $file[0];
970
971
            if ($fileNode->hasAttribute('phpVersion')) {
972
                $phpVersion = (string) $fileNode->getAttribute('phpVersion');
973
            } else {
974
                $phpVersion = PHP_VERSION;
975
            }
976
977
            if ($fileNode->hasAttribute('phpVersionOperator')) {
978
                $phpVersionOperator = (string) $fileNode->getAttribute('phpVersionOperator');
979
            } else {
980
                $phpVersionOperator = '>=';
981
            }
982
983
            if (!version_compare(PHP_VERSION, $phpVersion, $phpVersionOperator)) {
984
                continue;
985
            }
986
987
            $suite->addTestFile($file);
988
        }
989
990
        return $suite;
991
    }
992
993
    /**
994
     * @param string $value
995
     * @param bool   $default
996
     *
997
     * @return bool
998
     */
999
    protected function getBoolean($value, $default)
1000
    {
1001
        if (strtolower($value) == 'false') {
1002
            return false;
1003
        } elseif (strtolower($value) == 'true') {
1004
            return true;
1005
        }
1006
1007
        return $default;
1008
    }
1009
1010
    /**
1011
     * @param string $value
1012
     * @param bool   $default
1013
     *
1014
     * @return bool
1015
     */
1016
    protected function getInteger($value, $default)
1017
    {
1018
        if (is_numeric($value)) {
1019
            return (int) $value;
1020
        }
1021
1022
        return $default;
1023
    }
1024
1025
    /**
1026
     * @param string $query
1027
     *
1028
     * @return array
1029
     */
1030
    protected function readFilterDirectories($query)
1031
    {
1032
        $directories = [];
1033
1034
        foreach ($this->xpath->query($query) as $directory) {
1035
            $directoryPath = (string) $directory->textContent;
1036
1037
            if (!$directoryPath) {
1038
                continue;
1039
            }
1040
1041
            if ($directory->hasAttribute('prefix')) {
1042
                $prefix = (string) $directory->getAttribute('prefix');
1043
            } else {
1044
                $prefix = '';
1045
            }
1046
1047
            if ($directory->hasAttribute('suffix')) {
1048
                $suffix = (string) $directory->getAttribute('suffix');
1049
            } else {
1050
                $suffix = '.php';
1051
            }
1052
1053
            if ($directory->hasAttribute('group')) {
1054
                $group = (string) $directory->getAttribute('group');
1055
            } else {
1056
                $group = 'DEFAULT';
1057
            }
1058
1059
            $directories[] = [
1060
              'path'   => $this->toAbsolutePath($directoryPath),
1061
              'prefix' => $prefix,
1062
              'suffix' => $suffix,
1063
              'group'  => $group
1064
            ];
1065
        }
1066
1067
        return $directories;
1068
    }
1069
1070
    /**
1071
     * @param string $query
1072
     *
1073
     * @return array
1074
     */
1075
    protected function readFilterFiles($query)
1076
    {
1077
        $files = [];
1078
1079
        foreach ($this->xpath->query($query) as $file) {
1080
            $filePath = (string) $file->textContent;
1081
1082
            if ($filePath) {
1083
                $files[] = $this->toAbsolutePath($filePath);
1084
            }
1085
        }
1086
1087
        return $files;
1088
    }
1089
1090
    /**
1091
     * @param string $path
1092
     * @param bool   $useIncludePath
1093
     *
1094
     * @return string
1095
     */
1096
    protected function toAbsolutePath($path, $useIncludePath = false)
1097
    {
1098
        $path = trim($path);
1099
1100
        if ($path[0] === '/') {
1101
            return $path;
1102
        }
1103
1104
        // Matches the following on Windows:
1105
        //  - \\NetworkComputer\Path
1106
        //  - \\.\D:
1107
        //  - \\.\c:
1108
        //  - C:\Windows
1109
        //  - C:\windows
1110
        //  - C:/windows
1111
        //  - c:/windows
1112
        if (defined('PHP_WINDOWS_VERSION_BUILD') &&
1113
            ($path[0] === '\\' ||
1114
            (strlen($path) >= 3 && preg_match('#^[A-Z]\:[/\\\]#i', substr($path, 0, 3))))) {
1115
            return $path;
1116
        }
1117
1118
        // Stream
1119
        if (strpos($path, '://') !== false) {
1120
            return $path;
1121
        }
1122
1123
        $file = dirname($this->filename) . DIRECTORY_SEPARATOR . $path;
1124
1125
        if ($useIncludePath && !file_exists($file)) {
1126
            $includePathFile = stream_resolve_include_path($path);
1127
1128
            if ($includePathFile) {
1129
                $file = $includePathFile;
1130
            }
1131
        }
1132
1133
        return $file;
1134
    }
1135
}
1136