Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: /** Chris@0: * @since Class available since Release 2.0.0 Chris@0: */ Chris@0: class PHP_CodeCoverage_Report_Crap4j Chris@0: { Chris@0: /** Chris@0: * @var int Chris@0: */ Chris@0: private $threshold; Chris@0: Chris@0: /** Chris@0: * @param int $threshold Chris@0: */ Chris@0: public function __construct($threshold = 30) Chris@0: { Chris@0: if (!is_int($threshold)) { Chris@0: throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( Chris@0: 1, Chris@0: 'integer' Chris@0: ); Chris@0: } Chris@0: Chris@0: $this->threshold = $threshold; Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param PHP_CodeCoverage $coverage Chris@0: * @param string $target Chris@0: * @param string $name Chris@0: * @return string Chris@0: */ Chris@0: public function process(PHP_CodeCoverage $coverage, $target = null, $name = null) Chris@0: { Chris@0: $document = new DOMDocument('1.0', 'UTF-8'); Chris@0: $document->formatOutput = true; Chris@0: Chris@0: $root = $document->createElement('crap_result'); Chris@0: $document->appendChild($root); Chris@0: Chris@0: $project = $document->createElement('project', is_string($name) ? $name : ''); Chris@0: $root->appendChild($project); Chris@0: $root->appendChild($document->createElement('timestamp', date('Y-m-d H:i:s', (int) $_SERVER['REQUEST_TIME']))); Chris@0: Chris@0: $stats = $document->createElement('stats'); Chris@0: $methodsNode = $document->createElement('methods'); Chris@0: Chris@0: $report = $coverage->getReport(); Chris@0: unset($coverage); Chris@0: Chris@0: $fullMethodCount = 0; Chris@0: $fullCrapMethodCount = 0; Chris@0: $fullCrapLoad = 0; Chris@0: $fullCrap = 0; Chris@0: Chris@0: foreach ($report as $item) { Chris@0: $namespace = 'global'; Chris@0: Chris@0: if (!$item instanceof PHP_CodeCoverage_Report_Node_File) { Chris@0: continue; Chris@0: } Chris@0: Chris@0: $file = $document->createElement('file'); Chris@0: $file->setAttribute('name', $item->getPath()); Chris@0: Chris@0: $classes = $item->getClassesAndTraits(); Chris@0: Chris@0: foreach ($classes as $className => $class) { Chris@0: foreach ($class['methods'] as $methodName => $method) { Chris@0: $crapLoad = $this->getCrapLoad($method['crap'], $method['ccn'], $method['coverage']); Chris@0: Chris@0: $fullCrap += $method['crap']; Chris@0: $fullCrapLoad += $crapLoad; Chris@0: $fullMethodCount++; Chris@0: Chris@0: if ($method['crap'] >= $this->threshold) { Chris@0: $fullCrapMethodCount++; Chris@0: } Chris@0: Chris@0: $methodNode = $document->createElement('method'); Chris@0: Chris@0: if (!empty($class['package']['namespace'])) { Chris@0: $namespace = $class['package']['namespace']; Chris@0: } Chris@0: Chris@0: $methodNode->appendChild($document->createElement('package', $namespace)); Chris@0: $methodNode->appendChild($document->createElement('className', $className)); Chris@0: $methodNode->appendChild($document->createElement('methodName', $methodName)); Chris@0: $methodNode->appendChild($document->createElement('methodSignature', htmlspecialchars($method['signature']))); Chris@0: $methodNode->appendChild($document->createElement('fullMethod', htmlspecialchars($method['signature']))); Chris@0: $methodNode->appendChild($document->createElement('crap', $this->roundValue($method['crap']))); Chris@0: $methodNode->appendChild($document->createElement('complexity', $method['ccn'])); Chris@0: $methodNode->appendChild($document->createElement('coverage', $this->roundValue($method['coverage']))); Chris@0: $methodNode->appendChild($document->createElement('crapLoad', round($crapLoad))); Chris@0: Chris@0: $methodsNode->appendChild($methodNode); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: $stats->appendChild($document->createElement('name', 'Method Crap Stats')); Chris@0: $stats->appendChild($document->createElement('methodCount', $fullMethodCount)); Chris@0: $stats->appendChild($document->createElement('crapMethodCount', $fullCrapMethodCount)); Chris@0: $stats->appendChild($document->createElement('crapLoad', round($fullCrapLoad))); Chris@0: $stats->appendChild($document->createElement('totalCrap', $fullCrap)); Chris@0: Chris@0: if ($fullMethodCount > 0) { Chris@0: $crapMethodPercent = $this->roundValue((100 * $fullCrapMethodCount) / $fullMethodCount); Chris@0: } else { Chris@0: $crapMethodPercent = 0; Chris@0: } Chris@0: Chris@0: $stats->appendChild($document->createElement('crapMethodPercent', $crapMethodPercent)); Chris@0: Chris@0: $root->appendChild($stats); Chris@0: $root->appendChild($methodsNode); Chris@0: Chris@0: if ($target !== null) { Chris@0: if (!is_dir(dirname($target))) { Chris@0: mkdir(dirname($target), 0777, true); Chris@0: } Chris@0: Chris@0: return $document->save($target); Chris@0: } else { Chris@0: return $document->saveXML(); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param float $crapValue Chris@0: * @param int $cyclomaticComplexity Chris@0: * @param float $coveragePercent Chris@0: * @return float Chris@0: */ Chris@0: private function getCrapLoad($crapValue, $cyclomaticComplexity, $coveragePercent) Chris@0: { Chris@0: $crapLoad = 0; Chris@0: Chris@0: if ($crapValue >= $this->threshold) { Chris@0: $crapLoad += $cyclomaticComplexity * (1.0 - $coveragePercent / 100); Chris@0: $crapLoad += $cyclomaticComplexity / $this->threshold; Chris@0: } Chris@0: Chris@0: return $crapLoad; Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param float $value Chris@0: * @return float Chris@0: */ Chris@0: private function roundValue($value) Chris@0: { Chris@0: return round($value, 2); Chris@0: } Chris@0: }