Skip to content

Make the plugin file the composition root#46

Merged
GaryJones merged 3 commits into
mainfrom
GaryJones/composition-root
Jun 12, 2026
Merged

Make the plugin file the composition root#46
GaryJones merged 3 commits into
mainfrom
GaryJones/composition-root

Conversation

@GaryJones

Copy link
Copy Markdown
Owner

The Plugin class had become a single-responsibility class wearing the wrong name: everything it did was the settings page. ARCHITECTURE.md is unambiguous that a plugin does not need a Plugin class at all — the main file defines one constant, loads the autoloader, and wires its features through a bootstrapper. My earlier brightnucleus change kept a Plugin class and injected __FILE__ into it, which quietly diverged from that. This realigns it.

plugin-slug.php is now the composition root: it defines PLUGIN_SLUG_FILE — the single constant every path derives from at runtime — and on plugins_loaded hands off to a Bootstrapper. The bootstrapper is the one place features are registered; today it registers a SettingsPage, which holds what Plugin used to, and new features slot in beside it. No Plugin class, no globals.

The one wrinkle is that referencing PLUGIN_SLUG_FILE inside a class is what previously blocked PHPStan's top level, since PHPStan does not evaluate the runtime define(). Rather than route around it by injecting the path, a small bootstrap file declares the constant for analysis, so the classes use it directly — as the standard writes it — and analysis stays at max.

The boilerplate stays flat and container-less; the DI container and layered namespaces ARCHITECTURE.md shows are the scale-up path, not something to impose on a single settings page. The tests split to match the new classes, the bootstrapper's wiring is covered with a @uses annotation for the feature it registers, and mutation coverage holds at 100%.

ARCHITECTURE.md is explicit that no Plugin class is needed: the main file
defines one constant, loads the autoloader and wires features through a
bootstrapper. The former Plugin was only ever the settings page, so it
becomes a SettingsPage feature the Bootstrapper registers, and
PLUGIN_SLUG_FILE returns as the single source every path derives from.
PHPStan does not evaluate the runtime define() in the plugin file, so a
bootstrap file tells it about PLUGIN_SLUG_FILE. The classes can then use
the constant directly while analysis stays at max.
Splits the former Plugin tests to match the new classes and adds the
bootstrapper's wiring, holding mutation coverage at 100%.
@GaryJones GaryJones merged commit 555f852 into main Jun 12, 2026
4 checks passed
@GaryJones GaryJones deleted the GaryJones/composition-root branch June 12, 2026 07:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant