Skip to content

This release includes 4 breaking changes for platform teams planning a safe upgrade.

Published 1mo MCP Developer Tools
✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

architecture ast code-analysis code-metrics code-quality complexity
+10 more
developer-tools maintainability mcp prometheus php php-static-analysis quality-assurance sarif static-analysis technical-debt

Summary

AI summary

MetricsController decomposed into MetricsRegistry/MetricsReader/MetricsWriter with new factory and PHAR release

Full changelog

Changed

  • MetricsController split into MetricsRegistry / MetricsReader / MetricsWriter. The monolithic MetricsController is now decomposed into three focused classes backed by narrow interfaces (MetricsRegistryInterface, MetricsReaderInterface, MetricsWriterInterface). Every Calculator, Prediction, Visitor, DataProvider, and CLI-output class typehints the interface it actually needs — Calculators and Predictions declare reader / writer / registry separately, Visitors take writer + registry (plus reader when they read), and DataProviders take reader + registry. The AnalysisPipeline now returns the trio directly from runAnalysis() / runQuickAnalysis() instead of a controller. PredictionInterface::predict() loses its parameter; predictions receive the trio via constructor injection, analogous to Calculators. Closes #13.
  • New ServiceFactory::createMetricsTriple() is the only supported way to build the three objects so they share one MetricsContainer (invariant: registry, reader, and writer observe the same state).

Removed

  • CalculatorTrait — replaced by MetricsReaderWriterTrait (constructor property promotion for reader/writer/registry). Calculators with additional dependencies keep a custom constructor.
  • MaintainabilityIndexVisitor — unused dead code (never registered in Analyzer::getVisitorClassList()), removed together with its test file.

Deprecated

  • MetricsController — retained as a thin facade implementing all three narrow interfaces, so tests can still instantiate a single object. No production code path uses it anymore; it will be removed once the test suite migrates to the trio directly.

Added

  • PHAR release as a new installation option. A standalone phpcodearcheology.phar is now built automatically on every v*.*.* tag via GitHub Actions and attached to the corresponding GitHub Release as a draft, together with a phpcodearcheology.phar.sha256 checksum. The PHAR ships all runtime dependencies bundled, so it runs on legacy codebases where direct composer require conflicts with the tool's own dependencies (e.g. nikic/php-parser version collisions). Local builds are available via composer build-phar (uses Box 4.7.0, pinned SHA-256). Closes #18.

Changed

  • Metric definition discovery uses scandir() instead of glob() in HtmlReport::generateGlossaryPage(). glob() is unreliable inside phar:// streams across PHP versions; scandir() is not. Behavior is identical for regular installations.

Added

  • Source code display in HTML report. Method and function detail pages can now show the actual source code with PHP syntax highlighting (highlight.js). A nesting-depth heatmap highlights deeply nested lines progressively (depth 2: subtle yellow, depth 3: stronger yellow, depth 4+: red), making complexity drivers immediately visible. Problem badges above the code block and a colored left border (red/yellow/blue by severity) connect metrics to the code. Opt-in via --source-code CLI flag or sourceCode: { enable: true, display: "all"|"problems-only" } in config. Default display mode is problems-only (only methods/functions with detected problems). The highlight.js assets are only included in the report when the feature is enabled.
  • startLine / endLine metrics for methods, functions, and classes. Stored during AST analysis, also fixes the SARIF report which previously defaulted all line numbers to 1.
  • DocBlock summary display in HTML report detail views. Class and method/function detail pages now show the PHPDoc summary text (description before @-tags) below the title. Works for all visibility levels including private methods and __construct. Empty or missing docblocks are handled gracefully (no empty boxes). Closes #16.
  • Test coverage for TooComplexPrediction. 42 dedicated unit tests covering all code paths: CC thresholds (small/large code), Difficulty (trivial exit, framework adjustment), Effort and MI (relative-to-average, typed code tolerance, framework tolerance), LCOM (relative-to-average, floor behavior), the full shouldSkipLcom exclusion matrix, per-method cognitive complexity, classTooComplex flag, File/Function collection handling, and configurable thresholds. All expected values hand-calculated.

Fixed

  • Docker build broken by PHP version mismatch. The Dockerfile ran composer update in the composer:2 stage (now PHP 8.4), which resolved symfony/yaml to v8.0.8 (requires PHP 8.4). The resulting vendor/ was then copied into the php:8.2-cli-alpine runtime, where platform_check.php aborted with a fatal error. Fixed by pinning config.platform.php to 8.2.0 in composer.json (so lockfile resolution stays on the minimum supported PHP regardless of the host PHP version), regenerating composer.lock, and switching the Dockerfile to composer install with the committed lock. Builds are now deterministic. Closes #20.
  • Search input and filter dropdown invisible in dark mode. The search fields and problem-level dropdown in all table views (classes, methods, functions, files, git, tests, refactoring roadmap) used text-black without an explicit background, making them unreadable on dark backgrounds. Replaced with themed .search-input styling that works in both dark and light mode. Filter bar elements now have proper spacing.
  • Markdown report: empty class column in refactoring roadmap and AI summary. The fullName metric was never populated for class collections, so refactoring-roadmap.md showed empty cells in the Class column and ai-summary.md rendered classes as ****. IdentifyVisitor now sets fullName centrally, which also improves the HTML report (namespace prefix now rendered correctly in the roadmap) and the MCP tools. Closes #19.
  • Markdown report: broken footer navigation. The footer nav on every page had three problem-category links (File problems, Class problems, Function problems) all pointing to files.md, plus a duplicated **Packages** heading where **Problems** was intended. Links now resolve to their respective *-problems.md pages and the section heading is correct. Closes #19.
  • Markdown report: problems.md linked to .html files. The problem category links in problems.md were hardcoded to .html, breaking navigation in the Markdown report. All Markdown templates now consistently link to .md targets. Closes #19.
  • Security-smell false positive on SQL concat with class constants only. The SQL string concatenation detector flagged 'INSERT INTO ' . SomeClass::TABLE . ' …' even though the dynamic part is a compile-time constant and cannot carry attacker-controlled data. The detector now ignores concat expressions whose non-literal operands are exclusively class constants, enum cases, global constants, or magic constants. Common Doctrine subscriber / repository patterns no longer produce noise. Closes #19.
  • PHP Warning: Undefined array key 1 in HistoryService when an older history entry stored a plain numeric value for a metric that now carries the 'label: value' prefix. explode(': ', …)[1] was accessed unconditionally; it now falls back to [0] when no colon is present — same effective delta, no warning.
  • Trend chart missing on the second run after a fresh history. A regression introduced when the ReportOrchestrator was extracted from Application.php inverted the order of writeHistory() and report generation: the current run was only appended AFTER reports were rendered, so the HistoryDataProvider never saw it. The chart only surfaced on the third run. writeHistory() now runs before reports again, matching the original v2.7.1 fix.

Breaking Changes

  • Removal of `CalculatorTrait`; replaced by `MetricsReaderWriterTrait` with constructor property promotion.
  • Removal of unused `MaintainabilityIndexVisitor` and its test file.
  • Decomposition of monolithic `MetricsController` into three focused classes (`MetricsRegistry`, `MetricsReader`, `MetricsWriter`) backed by narrow interfaces; all Calculator, Prediction, Visitor, DataProvider, and CLI-output code now typehints the specific interface it needs.
  • Change to `PredictionInterface::predict()` – parameter removed; predictions receive the trio via constructor injection.

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track PhpCodeArcheology/PhpCodeArcheology

Get notified when new releases ship.

Sign up free

About PhpCodeArcheology/PhpCodeArcheology

PHP static analysis MCP server for architecture and maintainability. 11 tools exposing 60+ code quality metrics, problem detection, refactoring priorities, dependency graphs, git hotspots, test coverage, and impact analysis. Installable via Composer.

All releases →

Beta — feedback welcome: [email protected]