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: * Generates a Clover XML logfile from an PHP_CodeCoverage object. Chris@0: * Chris@0: * @since Class available since Release 1.0.0 Chris@0: */ Chris@0: class PHP_CodeCoverage_Report_Clover 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: $xmlDocument = new DOMDocument('1.0', 'UTF-8'); Chris@0: $xmlDocument->formatOutput = true; Chris@0: Chris@0: $xmlCoverage = $xmlDocument->createElement('coverage'); Chris@0: $xmlCoverage->setAttribute('generated', (int) $_SERVER['REQUEST_TIME']); Chris@0: $xmlDocument->appendChild($xmlCoverage); Chris@0: Chris@0: $xmlProject = $xmlDocument->createElement('project'); Chris@0: $xmlProject->setAttribute('timestamp', (int) $_SERVER['REQUEST_TIME']); Chris@0: Chris@0: if (is_string($name)) { Chris@0: $xmlProject->setAttribute('name', $name); Chris@0: } Chris@0: Chris@0: $xmlCoverage->appendChild($xmlProject); Chris@0: Chris@0: $packages = array(); Chris@0: $report = $coverage->getReport(); Chris@0: unset($coverage); 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: $xmlFile = $xmlDocument->createElement('file'); Chris@0: $xmlFile->setAttribute('name', $item->getPath()); Chris@0: Chris@0: $classes = $item->getClassesAndTraits(); Chris@0: $coverage = $item->getCoverageData(); Chris@0: $lines = array(); Chris@0: Chris@0: foreach ($classes as $className => $class) { Chris@0: $classStatements = 0; Chris@0: $coveredClassStatements = 0; Chris@0: $coveredMethods = 0; Chris@0: $classMethods = 0; Chris@0: Chris@0: foreach ($class['methods'] as $methodName => $method) { Chris@0: if ($method['executableLines'] == 0) { Chris@0: continue; Chris@0: } Chris@0: Chris@0: $classMethods++; Chris@0: $classStatements += $method['executableLines']; Chris@0: $coveredClassStatements += $method['executedLines']; Chris@0: if ($method['coverage'] == 100) { Chris@0: $coveredMethods++; Chris@0: } Chris@0: Chris@0: $methodCount = 0; Chris@0: for ($i = $method['startLine']; Chris@0: $i <= $method['endLine']; Chris@0: $i++) { Chris@0: if (isset($coverage[$i]) && ($coverage[$i] !== null)) { Chris@0: $methodCount = max($methodCount, count($coverage[$i])); Chris@0: } Chris@0: } Chris@0: Chris@0: $lines[$method['startLine']] = array( Chris@0: 'count' => $methodCount, Chris@0: 'crap' => $method['crap'], Chris@0: 'type' => 'method', Chris@0: 'name' => $methodName Chris@0: ); Chris@0: } Chris@0: Chris@0: if (!empty($class['package']['namespace'])) { Chris@0: $namespace = $class['package']['namespace']; Chris@0: } Chris@0: Chris@0: $xmlClass = $xmlDocument->createElement('class'); Chris@0: $xmlClass->setAttribute('name', $className); Chris@0: $xmlClass->setAttribute('namespace', $namespace); Chris@0: Chris@0: if (!empty($class['package']['fullPackage'])) { Chris@0: $xmlClass->setAttribute( Chris@0: 'fullPackage', Chris@0: $class['package']['fullPackage'] Chris@0: ); Chris@0: } Chris@0: Chris@0: if (!empty($class['package']['category'])) { Chris@0: $xmlClass->setAttribute( Chris@0: 'category', Chris@0: $class['package']['category'] Chris@0: ); Chris@0: } Chris@0: Chris@0: if (!empty($class['package']['package'])) { Chris@0: $xmlClass->setAttribute( Chris@0: 'package', Chris@0: $class['package']['package'] Chris@0: ); Chris@0: } Chris@0: Chris@0: if (!empty($class['package']['subpackage'])) { Chris@0: $xmlClass->setAttribute( Chris@0: 'subpackage', Chris@0: $class['package']['subpackage'] Chris@0: ); Chris@0: } Chris@0: Chris@0: $xmlFile->appendChild($xmlClass); Chris@0: Chris@0: $xmlMetrics = $xmlDocument->createElement('metrics'); Chris@0: $xmlMetrics->setAttribute('methods', $classMethods); Chris@0: $xmlMetrics->setAttribute('coveredmethods', $coveredMethods); Chris@0: $xmlMetrics->setAttribute('conditionals', 0); Chris@0: $xmlMetrics->setAttribute('coveredconditionals', 0); Chris@0: $xmlMetrics->setAttribute('statements', $classStatements); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'coveredstatements', Chris@0: $coveredClassStatements Chris@0: ); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'elements', Chris@0: $classMethods + Chris@0: $classStatements Chris@0: /* + conditionals */ Chris@0: ); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'coveredelements', Chris@0: $coveredMethods + Chris@0: $coveredClassStatements Chris@0: /* + coveredconditionals */ Chris@0: ); Chris@0: $xmlClass->appendChild($xmlMetrics); Chris@0: } Chris@0: Chris@0: foreach ($coverage as $line => $data) { Chris@0: if ($data === null || isset($lines[$line])) { Chris@0: continue; Chris@0: } Chris@0: Chris@0: $lines[$line] = array( Chris@0: 'count' => count($data), 'type' => 'stmt' Chris@0: ); Chris@0: } Chris@0: Chris@0: ksort($lines); Chris@0: Chris@0: foreach ($lines as $line => $data) { Chris@0: $xmlLine = $xmlDocument->createElement('line'); Chris@0: $xmlLine->setAttribute('num', $line); Chris@0: $xmlLine->setAttribute('type', $data['type']); Chris@0: Chris@0: if (isset($data['name'])) { Chris@0: $xmlLine->setAttribute('name', $data['name']); Chris@0: } Chris@0: Chris@0: if (isset($data['crap'])) { Chris@0: $xmlLine->setAttribute('crap', $data['crap']); Chris@0: } Chris@0: Chris@0: $xmlLine->setAttribute('count', $data['count']); Chris@0: $xmlFile->appendChild($xmlLine); Chris@0: } Chris@0: Chris@0: $linesOfCode = $item->getLinesOfCode(); Chris@0: Chris@0: $xmlMetrics = $xmlDocument->createElement('metrics'); Chris@0: $xmlMetrics->setAttribute('loc', $linesOfCode['loc']); Chris@0: $xmlMetrics->setAttribute('ncloc', $linesOfCode['ncloc']); Chris@0: $xmlMetrics->setAttribute('classes', $item->getNumClassesAndTraits()); Chris@0: $xmlMetrics->setAttribute('methods', $item->getNumMethods()); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'coveredmethods', Chris@0: $item->getNumTestedMethods() Chris@0: ); Chris@0: $xmlMetrics->setAttribute('conditionals', 0); Chris@0: $xmlMetrics->setAttribute('coveredconditionals', 0); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'statements', Chris@0: $item->getNumExecutableLines() Chris@0: ); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'coveredstatements', Chris@0: $item->getNumExecutedLines() Chris@0: ); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'elements', Chris@0: $item->getNumMethods() + $item->getNumExecutableLines() Chris@0: /* + conditionals */ Chris@0: ); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'coveredelements', Chris@0: $item->getNumTestedMethods() + $item->getNumExecutedLines() Chris@0: /* + coveredconditionals */ Chris@0: ); Chris@0: $xmlFile->appendChild($xmlMetrics); Chris@0: Chris@0: if ($namespace == 'global') { Chris@0: $xmlProject->appendChild($xmlFile); Chris@0: } else { Chris@0: if (!isset($packages[$namespace])) { Chris@0: $packages[$namespace] = $xmlDocument->createElement( Chris@0: 'package' Chris@0: ); Chris@0: Chris@0: $packages[$namespace]->setAttribute('name', $namespace); Chris@0: $xmlProject->appendChild($packages[$namespace]); Chris@0: } Chris@0: Chris@0: $packages[$namespace]->appendChild($xmlFile); Chris@0: } Chris@0: } Chris@0: Chris@0: $linesOfCode = $report->getLinesOfCode(); Chris@0: Chris@0: $xmlMetrics = $xmlDocument->createElement('metrics'); Chris@0: $xmlMetrics->setAttribute('files', count($report)); Chris@0: $xmlMetrics->setAttribute('loc', $linesOfCode['loc']); Chris@0: $xmlMetrics->setAttribute('ncloc', $linesOfCode['ncloc']); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'classes', Chris@0: $report->getNumClassesAndTraits() Chris@0: ); Chris@0: $xmlMetrics->setAttribute('methods', $report->getNumMethods()); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'coveredmethods', Chris@0: $report->getNumTestedMethods() Chris@0: ); Chris@0: $xmlMetrics->setAttribute('conditionals', 0); Chris@0: $xmlMetrics->setAttribute('coveredconditionals', 0); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'statements', Chris@0: $report->getNumExecutableLines() Chris@0: ); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'coveredstatements', Chris@0: $report->getNumExecutedLines() Chris@0: ); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'elements', Chris@0: $report->getNumMethods() + $report->getNumExecutableLines() Chris@0: /* + conditionals */ Chris@0: ); Chris@0: $xmlMetrics->setAttribute( Chris@0: 'coveredelements', Chris@0: $report->getNumTestedMethods() + $report->getNumExecutedLines() Chris@0: /* + coveredconditionals */ Chris@0: ); Chris@0: Chris@0: $xmlProject->appendChild($xmlMetrics); 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 $xmlDocument->save($target); Chris@0: } else { Chris@0: return $xmlDocument->saveXML(); Chris@0: } Chris@0: } Chris@0: }