Clover::process()   F
last analyzed

Complexity

Conditions 29
Paths > 20000

Size

Total Lines 228
Code Lines 146

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 29
eloc 146
nc 314584
nop 3
dl 0
loc 228
rs 0
c 0
b 0
f 0

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 the php-code-coverage package.
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
namespace SebastianBergmann\CodeCoverage\Report;
11
12
use SebastianBergmann\CodeCoverage\CodeCoverage;
13
use SebastianBergmann\CodeCoverage\Node\File;
14
use SebastianBergmann\CodeCoverage\RuntimeException;
15
16
/**
17
 * Generates a Clover XML logfile from a code coverage object.
18
 */
19
final class Clover
20
{
21
    /**
22
     * @throws \RuntimeException
23
     */
24
    public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string
25
    {
26
        $xmlDocument               = new \DOMDocument('1.0', 'UTF-8');
27
        $xmlDocument->formatOutput = true;
28
29
        $xmlCoverage = $xmlDocument->createElement('coverage');
30
        $xmlCoverage->setAttribute('generated', (int) $_SERVER['REQUEST_TIME']);
31
        $xmlDocument->appendChild($xmlCoverage);
32
33
        $xmlProject = $xmlDocument->createElement('project');
34
        $xmlProject->setAttribute('timestamp', (int) $_SERVER['REQUEST_TIME']);
35
36
        if (\is_string($name)) {
37
            $xmlProject->setAttribute('name', $name);
38
        }
39
40
        $xmlCoverage->appendChild($xmlProject);
41
42
        $packages = [];
43
        $report   = $coverage->getReport();
44
45
        foreach ($report as $item) {
46
            if (!$item instanceof File) {
47
                continue;
48
            }
49
50
            /* @var File $item */
51
52
            $xmlFile = $xmlDocument->createElement('file');
53
            $xmlFile->setAttribute('name', $item->getPath());
54
55
            $classes      = $item->getClassesAndTraits();
56
            $coverageData = $item->getCoverageData();
57
            $lines        = [];
58
            $namespace    = 'global';
59
60
            foreach ($classes as $className => $class) {
61
                $classStatements        = 0;
62
                $coveredClassStatements = 0;
63
                $coveredMethods         = 0;
64
                $classMethods           = 0;
65
66
                foreach ($class['methods'] as $methodName => $method) {
67
                    if ($method['executableLines'] == 0) {
68
                        continue;
69
                    }
70
71
                    $classMethods++;
72
                    $classStatements += $method['executableLines'];
73
                    $coveredClassStatements += $method['executedLines'];
74
75
                    if ($method['coverage'] == 100) {
76
                        $coveredMethods++;
77
                    }
78
79
                    $methodCount = 0;
80
81
                    foreach (\range($method['startLine'], $method['endLine']) as $line) {
82
                        if (isset($coverageData[$line]) && ($coverageData[$line] !== null)) {
83
                            $methodCount = \max($methodCount, \count($coverageData[$line]));
84
                        }
85
                    }
86
87
                    $lines[$method['startLine']] = [
88
                        'ccn'         => $method['ccn'],
89
                        'count'       => $methodCount,
90
                        'crap'        => $method['crap'],
91
                        'type'        => 'method',
92
                        'visibility'  => $method['visibility'],
93
                        'name'        => $methodName,
94
                    ];
95
                }
96
97
                if (!empty($class['package']['namespace'])) {
98
                    $namespace = $class['package']['namespace'];
99
                }
100
101
                $xmlClass = $xmlDocument->createElement('class');
102
                $xmlClass->setAttribute('name', $className);
103
                $xmlClass->setAttribute('namespace', $namespace);
104
105
                if (!empty($class['package']['fullPackage'])) {
106
                    $xmlClass->setAttribute(
107
                        'fullPackage',
108
                        $class['package']['fullPackage']
109
                    );
110
                }
111
112
                if (!empty($class['package']['category'])) {
113
                    $xmlClass->setAttribute(
114
                        'category',
115
                        $class['package']['category']
116
                    );
117
                }
118
119
                if (!empty($class['package']['package'])) {
120
                    $xmlClass->setAttribute(
121
                        'package',
122
                        $class['package']['package']
123
                    );
124
                }
125
126
                if (!empty($class['package']['subpackage'])) {
127
                    $xmlClass->setAttribute(
128
                        'subpackage',
129
                        $class['package']['subpackage']
130
                    );
131
                }
132
133
                $xmlFile->appendChild($xmlClass);
134
135
                $xmlMetrics = $xmlDocument->createElement('metrics');
136
                $xmlMetrics->setAttribute('complexity', $class['ccn']);
137
                $xmlMetrics->setAttribute('methods', $classMethods);
138
                $xmlMetrics->setAttribute('coveredmethods', $coveredMethods);
139
                $xmlMetrics->setAttribute('conditionals', 0);
140
                $xmlMetrics->setAttribute('coveredconditionals', 0);
141
                $xmlMetrics->setAttribute('statements', $classStatements);
142
                $xmlMetrics->setAttribute('coveredstatements', $coveredClassStatements);
143
                $xmlMetrics->setAttribute('elements', $classMethods + $classStatements /* + conditionals */);
144
                $xmlMetrics->setAttribute('coveredelements', $coveredMethods + $coveredClassStatements /* + coveredconditionals */);
145
                $xmlClass->appendChild($xmlMetrics);
146
            }
147
148
            foreach ($coverageData as $line => $data) {
149
                if ($data === null || isset($lines[$line])) {
150
                    continue;
151
                }
152
153
                $lines[$line] = [
154
                    'count' => \count($data), 'type' => 'stmt',
155
                ];
156
            }
157
158
            \ksort($lines);
159
160
            foreach ($lines as $line => $data) {
161
                $xmlLine = $xmlDocument->createElement('line');
162
                $xmlLine->setAttribute('num', $line);
163
                $xmlLine->setAttribute('type', $data['type']);
164
165
                if (isset($data['name'])) {
166
                    $xmlLine->setAttribute('name', $data['name']);
167
                }
168
169
                if (isset($data['visibility'])) {
170
                    $xmlLine->setAttribute('visibility', $data['visibility']);
171
                }
172
173
                if (isset($data['ccn'])) {
174
                    $xmlLine->setAttribute('complexity', $data['ccn']);
175
                }
176
177
                if (isset($data['crap'])) {
178
                    $xmlLine->setAttribute('crap', $data['crap']);
179
                }
180
181
                $xmlLine->setAttribute('count', $data['count']);
182
                $xmlFile->appendChild($xmlLine);
183
            }
184
185
            $linesOfCode = $item->getLinesOfCode();
186
187
            $xmlMetrics = $xmlDocument->createElement('metrics');
188
            $xmlMetrics->setAttribute('loc', $linesOfCode['loc']);
189
            $xmlMetrics->setAttribute('ncloc', $linesOfCode['ncloc']);
190
            $xmlMetrics->setAttribute('classes', $item->getNumClassesAndTraits());
191
            $xmlMetrics->setAttribute('methods', $item->getNumMethods());
192
            $xmlMetrics->setAttribute('coveredmethods', $item->getNumTestedMethods());
193
            $xmlMetrics->setAttribute('conditionals', 0);
194
            $xmlMetrics->setAttribute('coveredconditionals', 0);
195
            $xmlMetrics->setAttribute('statements', $item->getNumExecutableLines());
196
            $xmlMetrics->setAttribute('coveredstatements', $item->getNumExecutedLines());
197
            $xmlMetrics->setAttribute('elements', $item->getNumMethods() + $item->getNumExecutableLines() /* + conditionals */);
198
            $xmlMetrics->setAttribute('coveredelements', $item->getNumTestedMethods() + $item->getNumExecutedLines() /* + coveredconditionals */);
199
            $xmlFile->appendChild($xmlMetrics);
200
201
            if ($namespace === 'global') {
202
                $xmlProject->appendChild($xmlFile);
203
            } else {
204
                if (!isset($packages[$namespace])) {
205
                    $packages[$namespace] = $xmlDocument->createElement(
206
                        'package'
207
                    );
208
209
                    $packages[$namespace]->setAttribute('name', $namespace);
210
                    $xmlProject->appendChild($packages[$namespace]);
211
                }
212
213
                $packages[$namespace]->appendChild($xmlFile);
214
            }
215
        }
216
217
        $linesOfCode = $report->getLinesOfCode();
218
219
        $xmlMetrics = $xmlDocument->createElement('metrics');
220
        $xmlMetrics->setAttribute('files', \count($report));
221
        $xmlMetrics->setAttribute('loc', $linesOfCode['loc']);
222
        $xmlMetrics->setAttribute('ncloc', $linesOfCode['ncloc']);
223
        $xmlMetrics->setAttribute('classes', $report->getNumClassesAndTraits());
224
        $xmlMetrics->setAttribute('methods', $report->getNumMethods());
225
        $xmlMetrics->setAttribute('coveredmethods', $report->getNumTestedMethods());
226
        $xmlMetrics->setAttribute('conditionals', 0);
227
        $xmlMetrics->setAttribute('coveredconditionals', 0);
228
        $xmlMetrics->setAttribute('statements', $report->getNumExecutableLines());
229
        $xmlMetrics->setAttribute('coveredstatements', $report->getNumExecutedLines());
230
        $xmlMetrics->setAttribute('elements', $report->getNumMethods() + $report->getNumExecutableLines() /* + conditionals */);
231
        $xmlMetrics->setAttribute('coveredelements', $report->getNumTestedMethods() + $report->getNumExecutedLines() /* + coveredconditionals */);
232
        $xmlProject->appendChild($xmlMetrics);
233
234
        $buffer = $xmlDocument->saveXML();
235
236
        if ($target !== null) {
237
            if (!$this->createDirectory(\dirname($target))) {
238
                throw new \RuntimeException(\sprintf('Directory "%s" was not created', \dirname($target)));
239
            }
240
241
            if (@\file_put_contents($target, $buffer) === false) {
242
                throw new RuntimeException(
243
                    \sprintf(
244
                        'Could not write to "%s',
245
                        $target
246
                    )
247
                );
248
            }
249
        }
250
251
        return $buffer;
252
    }
253
254
    private function createDirectory(string $directory): bool
255
    {
256
        return !(!\is_dir($directory) && !@\mkdir($directory, 0777, true) && !\is_dir($directory));
257
    }
258
}
259