This release includes 4 breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
Topics
+10 more
Summary
AI summaryMetricsController decomposed into MetricsRegistry/MetricsReader/MetricsWriter with new factory and PHAR release
Full changelog
Changed
MetricsControllersplit intoMetricsRegistry/MetricsReader/MetricsWriter. The monolithicMetricsControlleris 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 declarereader/writer/registryseparately, Visitors take writer + registry (plus reader when they read), and DataProviders take reader + registry. TheAnalysisPipelinenow returns the trio directly fromrunAnalysis()/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 oneMetricsContainer(invariant: registry, reader, and writer observe the same state).
Removed
CalculatorTrait— replaced byMetricsReaderWriterTrait(constructor property promotion for reader/writer/registry). Calculators with additional dependencies keep a custom constructor.MaintainabilityIndexVisitor— unused dead code (never registered inAnalyzer::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.pharis now built automatically on everyv*.*.*tag via GitHub Actions and attached to the corresponding GitHub Release as a draft, together with aphpcodearcheology.phar.sha256checksum. The PHAR ships all runtime dependencies bundled, so it runs on legacy codebases where directcomposer requireconflicts with the tool's own dependencies (e.g.nikic/php-parserversion collisions). Local builds are available viacomposer build-phar(uses Box 4.7.0, pinned SHA-256). Closes #18.
Changed
- Metric definition discovery uses
scandir()instead ofglob()inHtmlReport::generateGlossaryPage().glob()is unreliable insidephar://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-codeCLI flag orsourceCode: { enable: true, display: "all"|"problems-only" }in config. Default display mode isproblems-only(only methods/functions with detected problems). The highlight.js assets are only included in the report when the feature is enabled. startLine/endLinemetrics 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 fullshouldSkipLcomexclusion matrix, per-method cognitive complexity,classTooComplexflag, File/Function collection handling, and configurable thresholds. All expected values hand-calculated.
Fixed
- Docker build broken by PHP version mismatch. The
Dockerfilerancomposer updatein thecomposer:2stage (now PHP 8.4), which resolvedsymfony/yamlto v8.0.8 (requires PHP 8.4). The resultingvendor/was then copied into thephp:8.2-cli-alpineruntime, whereplatform_check.phpaborted with a fatal error. Fixed by pinningconfig.platform.phpto8.2.0incomposer.json(so lockfile resolution stays on the minimum supported PHP regardless of the host PHP version), regeneratingcomposer.lock, and switching the Dockerfile tocomposer installwith 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-blackwithout an explicit background, making them unreadable on dark backgrounds. Replaced with themed.search-inputstyling 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
fullNamemetric was never populated for class collections, sorefactoring-roadmap.mdshowed empty cells in theClasscolumn andai-summary.mdrendered classes as****.IdentifyVisitornow setsfullNamecentrally, 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 tofiles.md, plus a duplicated**Packages**heading where**Problems**was intended. Links now resolve to their respective*-problems.mdpages and the section heading is correct. Closes #19. - Markdown report:
problems.mdlinked to.htmlfiles. The problem category links inproblems.mdwere hardcoded to.html, breaking navigation in the Markdown report. All Markdown templates now consistently link to.mdtargets. 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 1inHistoryServicewhen 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
ReportOrchestratorwas extracted fromApplication.phpinverted the order ofwriteHistory()and report generation: the current run was only appended AFTER reports were rendered, so theHistoryDataProvidernever 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
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.
Related context
Beta — feedback welcome: [email protected]