comparison vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php @ 14:1fec387a4317

Update Drupal core to 8.5.2 via Composer
author Chris Cannam
date Mon, 23 Apr 2018 09:46:53 +0100
parents
children
comparison
equal deleted inserted replaced
13:5fb285c0d0e3 14:1fec387a4317
1 <?php
2 /*
3 * This file is part of the php-code-coverage package.
4 *
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
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 namespace SebastianBergmann\CodeCoverage\Report\Xml;
12
13 use SebastianBergmann\CodeCoverage\CodeCoverage;
14 use SebastianBergmann\CodeCoverage\Node\AbstractNode;
15 use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
16 use SebastianBergmann\CodeCoverage\Node\File as FileNode;
17 use SebastianBergmann\CodeCoverage\RuntimeException;
18 use SebastianBergmann\CodeCoverage\Version;
19 use SebastianBergmann\Environment\Runtime;
20
21 class Facade
22 {
23 /**
24 * @var string
25 */
26 private $target;
27
28 /**
29 * @var Project
30 */
31 private $project;
32
33 /**
34 * @var string
35 */
36 private $phpUnitVersion;
37
38 /**
39 * @param string $version
40 */
41 public function __construct($version)
42 {
43 $this->phpUnitVersion = $version;
44 }
45
46 /**
47 * @param CodeCoverage $coverage
48 * @param string $target
49 *
50 * @throws RuntimeException
51 */
52 public function process(CodeCoverage $coverage, $target)
53 {
54 if (\substr($target, -1, 1) != DIRECTORY_SEPARATOR) {
55 $target .= DIRECTORY_SEPARATOR;
56 }
57
58 $this->target = $target;
59 $this->initTargetDirectory($target);
60
61 $report = $coverage->getReport();
62
63 $this->project = new Project(
64 $coverage->getReport()->getName()
65 );
66
67 $this->setBuildInformation();
68 $this->processTests($coverage->getTests());
69 $this->processDirectory($report, $this->project);
70
71 $this->saveDocument($this->project->asDom(), 'index');
72 }
73
74 private function setBuildInformation()
75 {
76 $buildNode = $this->project->getBuildInformation();
77 $buildNode->setRuntimeInformation(new Runtime());
78 $buildNode->setBuildTime(\DateTime::createFromFormat('U', $_SERVER['REQUEST_TIME']));
79 $buildNode->setGeneratorVersions($this->phpUnitVersion, Version::id());
80 }
81
82 /**
83 * @param string $directory
84 */
85 protected function initTargetDirectory($directory)
86 {
87 if (\file_exists($directory)) {
88 if (!\is_dir($directory)) {
89 throw new RuntimeException(
90 "'$directory' exists but is not a directory."
91 );
92 }
93
94 if (!\is_writable($directory)) {
95 throw new RuntimeException(
96 "'$directory' exists but is not writable."
97 );
98 }
99 } elseif (!@\mkdir($directory, 0777, true)) {
100 throw new RuntimeException(
101 "'$directory' could not be created."
102 );
103 }
104 }
105
106 private function processDirectory(DirectoryNode $directory, Node $context)
107 {
108 $dirname = $directory->getName();
109 if ($this->project->getProjectSourceDirectory() === $dirname) {
110 $dirname = '/';
111 }
112 $dirObject = $context->addDirectory($dirname);
113
114 $this->setTotals($directory, $dirObject->getTotals());
115
116 foreach ($directory->getDirectories() as $node) {
117 $this->processDirectory($node, $dirObject);
118 }
119
120 foreach ($directory->getFiles() as $node) {
121 $this->processFile($node, $dirObject);
122 }
123 }
124
125 private function processFile(FileNode $file, Directory $context)
126 {
127 $fileObject = $context->addFile(
128 $file->getName(),
129 $file->getId() . '.xml'
130 );
131
132 $this->setTotals($file, $fileObject->getTotals());
133
134 $path = \substr(
135 $file->getPath(),
136 \strlen($this->project->getProjectSourceDirectory())
137 );
138 $fileReport = new Report($path);
139
140 $this->setTotals($file, $fileReport->getTotals());
141
142 foreach ($file->getClassesAndTraits() as $unit) {
143 $this->processUnit($unit, $fileReport);
144 }
145
146 foreach ($file->getFunctions() as $function) {
147 $this->processFunction($function, $fileReport);
148 }
149
150 foreach ($file->getCoverageData() as $line => $tests) {
151 if (!\is_array($tests) || \count($tests) === 0) {
152 continue;
153 }
154
155 $coverage = $fileReport->getLineCoverage($line);
156
157 foreach ($tests as $test) {
158 $coverage->addTest($test);
159 }
160
161 $coverage->finalize();
162 }
163
164 $fileReport->getSource()->setSourceCode(
165 \file_get_contents($file->getPath())
166 );
167
168 $this->saveDocument($fileReport->asDom(), $file->getId());
169 }
170
171 private function processUnit($unit, Report $report)
172 {
173 if (isset($unit['className'])) {
174 $unitObject = $report->getClassObject($unit['className']);
175 } else {
176 $unitObject = $report->getTraitObject($unit['traitName']);
177 }
178
179 $unitObject->setLines(
180 $unit['startLine'],
181 $unit['executableLines'],
182 $unit['executedLines']
183 );
184
185 $unitObject->setCrap($unit['crap']);
186
187 $unitObject->setPackage(
188 $unit['package']['fullPackage'],
189 $unit['package']['package'],
190 $unit['package']['subpackage'],
191 $unit['package']['category']
192 );
193
194 $unitObject->setNamespace($unit['package']['namespace']);
195
196 foreach ($unit['methods'] as $method) {
197 $methodObject = $unitObject->addMethod($method['methodName']);
198 $methodObject->setSignature($method['signature']);
199 $methodObject->setLines($method['startLine'], $method['endLine']);
200 $methodObject->setCrap($method['crap']);
201 $methodObject->setTotals(
202 $method['executableLines'],
203 $method['executedLines'],
204 $method['coverage']
205 );
206 }
207 }
208
209 private function processFunction($function, Report $report)
210 {
211 $functionObject = $report->getFunctionObject($function['functionName']);
212
213 $functionObject->setSignature($function['signature']);
214 $functionObject->setLines($function['startLine']);
215 $functionObject->setCrap($function['crap']);
216 $functionObject->setTotals($function['executableLines'], $function['executedLines'], $function['coverage']);
217 }
218
219 private function processTests(array $tests)
220 {
221 $testsObject = $this->project->getTests();
222
223 foreach ($tests as $test => $result) {
224 if ($test == 'UNCOVERED_FILES_FROM_WHITELIST') {
225 continue;
226 }
227
228 $testsObject->addTest($test, $result);
229 }
230 }
231
232 private function setTotals(AbstractNode $node, Totals $totals)
233 {
234 $loc = $node->getLinesOfCode();
235
236 $totals->setNumLines(
237 $loc['loc'],
238 $loc['cloc'],
239 $loc['ncloc'],
240 $node->getNumExecutableLines(),
241 $node->getNumExecutedLines()
242 );
243
244 $totals->setNumClasses(
245 $node->getNumClasses(),
246 $node->getNumTestedClasses()
247 );
248
249 $totals->setNumTraits(
250 $node->getNumTraits(),
251 $node->getNumTestedTraits()
252 );
253
254 $totals->setNumMethods(
255 $node->getNumMethods(),
256 $node->getNumTestedMethods()
257 );
258
259 $totals->setNumFunctions(
260 $node->getNumFunctions(),
261 $node->getNumTestedFunctions()
262 );
263 }
264
265 /**
266 * @return string
267 */
268 protected function getTargetDirectory()
269 {
270 return $this->target;
271 }
272
273 protected function saveDocument(\DOMDocument $document, $name)
274 {
275 $filename = \sprintf('%s/%s.xml', $this->getTargetDirectory(), $name);
276
277 $document->formatOutput = true;
278 $document->preserveWhiteSpace = false;
279 $this->initTargetDirectory(\dirname($filename));
280
281 $document->save($filename);
282 }
283 }