Framework Adapters
Codemetry’s core is framework-agnostic. Official adapters exist for Laravel (Artisan) and WordPress (WP-CLI). You can create adapters for other frameworks or use the core directly.
Architecture Overview
┌───────────────────────────────────────────────────────────────┐│ Your Application │├───────────────────────────────────────────────────────────────┤│ Laravel Adapter │ WordPress Adapter │ Symfony Bundle │...│├───────────────────────────────────────────────────────────────┤│ Codemetry Core ││ (Analyzer, Providers, Scorer, etc.) │└───────────────────────────────────────────────────────────────┘Official Adapters
Laravel Adapter
The Laravel adapter (codemetry/laravel) provides:
- Artisan command:
php artisan codemetry:analyze - Laravel-style configuration via
config/codemetry.php - Environment variable support via
.env - Auto-discovery via Laravel’s package system
WordPress Adapter
The WordPress adapter (codemetry/wordpress) provides:
- WP-CLI command:
wp codemetry analyze - Configuration via
wp-cli.yml - Additional command:
wp codemetry config(view active configuration)
Package structure:
packages/wordpress/├── composer.json├── src/│ └── Command/│ └── CodemetryCommand.php└── wp-cli.yml.exampleHow WP-CLI auto-discovery works:
WP-CLI automatically discovers commands from Composer packages that include a wp-cli.yml file at the package root. The WordPress adapter registers itself like this:
<?phpnamespace Codemetry\WordPress\Command;
use Codemetry\Core\Analyzer;use Codemetry\Core\Domain\AnalysisRequest;use WP_CLI;
class CodemetryCommand{ /** * Analyze Git repository for code quality metrics. * * ## OPTIONS * * [--days=<days>] * : Number of days to analyze. * --- * default: 7 * --- * * [--format=<format>] * : Output format (table or json). * --- * default: table * options: * - table * - json * --- * * ## EXAMPLES * * wp codemetry analyze --days=7 * wp codemetry analyze --format=json --ai=1 * * @when before_wp_load */ public function analyze($args, $assocArgs): void { $config = $this->loadConfig(); $analyzer = new Analyzer($config);
$request = $this->buildRequest($assocArgs); $result = $analyzer->analyze(getcwd(), $request);
$this->renderOutput($result, $assocArgs['format'] ?? 'table'); }}The package’s composer.json includes the WP-CLI autoload hook:
{ "extra": { "commands": [ "Codemetry\\WordPress\\Command\\CodemetryCommand" ] }}Using Core Directly
For non-Laravel projects, use the core package directly:
composer require codemetry/coreBasic Usage
<?php
use Codemetry\Core\Analyzer;use Codemetry\Core\Domain\AnalysisRequest;use DateTimeImmutable;
// Create analyzer with default configuration$analyzer = new Analyzer();
// Build request$request = new AnalysisRequest( since: new DateTimeImmutable('-7 days'), until: new DateTimeImmutable('now'), author: null, branch: null, timezone: new DateTimeZone('UTC'), baselineDays: 56, followUpHorizonDays: 3, aiEnabled: false, aiEngine: 'openai', outputFormat: 'json');
// Run analysis$result = $analyzer->analyze('/path/to/repo', $request);
// Access resultsforeach ($result->windows() as $window) { echo $window->windowLabel() . ': ' . $window->moodLabel() . "\n";}
// Get JSON output$json = $result->toJson();Configuration
Without a framework, pass configuration directly:
use Codemetry\Core\Analyzer;use Codemetry\Core\Config\Config;
$config = new Config( baselineDays: 56, followUpHorizonDays: 3, keywords: [ 'fix_pattern' => '/\b(fix|bug|hotfix)\b/i', 'revert_pattern' => '/\b(revert)\b/i', 'wip_pattern' => '/\b(wip|tmp)\b/i', ], aiEnabled: false, aiEngine: 'openai', aiModel: null, aiApiKey: null,);
$analyzer = new Analyzer($config);Creating a Symfony Adapter
Example structure for a Symfony bundle:
src/ CodemetryBundle.php DependencyInjection/ CodemetryExtension.php Configuration.php Command/ AnalyzeCommand.php Resources/ config/ services.yamlService Registration
services: Codemetry\Core\Analyzer: arguments: $config: '@codemetry.config'
codemetry.config: class: Codemetry\Core\Config\Config factory: ['@App\Factory\CodemetryConfigFactory', 'create']
App\Command\CodemetryAnalyzeCommand: arguments: $analyzer: '@Codemetry\Core\Analyzer' tags: - { name: console.command }Console Command
<?php
namespace App\Command;
use Codemetry\Core\Analyzer;use Codemetry\Core\Domain\AnalysisRequest;use Symfony\Component\Console\Attribute\AsCommand;use Symfony\Component\Console\Command\Command;use Symfony\Component\Console\Input\InputInterface;use Symfony\Component\Console\Input\InputOption;use Symfony\Component\Console\Output\OutputInterface;use DateTimeImmutable;
#[AsCommand(name: 'codemetry:analyze')]class CodemetryAnalyzeCommand extends Command{ public function __construct( private Analyzer $analyzer ) { parent::__construct(); }
protected function configure(): void { $this ->addOption('days', 'd', InputOption::VALUE_REQUIRED, 'Days to analyze', 7) ->addOption('format', 'f', InputOption::VALUE_REQUIRED, 'Output format', 'table') ->addOption('ai', null, InputOption::VALUE_REQUIRED, 'Enable AI', 0); }
protected function execute(InputInterface $input, OutputInterface $output): int { $days = (int) $input->getOption('days'); $format = $input->getOption('format'); $aiEnabled = (bool) $input->getOption('ai');
$request = new AnalysisRequest( since: new DateTimeImmutable("-{$days} days"), until: new DateTimeImmutable('now'), aiEnabled: $aiEnabled, outputFormat: $format, // ... other options );
$result = $this->analyzer->analyze(getcwd(), $request);
if ($format === 'json') { $output->writeln($result->toJson()); } else { $this->renderTable($output, $result); }
return Command::SUCCESS; }}Creating Other Adapters
Key responsibilities of an adapter:
1. Configuration Binding
Map framework config to Codemetry’s Config object:
// Read from framework config$frameworkConfig = $this->getConfig('codemetry');
// Create Codemetry config$config = new Config( baselineDays: $frameworkConfig['baseline_days'] ?? 56, // ...);2. Command/CLI Integration
Provide framework-native CLI commands:
- Parse arguments and options
- Build
AnalysisRequest - Format output appropriately
3. Service Registration
Register Codemetry services with the framework’s container:
Analyzeras singleton- Custom providers
- AI engines if needed
4. Output Formatting
Adapt output to framework conventions:
- Table rendering
- JSON responses
- Progress indicators
Adapter Best Practices
Keep It Thin
The adapter should only:
- Map configuration
- Provide CLI interface
- Register services
Business logic stays in core.
Respect Framework Conventions
- Use native configuration systems
- Follow framework’s CLI patterns
- Integrate with framework’s logging
Handle Dependencies
Don’t require core dependencies in the adapter:
// Good: Adapter requires only what it needs{ "require": { "codemetry/core": "^1.0", "symfony/console": "^6.0|^7.0" }}Test Independently
Test adapter functionality separately from core:
- Configuration parsing
- Command argument handling
- Output formatting
Contributing Adapters
If you build an adapter for a popular framework:
- Consider contributing it to the Codemetry organization
- Follow the existing Laravel adapter as a pattern
- Include comprehensive tests
- Document framework-specific features
Community adapters help make Codemetry accessible to more developers.