This guide explains how to create custom reporters for the Cognitive Code Checker to output metrics in your preferred format.
The Cognitive Code Checker supports two types of reports:
- Cognitive reporter: Export cognitive complexity metrics
- Churn reporter: Export code churn metrics
Both types follow similar patterns but have different interfaces and data structures.
Cognitive reporter handle cognitive complexity metrics data and implement the ReportGeneratorInterface from the Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Report namespace.
Interface:
interface ReportGeneratorInterface
{
public function export(CognitiveMetricsCollection $metrics, string $filename): void;
}Data Structure: CognitiveMetricsCollection contains individual CognitiveMetrics objects with methods like:
getClass()- Class namegetMethod()- Method namegetLineCount()- Number of linesgetScore()- Combined cognitive complexity scoregetLineCountWeight(),getArgCountWeight(), etc. - Individual metric weightsgetLineCountWeightDelta(), etc. - Delta values for comparison
Churn reporter handle code churn metrics data and implement the ReportGeneratorInterface from the Phauthentic\CognitiveCodeAnalysis\Business\Churn\Report namespace.
Interface:
interface ReportGeneratorInterface
{
/**
* @param array<string, array<string, mixed>> $classes
*/
public function export(array $classes, string $filename): void;
}Data Structure: Array with class names as keys and arrays containing:
file- File pathscore- Churn scorechurn- Churn valuetimesChanged- Number of times changedcoverage- Test coverage (optional)riskLevel- Risk level (optional)
Add your custom reporter to the config.yml file under the customReporters section:
cognitive:
# ... other cognitive settings ...
customReporters:
cognitive:
pdf: # Custom reporter name
class: 'My\Custom\PdfReporter'
file: '/path/to/PdfReporter.php'
churn:
churn: # Custom reporter name
class: 'My\Custom\ChurnReporter'
file: '/path/to/ChurnReporter.php'class(required): Fully qualified class name of your reporterfile(optional): Path to the PHP file containing your reporter class. Set tonullif using autoloading
The system automatically detects whether your reporter needs the CognitiveConfig object:
class PdfReporter implements ReportGeneratorInterface
{
private CognitiveConfig $config;
public function __construct(CognitiveConfig $config)
{
$this->config = $config;
}
// ... rest of implementation
}class SimpleReporter implements ReportGeneratorInterface
{
public function __construct()
{
// No config needed
}
// ... rest of implementation
}The system will automatically try to pass the config to your constructor. If your constructor doesn't accept it, the system will fall back to calling the constructor without arguments.
Here's a complete example of a custom PDF reporter for cognitive metrics:
<?php
declare(strict_types=1);
namespace My\Custom;
use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Report\ReportGeneratorInterface;
use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection;
use Phauthentic\CognitiveCodeAnalysis\Config\CognitiveConfig;
use Phauthentic\CognitiveCodeAnalysis\CognitiveAnalysisException;
class PdfReporter implements ReportGeneratorInterface
{
private CognitiveConfig $config;
public function __construct(CognitiveConfig $config)
{
$this->config = $config;
}
public function export(CognitiveMetricsCollection $metrics, string $filename): void
{
// Ensure directory exists
$directory = dirname($filename);
if (!is_dir($directory)) {
throw new CognitiveAnalysisException("Directory {$directory} does not exist");
}
// Create PDF content
$pdfContent = $this->generatePdfContent($metrics);
// Write to file
if (file_put_contents($filename, $pdfContent) === false) {
throw new CognitiveAnalysisException("Could not write to file: {$filename}");
}
}
private function generatePdfContent(CognitiveMetricsCollection $metrics): string
{
$content = "%PDF-1.4\n";
$content .= "1 0 obj\n";
$content .= "<< /Type /Catalog /Pages 2 0 R >>\n";
$content .= "endobj\n";
// Add your PDF generation logic here
$groupedByClass = $metrics->groupBy('class');
foreach ($groupedByClass as $class => $methods) {
$content .= "% Class: {$class}\n";
foreach ($methods as $metric) {
$content .= "Method: {$metric->getMethod()}, Score: {$metric->getScore()}\n";
}
}
return $content;
}
}Here's an example of a custom churn reporter for churn metrics:
<?php
declare(strict_types=1);
namespace My\Custom;
use Phauthentic\CognitiveCodeAnalysis\Business\Churn\Report\ReportGeneratorInterface;
use Phauthentic\CognitiveCodeAnalysis\CognitiveAnalysisException;
class ChurnReporter implements ReportGeneratorInterface
{
public function export(array $classes, string $filename): void
{
// Ensure directory exists
$directory = dirname($filename);
if (!is_dir($directory)) {
throw new CognitiveAnalysisException("Directory {$directory} does not exist");
}
// Generate churn content
$churnContent = $this->generateChurnContent($classes);
// Write to file
if (file_put_contents($filename, $churnContent) === false) {
throw new CognitiveAnalysisException("Could not write to file: {$filename}");
}
}
private function generateChurnContent(array $classes): string
{
$content = "Churn Report\n";
$content .= "============\n\n";
foreach ($classes as $className => $data) {
$content .= "Class: {$className}\n";
$content .= "File: {$data['file']}\n";
$content .= "Score: {$data['score']}\n";
$content .= "Churn: {$data['churn']}\n";
$content .= "Times Changed: {$data['timesChanged']}\n";
$content .= "---\n";
}
return $content;
}
}Once configured, you can use your custom reporter by specifying its name when generating reports:
# For cognitive metrics
php bin/cognitive-report --format=pdf --output=report.pdf
# For churn metrics
php bin/churn-report --format=churn --output=churn.txt- Error Handling: Always throw
CognitiveAnalysisExceptionfor errors - File Validation: Check that directories exist and files are writable
- Data Access: Use the provided methods to access metric data
- Configuration: Use
CognitiveConfigif you need access to settings - Testing: Test your reporter with real data to ensure proper formatting
For inspiration, examine the built-in reporter:
JsonReport- JSON formatCsvReport- CSV formatHtmlReport- HTML with Bootstrap stylingMarkdownReport- Markdown tables
Churn reporter:
JsonReport- JSON formatCsvReport- CSV formatHtmlReport- HTML with Bootstrap stylingMarkdownReport- Markdown tablesSvgTreemapReport- SVG treemap visualization
Common Issues:
- Class not found: Ensure the
classparameter uses the full namespace - File not found: Check the
filepath is correct and accessible - Interface not implemented: Ensure your class implements the correct
ReportGeneratorInterface - Constructor issues: Your reporter can optionally accept
CognitiveConfigin its constructor - the system will automatically detect this
Debug Tips:
- Check the configuration syntax in
config.yml - Verify file paths are absolute or relative to the project root
- Test with simple reporter first before complex implementations
- Use the built-in reporter as templates for your custom ones