Chris@0
|
1 <?php
|
Chris@0
|
2 /*
|
Chris@0
|
3 * This file is part of the PHP_CodeCoverage package.
|
Chris@0
|
4 *
|
Chris@0
|
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
|
Chris@0
|
6 *
|
Chris@0
|
7 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
8 * file that was distributed with this source code.
|
Chris@0
|
9 */
|
Chris@0
|
10
|
Chris@0
|
11 /**
|
Chris@0
|
12 * @since Class available since Release 2.0.0
|
Chris@0
|
13 */
|
Chris@0
|
14 class PHP_CodeCoverage_Report_Crap4j
|
Chris@0
|
15 {
|
Chris@0
|
16 /**
|
Chris@0
|
17 * @var int
|
Chris@0
|
18 */
|
Chris@0
|
19 private $threshold;
|
Chris@0
|
20
|
Chris@0
|
21 /**
|
Chris@0
|
22 * @param int $threshold
|
Chris@0
|
23 */
|
Chris@0
|
24 public function __construct($threshold = 30)
|
Chris@0
|
25 {
|
Chris@0
|
26 if (!is_int($threshold)) {
|
Chris@0
|
27 throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
|
Chris@0
|
28 1,
|
Chris@0
|
29 'integer'
|
Chris@0
|
30 );
|
Chris@0
|
31 }
|
Chris@0
|
32
|
Chris@0
|
33 $this->threshold = $threshold;
|
Chris@0
|
34 }
|
Chris@0
|
35
|
Chris@0
|
36 /**
|
Chris@0
|
37 * @param PHP_CodeCoverage $coverage
|
Chris@0
|
38 * @param string $target
|
Chris@0
|
39 * @param string $name
|
Chris@0
|
40 * @return string
|
Chris@0
|
41 */
|
Chris@0
|
42 public function process(PHP_CodeCoverage $coverage, $target = null, $name = null)
|
Chris@0
|
43 {
|
Chris@0
|
44 $document = new DOMDocument('1.0', 'UTF-8');
|
Chris@0
|
45 $document->formatOutput = true;
|
Chris@0
|
46
|
Chris@0
|
47 $root = $document->createElement('crap_result');
|
Chris@0
|
48 $document->appendChild($root);
|
Chris@0
|
49
|
Chris@0
|
50 $project = $document->createElement('project', is_string($name) ? $name : '');
|
Chris@0
|
51 $root->appendChild($project);
|
Chris@0
|
52 $root->appendChild($document->createElement('timestamp', date('Y-m-d H:i:s', (int) $_SERVER['REQUEST_TIME'])));
|
Chris@0
|
53
|
Chris@0
|
54 $stats = $document->createElement('stats');
|
Chris@0
|
55 $methodsNode = $document->createElement('methods');
|
Chris@0
|
56
|
Chris@0
|
57 $report = $coverage->getReport();
|
Chris@0
|
58 unset($coverage);
|
Chris@0
|
59
|
Chris@0
|
60 $fullMethodCount = 0;
|
Chris@0
|
61 $fullCrapMethodCount = 0;
|
Chris@0
|
62 $fullCrapLoad = 0;
|
Chris@0
|
63 $fullCrap = 0;
|
Chris@0
|
64
|
Chris@0
|
65 foreach ($report as $item) {
|
Chris@0
|
66 $namespace = 'global';
|
Chris@0
|
67
|
Chris@0
|
68 if (!$item instanceof PHP_CodeCoverage_Report_Node_File) {
|
Chris@0
|
69 continue;
|
Chris@0
|
70 }
|
Chris@0
|
71
|
Chris@0
|
72 $file = $document->createElement('file');
|
Chris@0
|
73 $file->setAttribute('name', $item->getPath());
|
Chris@0
|
74
|
Chris@0
|
75 $classes = $item->getClassesAndTraits();
|
Chris@0
|
76
|
Chris@0
|
77 foreach ($classes as $className => $class) {
|
Chris@0
|
78 foreach ($class['methods'] as $methodName => $method) {
|
Chris@0
|
79 $crapLoad = $this->getCrapLoad($method['crap'], $method['ccn'], $method['coverage']);
|
Chris@0
|
80
|
Chris@0
|
81 $fullCrap += $method['crap'];
|
Chris@0
|
82 $fullCrapLoad += $crapLoad;
|
Chris@0
|
83 $fullMethodCount++;
|
Chris@0
|
84
|
Chris@0
|
85 if ($method['crap'] >= $this->threshold) {
|
Chris@0
|
86 $fullCrapMethodCount++;
|
Chris@0
|
87 }
|
Chris@0
|
88
|
Chris@0
|
89 $methodNode = $document->createElement('method');
|
Chris@0
|
90
|
Chris@0
|
91 if (!empty($class['package']['namespace'])) {
|
Chris@0
|
92 $namespace = $class['package']['namespace'];
|
Chris@0
|
93 }
|
Chris@0
|
94
|
Chris@0
|
95 $methodNode->appendChild($document->createElement('package', $namespace));
|
Chris@0
|
96 $methodNode->appendChild($document->createElement('className', $className));
|
Chris@0
|
97 $methodNode->appendChild($document->createElement('methodName', $methodName));
|
Chris@0
|
98 $methodNode->appendChild($document->createElement('methodSignature', htmlspecialchars($method['signature'])));
|
Chris@0
|
99 $methodNode->appendChild($document->createElement('fullMethod', htmlspecialchars($method['signature'])));
|
Chris@0
|
100 $methodNode->appendChild($document->createElement('crap', $this->roundValue($method['crap'])));
|
Chris@0
|
101 $methodNode->appendChild($document->createElement('complexity', $method['ccn']));
|
Chris@0
|
102 $methodNode->appendChild($document->createElement('coverage', $this->roundValue($method['coverage'])));
|
Chris@0
|
103 $methodNode->appendChild($document->createElement('crapLoad', round($crapLoad)));
|
Chris@0
|
104
|
Chris@0
|
105 $methodsNode->appendChild($methodNode);
|
Chris@0
|
106 }
|
Chris@0
|
107 }
|
Chris@0
|
108 }
|
Chris@0
|
109
|
Chris@0
|
110 $stats->appendChild($document->createElement('name', 'Method Crap Stats'));
|
Chris@0
|
111 $stats->appendChild($document->createElement('methodCount', $fullMethodCount));
|
Chris@0
|
112 $stats->appendChild($document->createElement('crapMethodCount', $fullCrapMethodCount));
|
Chris@0
|
113 $stats->appendChild($document->createElement('crapLoad', round($fullCrapLoad)));
|
Chris@0
|
114 $stats->appendChild($document->createElement('totalCrap', $fullCrap));
|
Chris@0
|
115
|
Chris@0
|
116 if ($fullMethodCount > 0) {
|
Chris@0
|
117 $crapMethodPercent = $this->roundValue((100 * $fullCrapMethodCount) / $fullMethodCount);
|
Chris@0
|
118 } else {
|
Chris@0
|
119 $crapMethodPercent = 0;
|
Chris@0
|
120 }
|
Chris@0
|
121
|
Chris@0
|
122 $stats->appendChild($document->createElement('crapMethodPercent', $crapMethodPercent));
|
Chris@0
|
123
|
Chris@0
|
124 $root->appendChild($stats);
|
Chris@0
|
125 $root->appendChild($methodsNode);
|
Chris@0
|
126
|
Chris@0
|
127 if ($target !== null) {
|
Chris@0
|
128 if (!is_dir(dirname($target))) {
|
Chris@0
|
129 mkdir(dirname($target), 0777, true);
|
Chris@0
|
130 }
|
Chris@0
|
131
|
Chris@0
|
132 return $document->save($target);
|
Chris@0
|
133 } else {
|
Chris@0
|
134 return $document->saveXML();
|
Chris@0
|
135 }
|
Chris@0
|
136 }
|
Chris@0
|
137
|
Chris@0
|
138 /**
|
Chris@0
|
139 * @param float $crapValue
|
Chris@0
|
140 * @param int $cyclomaticComplexity
|
Chris@0
|
141 * @param float $coveragePercent
|
Chris@0
|
142 * @return float
|
Chris@0
|
143 */
|
Chris@0
|
144 private function getCrapLoad($crapValue, $cyclomaticComplexity, $coveragePercent)
|
Chris@0
|
145 {
|
Chris@0
|
146 $crapLoad = 0;
|
Chris@0
|
147
|
Chris@0
|
148 if ($crapValue >= $this->threshold) {
|
Chris@0
|
149 $crapLoad += $cyclomaticComplexity * (1.0 - $coveragePercent / 100);
|
Chris@0
|
150 $crapLoad += $cyclomaticComplexity / $this->threshold;
|
Chris@0
|
151 }
|
Chris@0
|
152
|
Chris@0
|
153 return $crapLoad;
|
Chris@0
|
154 }
|
Chris@0
|
155
|
Chris@0
|
156 /**
|
Chris@0
|
157 * @param float $value
|
Chris@0
|
158 * @return float
|
Chris@0
|
159 */
|
Chris@0
|
160 private function roundValue($value)
|
Chris@0
|
161 {
|
Chris@0
|
162 return round($value, 2);
|
Chris@0
|
163 }
|
Chris@0
|
164 }
|