Closes #8769: Migrate StudioPress accelerator into Hostings Subscriber - #8771
Closes #8769: Migrate StudioPress accelerator into Hostings Subscriber#8771remyperona wants to merge 2 commits into
Conversation
…Hostings Subscriber Ports the raw-require'd inc/3rd-party/themes/studiopress.php into inc/ThirdParty/Hostings/StudioPress.php as a container-registered Subscriber, resolving #8769. Both hooks (admin_init, rocket_after_clean_domain) are registered unconditionally since the runtime detection global (SP_Accel_Nginx_Proxy_Cache_Purge) can be theme-defined and therefore isn't reliably present when HostResolver runs at plugins_loaded; the existing isset()/is_a() guard is preserved verbatim inside each callback instead. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 12 |
🟢 Coverage 85.00% diff coverage
Metric Results Coverage variation Report missing for 308c4d71 Diff coverage ✅ 85.00% diff coverage (50.00%) Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (308c4d7) Report Missing Report Missing Report Missing Head commit (49f2481) 47680 22474 47.14% Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#8771) 20 17 85.00% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%1 Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
|
Note Generated by the AI delivery pipeline (qa-engineer · Claude Opus 4.8). QA: ✅ PASS
Evidence
Smoke tests
Note on scope vs. originating issue: issue #8769 suggested |
|
Note Generated by the AI delivery pipeline (lead-reviewer · Claude Opus 4.8). Review: ✅ PASS Re-reviewed after commit
Verified: |
Adds a tests/Fixtures/classes stub for SP_Accel_Nginx_Proxy_Cache_Purge (mirroring the NinukisCaching pattern) so PHPStan can resolve the Mockery::mock() calls, and replaces addToAssertionCount() with real assertions (assertArrayNotHasKey / Mockery ->never() expectations) in the three no-op test branches, since addToAssertionCount() is not baseline-eligible for new code. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Important On hold — do not merge yet. Pending confirmation of whether StudioPress Accelerator is still a supported integration. The migration itself is complete, green (all CI passing), QA-passed, and lead-review-approved — it strictly preserves current behavior. However, before merging we want to resolve an open question raised during review: Is StudioPress Accelerator still in use, or fully deprecated since the WP Engine acquisition? Signals that it may be dead:
What unblocks this PR:
Marking as draft until that decision is made. |
Closes #8769
Description
Migrates the legacy
inc/3rd-party/themes/studiopress.phpprocedural file into a container-registered Subscriber class atinc/ThirdParty/Hostings/StudioPress.php, resolving the issue where StudioPress/Genesis Accelerator compatibility was unconditionallyrequired outside the DI container. The integration now lives under the Hostings namespace and is registered via the container, while preserving identical runtime detection behavior and cache-clearing functionality.Type of change
Detailed scenario
What was tested
Automated coverage authored and run for the migrated StudioPress subscriber:
tests/Unit/inc/ThirdParty/Hostings/StudioPress/):getSubscribedEvents(asserts both hooks are returned unconditionally),clearCacheAfterAccelerator(capability guard, nonce handling, URL-purge vs theme-purge branches),cleanAcceleratorCache(runtimeisset/is_aguard,cache_flush_theme()invoked only when the global is present).tests/Integration/inc/ThirdParty/Hostings/StudioPress/):hooksAreRegistered(container resolvesstudiopress_acceleratorto aStudioPressinstance and bothadmin_init/rocket_after_clean_domaincallbacks are actually attached after bootstrap),cleanAcceleratorCache.inc/3rd-party/themes/studiopress.php; no behavioral change.QA: PASS (report: #8771 (comment)). QA booted the wp-env environment and verified all four acceptance criteria live: the container resolves
studiopress_acceleratorto aStudioPressinstance; bothadmin_initandrocket_after_clean_domainhooks are attached at priority 10; a full cache clear ran with no warnings/fatals; and the new suites passed in-container (unit--group StudioPress10 tests/41 assertions, integration--group StudioPress3 tests/6 assertions). The real host-purge branch (SP_Accel_Nginx_Proxy_Cache_Purge::cache_flush_theme()) is guarded and not exercisable off a StudioPress host — covered by Mockery-based tests. All CI checks green (PHPUnit matrix PHP 7.4–8.5, PHPCS, PHPStan, task-check).How to test
Manual Smoke Test (required): On a site WITHOUT
SP_Accel_Nginx_Proxy_Cache_Purgedefined (the common case):wp eval 'var_dump( has_action( "admin_init" ), has_action( "rocket_after_clean_domain" ) );'should confirm both hooks attached.wp eval 'rocket_clean_domain();'.sp_accel_nginx_proxy_cache_purge.Automated Unit Test Coverage: 10 new unit tests in
tests/Unit/inc/ThirdParty/Hostings/StudioPress/cover:clear_cache_after_accelerator()with: (a) capability denied, (b) validsp-accel-purge-urlnonce +cache-purge-urlpresent, (c) validsp-accel-purge-themenonce, (d) invalid/missing nonce, (e)$GLOBALS['sp_accel_nginx_proxy_cache_purge']unset.clean_accelerator_cache()with the global set and absent.Automated Integration Test Coverage: 3 new integration tests in
tests/Integration/inc/ThirdParty/Hostings/StudioPress/verify:Subscriber_Interfaceand event manager.has_action()reports both hooks present regardless ofHostResolver::get_host_service()'s return value (locks in the "always-on" contract).Affected Features & Quality Assurance Scope
wp rocket clean, and programmaticrocket_clean_domain()calls.Technical description
Documentation
Why always-loaded registration (not gated by
HostResolver):SP_Accel_Nginx_Proxy_Cache_Purgecan be defined by a Genesis/StudioPress child theme'sfunctions.php, which WordPress loads after theplugins_loadedaction.HostResolver::get_host_service()runs insideHostings\ServiceProvider::register(), which is hooked toplugins_loaded. A resolver-timeclass_exists()check would returnfalseon sites where the integration exists but is defined theme-side, silently dropping both hooks on exactly the sites this integration targets — a regression from the current always-loadedrequire.Detection is therefore performed at hook-fire time inside each callback (
admin_initandrocket_after_clean_domain), using the runtimeisset()/is_a()guard that was already present in the legacy code. This guard is evaluated after the theme has loaded, so it correctly detects theme-defined instances.Implementation pattern:
StudioPressclass implementsSubscriber_Interfaceand is registered as a shared container binding ('studiopress_accelerator' => StudioPress::class) unconditionally inHostings\ServiceProvider::register().get_subscribed_events()returns both hooks unconditionally (no resolver-time gate).isset()/is_a()guard verbatim; mirrors the pattern used byKinsta.php(defensive re-check even though the subscriber is conditionally registered there; here the guard is the entire detection mechanism).StudioPressis added to the$common_subscribersarray inPlugin::init_common_subscribers()as an unconditional entry, matching the pattern used by'jetpack','mobile_subscriber', and'wordfence_subscriber'.HostResolver.phpandHostSubscriberFactory.phpare left unchanged; no new detection branch or case added.Behavioral equivalence:
Both hooks (
admin_initfor user-initiated purge confirmation,rocket_after_clean_domainfor automatic cache coordination) are ported verbatim from the legacy procedural file:clear_cache_after_accelerator()→ previouslyrocket_clear_cache_after_studiopress_accelerator()clean_accelerator_cache()→ previouslyrocket_clean_studiopress_accelerator()All conditionals, nonce action strings, sanitization, and function calls are unchanged.
New dependencies
None.
Risks
None identified.
The new code path is a 1:1 refactoring of existing, production-proven logic. The only structural change is moving from a procedural
requireto a container-registered Subscriber, which is the standard DI pattern used throughout the codebase. Runtime behavior is identical (detection and cache-clearing happen at the same hooks with the same guards).No new permissions, capabilities, or API calls introduced. Multisite network activation and plugin activation/deactivation handling are unaffected (the legacy code never hooked those events either).
Follow-up tickets
None. Two nice-to-have items surfaced during review (a wiring-key regression unit test, and a doc comment on the always-on integration test's coverage limitation) were reviewed and discarded — the existing integration test already asserts the end-to-end wiring at runtime.
Mandatory Checklist
Code validation
Code style
Unticked items justification
Output-messages item is N/A: this refactoring introduces no user-facing output messages — it relocates existing hook callbacks 1:1 with no new notices, errors, or logs. Acceptance criteria were validated by the QA pass (see "What was tested"); the new/changed lines are exercised by the unit + integration suites.
Additional Checks