1+ <?php
2+
3+ /**
4+ * PHP_CodeCoverage_Report_Crap4j
5+ */
6+ class PHP_CodeCoverage_Report_Crap4j
7+ {
8+ private $ threshold = 30 ;
9+
10+ /**
11+ * @param PHP_CodeCoverage $coverage
12+ * @param string $target
13+ * @param string $name
14+ * @return string
15+ */
16+ public function process (PHP_CodeCoverage $ coverage , $ target = NULL , $ name = NULL )
17+ {
18+ $ document = new DOMDocument ('1.0 ' , 'UTF-8 ' );
19+ $ document ->formatOutput = TRUE ;
20+
21+ $ root = $ document ->createElement ('crap_result ' );
22+ $ document ->appendChild ($ root );
23+
24+ $ project = $ document ->createElement ('project ' , is_string ($ name ) ? $ name : '' );
25+ $ root ->appendChild ($ project );
26+ $ root ->appendChild ($ document ->createElement ('timestamp ' , date ('Y-m-d H:i:s ' , (int )$ _SERVER ['REQUEST_TIME ' ])));
27+
28+ $ stats = $ document ->createElement ('stats ' );
29+ $ methodsNode = $ document ->createElement ('methods ' );
30+
31+ $ report = $ coverage ->getReport ();
32+ unset($ coverage );
33+
34+ $ fullMethodCount = 0 ;
35+ $ fullCrapMethodCount = 0 ;
36+ $ fullCrapLoad = 0 ;
37+ $ fullCrap = 0 ;
38+
39+ foreach ($ report as $ item ) {
40+ if (!$ item instanceof PHP_CodeCoverage_Report_Node_File) {
41+ continue ;
42+ }
43+
44+ $ file = $ document ->createElement ('file ' );
45+ $ file ->setAttribute ('name ' , $ item ->getPath ());
46+
47+ $ classes = $ item ->getClassesAndTraits ();
48+
49+ foreach ($ classes as $ className => $ class ) {
50+ foreach ($ class ['methods ' ] as $ methodName => $ method ) {
51+ $ crapLoad = $ this ->getCrapLoad ($ method ['crap ' ], $ method ['ccn ' ], $ method ['coverage ' ]);
52+
53+ $ fullCrap += $ method ['crap ' ];
54+ $ fullCrapLoad += $ crapLoad ;
55+ $ fullMethodCount ++;
56+
57+ if ($ method ['crap ' ] >= $ this ->threshold ) {
58+ $ fullCrapMethodCount ++;
59+ }
60+
61+ $ methodNode = $ document ->createElement ('method ' );
62+
63+ $ methodNode ->appendChild ($ document ->createElement ('package ' , '' ));
64+ $ methodNode ->appendChild ($ document ->createElement ('className ' , $ className ));
65+ $ methodNode ->appendChild ($ document ->createElement ('methodName ' , $ methodName ));
66+ $ methodNode ->appendChild ($ document ->createElement ('methodSignature ' , htmlspecialchars ($ method ['signature ' ])));
67+ $ methodNode ->appendChild ($ document ->createElement ('fullMethod ' , htmlspecialchars ($ method ['signature ' ])));
68+ $ methodNode ->appendChild ($ document ->createElement ('crap ' , $ this ->roundValue ($ method ['crap ' ])));
69+ $ methodNode ->appendChild ($ document ->createElement ('complexity ' , $ method ['ccn ' ]));
70+ $ methodNode ->appendChild ($ document ->createElement ('coverage ' , $ this ->roundValue ($ method ['coverage ' ])));
71+ $ methodNode ->appendChild ($ document ->createElement ('crapLoad ' , round ($ crapLoad )));
72+
73+ $ methodsNode ->appendChild ($ methodNode );
74+ }
75+ }
76+ }
77+
78+ $ stats ->appendChild ($ document ->createElement ('name ' , 'Method Crap Stats ' ));
79+ $ stats ->appendChild ($ document ->createElement ('methodCount ' , $ fullMethodCount ));
80+ $ stats ->appendChild ($ document ->createElement ('crapMethodCount ' , $ fullCrapMethodCount ));
81+ $ stats ->appendChild ($ document ->createElement ('crapLoad ' , round ($ fullCrapLoad )));
82+ $ stats ->appendChild ($ document ->createElement ('totalCrap ' , $ fullCrap ));
83+ $ stats ->appendChild ($ document ->createElement ('crapMethodPercent ' , $ this ->roundValue (100 * $ fullCrapMethodCount / $ fullMethodCount )));
84+
85+ $ root ->appendChild ($ stats );
86+ $ root ->appendChild ($ methodsNode );
87+
88+ if ($ target !== NULL ) {
89+ if (!is_dir (dirname ($ target ))) {
90+ mkdir (dirname ($ target ), 0777 , TRUE );
91+ }
92+
93+ return $ document ->save ($ target );
94+ } else {
95+ return $ document ->saveXML ();
96+ }
97+ }
98+
99+ private function getCrapLoad ($ crapValue , $ cyclomaticComplexity , $ coveragePercent )
100+ {
101+ $ crapLoad = 0 ;
102+ if ($ crapValue > $ this ->threshold ) {
103+ $ crapLoad += $ cyclomaticComplexity * (1.0 - $ coveragePercent / 100 );
104+ $ crapLoad += $ cyclomaticComplexity / $ this ->threshold ;
105+ }
106+ return $ crapLoad ;
107+ }
108+
109+ private function roundValue ($ value )
110+ {
111+ return round ($ value , 2 );
112+ }
113+ }
0 commit comments