Static bootloader + Services locator (drop the DI container) - #11
Merged
Conversation
BREAKING: the generated plugin's architecture changes.
- Plugin is a singleton bootloader: Plugin::instance()->boot() news up
every selected module and calls its init_hooks(); boot() is idempotent.
No constructor, no provider list, no register()/boot() two-phase.
- Services is a static locator — Services::cache(), Services::settings_repository(),
etc. build one memoised instance per accessor, with set()/reset() test seams.
Only emitted for module sets that need a shared service.
- Every module class loses `implements Service_Provider` / `Conditional` and
merges register()+boot() into one init_hooks(): void. Dependencies are
constructor-injected from Services at the bootloader call site.
- WooCommerce modules go inside one `if ( class_exists( 'WooCommerce' ) )`
guard in boot() instead of each provider implementing Conditional.
- Deleted: Core/Container, Core/Exceptions/Not_Found_Exception,
Contracts/Service_Provider, Contracts/Conditional, tests/Unit/Container_Test.
Activatable/Deactivatable keep their contract but lose the Container arg.
- Activator/Deactivator run `( new X() )->method()` directly; the main file
calls Plugin::instance()->boot() on plugins_loaded.
- index.js: providerRegistrations -> bootLines / wooBootLines / servicesAccessors;
{{PROVIDER_REGISTRATIONS}} -> {{BOOTLOADER_LINES}} + {{SERVICES_ACCESSORS}}.
- Tests: Container_Test dropped; Example_Test + Plugin_Boot_Test cover the
singleton + idempotent boot; new Services_Test for the locator seams.
Verified: 67 generator + 13 engine tests; full all-modules scaffold — php -l
clean on every file, no leftover Container/Service_Provider refs, no stray
tokens. composer lint / composer test on the new shape run in CI.
akshat009
added a commit
that referenced
this pull request
Aug 29, 2026
akshat009
added a commit
that referenced
this pull request
Aug 29, 2026
…repare-dist (#11, #12 revised) Re-audit #2 retracted "drop the */templates/* exclude" — the WC email/My-Account overrides genuinely fail three sniffs (PrefixAllGlobals on core WC hook names + loosely-named locals; EscapeOutput on plain-text bodies that use wp_strip_all_tags). But the blanket path exclude also silenced EscapeOutput on the HTML email template, where escaping does matter. Now: when a woo:email / woo:my-account module ships a templates/ dir, phpcs.xml adds `<file>./templates</file>` and excludes only: - WordPress.NamingConventions.PrefixAllGlobals for */templates/* - WordPress.Security.EscapeOutput for */templates/emails/plain/* only Everything else in templates/ (docblocks, spacing, i18n, the HTML email's escaping) is linted. Gated on a new has_wc_template_overrides flag; a scaffold without those modules has no templates/ reference at all. Also: `composer prepare-dist` = `composer install --no-dev --optimize-autoloader`, so `npm run plugin-zip` doesn't depend on the user reading the release docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces the DI-container architecture with a lighter static bootloader, per request.
Before / after
Plugincreate()builds aContainer+ provider list;boot()loopsregister()thenboot()Plugin::instance()->boot()— news up each module, callsinit_hooks(); idempotentimplements Service_Provider [, Conditional],register()+boot()init_hooks(): void$container->get(X::class)+ per-provider factory closuresServices::x()— static, memoised, one instance per accessorimplements Conditional/is_needed()if ( class_exists( 'WooCommerce' ) )block inboot()Core/Container,Core/Exceptions/Not_Found_Exception,Contracts/Service_Provider,Contracts/Conditional,Container_TestActivator/Deactivatorkeep theActivatable/Deactivatablecontract but drop theContainerargument and( new X() )->method()directly. Main file callsPlugin::instance()->boot()onplugins_loaded.Tests
Container_Testremoved; newServices_Testcoversset()/reset().Example_Test/Plugin_Boot_Testnow assert the singleton identity + idempotentboot()(no double hook registration).->boot(new Container())to->init_hooks().Verification
67 generator + 13 engine tests green. Full all-modules scaffold:
php -lclean on every PHP file, no leftoverContainer/Service_Providerreferences, no stray template tokens.composer lint(wp-org + vip + both) andcomposer teston the new shape run in CI here.