Filter::addTestsFromTestSuite()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.9666
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Paraunit\Filter;
6
7 1
if (! class_exists('SebastianBergmann\FileIterator\Facade')) {
8
    \class_alias('\File_Iterator_Facade', 'SebastianBergmann\FileIterator\Facade');
9
}
10
11
use Paraunit\Configuration\PHPUnitConfig;
12
use Paraunit\Proxy\PHPUnitUtilXMLProxy;
13
use SebastianBergmann\FileIterator\Facade;
14
15
/**
16
 * Class Filter
17
 * @package Paraunit\Filter
18
 */
19
class Filter
20
{
21
    /** @var PHPUnitUtilXMLProxy */
22
    private $utilXml;
23
24
    /** @var Facade */
25
    private $fileIteratorFacade;
26
27
    /** @var PHPUnitConfig */
28
    private $configFile;
29
30
    /** @var string | null */
31
    private $relativePath;
32
33
    /** @var string | null */
34
    private $testSuiteFilter;
35
36
    /** @var string | null */
37
    private $stringFilter;
38
39
    /**
40
     * @param PHPUnitUtilXMLProxy $utilXml
41
     * @param Facade $fileIteratorFacade
42
     * @param PHPUnitConfig $configFile
43
     * @param string | null $testSuiteFilter
44
     * @param string | null $stringFilter
45
     */
46 48
    public function __construct(
47
        PHPUnitUtilXMLProxy $utilXml,
48
        Facade $fileIteratorFacade,
49
        PHPUnitConfig $configFile,
50
        string $testSuiteFilter = null,
51
        string $stringFilter = null
52
    ) {
53 48
        $this->utilXml = $utilXml;
54 48
        $this->fileIteratorFacade = $fileIteratorFacade;
55 48
        $this->configFile = $configFile;
56 48
        $this->relativePath = $configFile->getBaseDirectory() . DIRECTORY_SEPARATOR;
57 48
        $this->testSuiteFilter = $testSuiteFilter;
58 48
        $this->stringFilter = $stringFilter;
59
    }
60
61
    /**
62
     * @return string[]
63
     * @throws \RuntimeException
64
     */
65 32
    public function filterTestFiles(): array
66
    {
67 32
        $aggregatedFiles = [];
68
69 32
        $document = $this->utilXml->loadFile($this->configFile->getFileFullPath());
70 32
        $xpath = new \DOMXPath($document);
71
72
        /** @var \DOMElement $testSuiteNode */
73 32
        foreach ($xpath->query('testsuites/testsuite') as $testSuiteNode) {
74 32
            if ($this->testSuitePassFilter($testSuiteNode, $this->testSuiteFilter)) {
75 32
                $this->addTestsFromTestSuite($testSuiteNode, $aggregatedFiles);
76
            }
77
        }
78
79 32
        return $this->filterByString($aggregatedFiles, $this->stringFilter);
80
    }
81
82 32
    private function testSuitePassFilter(\DOMElement $testSuiteNode, string $testSuiteFilter = null): bool
83
    {
84 32
        if ($testSuiteFilter === null) {
85 30
            return true;
86
        }
87
88 2
        return \in_array(
89 2
            $this->getDOMNodeAttribute($testSuiteNode, 'name'),
90 2
            explode(',', $testSuiteFilter),
91 2
            true
92
        );
93
    }
94
95
    /**
96
     * @param \DOMElement $testSuiteNode
97
     * @param array $aggregatedFiles
98
     * @return string[]
99
     */
100 32
    private function addTestsFromTestSuite(\DOMElement $testSuiteNode, array &$aggregatedFiles): array
101
    {
102 32
        $excludes = $this->getExcludesArray($testSuiteNode);
103
104 32
        $this->addTestsFromDirectoryNodes($testSuiteNode, $aggregatedFiles, $excludes);
105 32
        $this->addTestsFromFileNodes($testSuiteNode, $aggregatedFiles);
106
107 32
        return $aggregatedFiles;
108
    }
109
110
    /**
111
     * @param \DOMElement $testSuiteNode
112
     * @return string[]
113
     */
114 32
    private function getExcludesArray(\DOMElement $testSuiteNode): array
115
    {
116 32
        $excludes = [];
117 32
        foreach ($testSuiteNode->getElementsByTagName('exclude') as $excludeNode) {
118 1
            $excludes[] = (string) $excludeNode->nodeValue;
119
        }
120
121 32
        return $excludes;
122
    }
123
124
    /**
125
     * @param \DOMElement $testSuiteNode
126
     * @param string[] $aggregatedFiles
127
     * @param string[] $excludes
128
     */
129 32
    private function addTestsFromDirectoryNodes(\DOMElement $testSuiteNode, array &$aggregatedFiles, array $excludes)
130
    {
131 32
        foreach ($testSuiteNode->getElementsByTagName('directory') as $directoryNode) {
132 30
            $directory = (string) $directoryNode->nodeValue;
133
134 30
            $files = $this->fileIteratorFacade->getFilesAsArray(
135 30
                $this->relativePath . $directory,
136 30
                $this->getDOMNodeAttribute($directoryNode, 'suffix', 'Test.php'),
137 30
                $this->getDOMNodeAttribute($directoryNode, 'prefix', ''),
138 30
                $excludes
139
            );
140
141 30
            foreach ($files as $fileName) {
142 30
                $this->addFileToAggregateArray($aggregatedFiles, $fileName);
143
            }
144
        }
145
    }
146
147
    /**
148
     * @param \DOMElement $testSuiteNode
149
     * @param string[] $aggregatedFiles
150
     */
151 32
    private function addTestsFromFileNodes(\DOMElement $testSuiteNode, array &$aggregatedFiles)
152
    {
153 32
        foreach ($testSuiteNode->getElementsByTagName('file') as $fileNode) {
154 3
            $fileName = $this->relativePath . (string) $fileNode->nodeValue;
155 3
            $this->addFileToAggregateArray($aggregatedFiles, $fileName);
156
        }
157
    }
158
159
    /**
160
     * @param array $aggregatedFiles
161
     * @param string $fileName
162
     */
163 32
    private function addFileToAggregateArray(array &$aggregatedFiles, string $fileName)
164
    {
165
        // optimized array_unique
166 32
        $aggregatedFiles[$fileName] = $fileName;
167
    }
168
169
    /**
170
     * @param \DOMElement $testSuiteNode
171
     * @param string $nodeName
172
     * @param string|null $defaultValue
173
     *
174
     * @return string
175
     */
176 31
    private function getDOMNodeAttribute(
177
        \DOMElement $testSuiteNode,
178
        string $nodeName,
179
        string $defaultValue = null
180
    ): string {
181
        /**
182
         * @var string
183
         * @var \DOMAttr
184
         */
185 31
        foreach ($testSuiteNode->attributes as $attrName => $attrNode) {
186 26
            if ($attrName === $nodeName) {
187 26
                return $attrNode->value;
188
            }
189
        }
190
191 30
        return $defaultValue;
192
    }
193
194
    /**
195
     * @param array $aggregatedFiles
196
     * @param string | null $stringFilter
197
     * @return string[]
198
     */
199 32
    private function filterByString(array $aggregatedFiles, $stringFilter): array
200
    {
201 32
        if ($stringFilter !== null) {
202
            $aggregatedFiles = array_filter($aggregatedFiles, function ($value) use ($stringFilter) {
203 20
                return stripos($value, $stringFilter) !== false;
204 20
            });
205
        }
206
207 32
        return array_values($aggregatedFiles);
208
    }
209
}
210