Completed
Push — master ( 700290...87c316 )
by Julian
03:59 queued 02:02
created

Configuration::getSuitePaths()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 11
cts 11
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 11
nc 5
nop 1
crap 5
1
<?php
2
namespace ParaTest\Runners\PHPUnit;
3
4
/**
5
 * Class Configuration
6
 *
7
 * Stores information about the phpunit xml
8
 * configuration being used to run tests
9
 *
10
 * @package ParaTest\Runners\PHPUnit
11
 */
12
class Configuration
13
{
14
    /**
15
     * Path to the configuration file
16
     *
17
     * @var string
18
     */
19
    protected $path;
20
21
    /**
22
     * @var \SimpleXMLElement
23
     */
24
    protected $xml;
25
26
    protected $availableNodes = ['exclude', 'file', 'directory', 'testsuite'];
27
28
    /**
29
     * A collection of datastructures
30
     * build from the <testsuite> nodes inside of a
31
     * PHPUnit configuration
32
     *
33
     * @var array
34
     */
35
    protected $suites = [];
36
37 59
    public function __construct($path)
38
    {
39 59
        $this->path = $path;
40 59
        if (file_exists($path)) {
41 52
            $this->xml = simplexml_load_string(file_get_contents($path));
42
        }
43 59
    }
44
45
    /**
46
     * Get the bootstrap PHPUnit configuration attribute
47
     *
48
     * @return string The bootstrap attribute or empty string if not set
49
     */
50 4
    public function getBootstrap()
51
    {
52 4
        if ($this->xml) {
53 4
            return (string)$this->xml->attributes()->bootstrap;
54
        } else {
55
            return '';
56
        }
57
    }
58
59
    /**
60
     * Returns the path to the phpunit configuration
61
     * file
62
     *
63
     * @return string
64
     */
65 15
    public function getPath()
66
    {
67 15
        return $this->path;
68
    }
69
70
    /**
71
     * Return the contents of the <testsuite> nodes
72
     * contained in a PHPUnit configuration
73
     *
74
     * @return SuitePath[][]|null
75
     */
76 6
    public function getSuites()
77
    {
78 6
        if (!$this->xml) {
79 1
            return null;
80
        }
81 5
        $suites = [];
82 5
        $nodes  = $this->xml->xpath('//testsuites/testsuite');
83
84 5
        while (list(, $node) = each($nodes)) {
85 5
            $suites = array_merge_recursive($suites, $this->getSuiteByName((string)$node['name']));
86
        }
87 4
        return $suites;
88
    }
89
90
    /**
91
     * Return the contents of the <testsuite> nodes
92
     * contained in a PHPUnit configuration
93
     *
94
     * @param string $suiteName
95
     *
96
     * @return SuitePath[]|null
97
     */
98 15
    public function getSuiteByName($suiteName)
99
    {
100 15
        $nodes = $this->xml->xpath(sprintf('//testsuite[@name="%s"]', $suiteName));
101
102 15
        $suites        = [];
103 15
        $excludedPaths = [];
104 15
        while (list(, $node) = each($nodes)) {
105 15
            foreach ($this->availableNodes as $nodeName) {
106 15
                foreach ($node->{$nodeName} as $nodeContent) {
107
                    switch ($nodeName) {
108 15
                        case 'exclude':
109 3
                            foreach ($this->getSuitePaths((string)$nodeContent) as $excludedPath) {
110 3
                                $excludedPaths[$excludedPath] = $excludedPath;
111
                            }
112 3
                            break;
113 15
                        case 'testsuite':
114 1
                            $suites = array_merge_recursive($suites, $this->getSuiteByName((string)$nodeContent));
115 1
                            break;
116 15
                        case 'directory':
117
                            // Replicate behaviour of PHPUnit
118
                            // if a directory is included and excluded at the same time, then it is considered included
119 12
                            foreach ($this->getSuitePaths((string)$nodeContent) as $dir) {
120 11
                                if (array_key_exists($dir, $excludedPaths)) {
121 11
                                    unset($excludedPaths[$dir]);
122
                                }
123
                            }
124
                            // not breaking on purpose
125
                        default:
126 14
                            foreach ($this->getSuitePaths((string)$nodeContent) as $path) {
127 14
                                $suites[(string)$node['name']][] = new SuitePath(
128
                                    $path,
129
                                    $excludedPaths,
130 14
                                    $nodeContent->attributes()->suffix
131
                                );
132
                            }
133 15
                            break;
134
                    }
135
                }
136
            }
137
        }
138
139 14
        return $suites;
140
    }
141
142
    /**
143
     * Return the path of the directory
144
     * that contains the phpunit configuration
145
     *
146
     * @return string
147
     */
148 19
    public function getConfigDir()
149
    {
150 19
        return dirname($this->path).DIRECTORY_SEPARATOR;
151
    }
152
153
    /**
154
     * Returns a suite paths relative to the config file
155
     *
156
     * @param $path
157
     * @return array|string[]
158
     */
159 15
    public function getSuitePaths($path)
160
    {
161 15
        $real = realpath($this->getConfigDir().$path);
162
163 15
        if ($real !== false) {
164 13
            return [$real];
165
        }
166
167 2
        if ($this->isGlobRequired($path)) {
168 1
            $paths = [];
169 1
            foreach (glob($this->getConfigDir().$path, GLOB_ONLYDIR) as $path) {
170 1
                if (($path = realpath($path)) !== false) {
171 1
                    $paths[] = $path;
172
                }
173
            }
174 1
            return $paths;
175
        }
176
177 1
        throw new \RuntimeException("Suite path $path could not be found");
178
    }
179
180
    /**
181
     * Returns true if path needs globbing (like a /path/*-to/string)
182
     *
183
     * @param string $path
184
     * @return bool
185
     */
186 2
    public function isGlobRequired($path)
187
    {
188 2
        return strpos($path, '*') !== false;
189
    }
190
191
    /**
192
     * Converting the configuration to a string
193
     * returns the configuration path
194
     *
195
     * @return string
196
     */
197 3
    public function __toString()
198
    {
199 3
        return $this->path;
200
    }
201
}
202