Download the PHP package hokoo/wp-hooks-dispatcher without Composer
On this page you can find all versions of the php package hokoo/wp-hooks-dispatcher. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download hokoo/wp-hooks-dispatcher
More information about hokoo/wp-hooks-dispatcher
Files in hokoo/wp-hooks-dispatcher
Package wp-hooks-dispatcher
Short Description Context-aware WordPress action and filter subscriptions
License MIT
Homepage https://github.com/hokoo/wp-hooks-dispatcher
Informations about the package wp-hooks-dispatcher
wpHooksDispatcher
Prevents a WordPress action or filter callback created for one site from running while a different multisite context is active.
[!IMPORTANT] This package is a temporary workaround for a WordPress Core
WP_Hooklimitation: callback registrations cannot be scoped to an individual Multisite site. The proposed native solution is tracked in WordPress Core Trac #66097. Once the ticket is resolved in Core and the WordPress version containing the fix has been released, this package will be considered obsolete. Check the ticket status before adopting it in new projects.
The problem
The WordPress hook registry is process-global. switch_to_blog() changes the
active site and database prefix, but it does not remove or scope callbacks that
were registered earlier:
This matters when the callback retains a site-bound database adapter, client, cache, or other service. In a long-running worker, multisite test process, CLI command, or any application that switches sites dynamically, stale callbacks can execute against the wrong context, fail unexpectedly, or keep retired object graphs alive.
add_action() and add_filter() have no site-context boundary and return no
lifecycle handle for the registration.
What this package does
ActionDispatcher::subscribe() and FilterDispatcher::subscribe() capture
both the current WordPress blog ID and $wpdb->prefix, then register a stable
wrapper with the native WordPress hook registry. Every time the hook fires, the
wrapper checks the current values before invoking application code:
- both values match: the consumer callback runs normally;
- either value differs: the callback is skipped (and filters pass the current value through unchanged);
- the captured context is restored: delivery resumes while still subscribed;
- the subscription is removed: delivery stops permanently for that handle.
WordPress still owns hook dispatch, priority order, filter value chaining, and accepted-argument handling. Exceptions from an active callback pass through unchanged.
The package deliberately does not switch sites, create site-specific clients, or rebind existing subscriptions. The consumer remains responsible for initializing and subscribing a separate application object in every site context it uses.
When to use it
Use it for callbacks that retain site-specific state in a process that can call
switch_to_blog() after registration. Typical cases are multisite workers,
test suites, importers, queue consumers, and CLI processes.
It is usually unnecessary for a conventional isolated WordPress request that never changes site, or for a callback that is intentionally context-neutral.
Requirements
- PHP 8.1 or newer
- a loaded WordPress runtime providing the relevant
add_action()andremove_action()oradd_filter()andremove_filter()functions,get_current_blog_id(), and a string$wpdb->prefix
The package has no Composer runtime dependencies beyond PHP. Non-standard or
isolated bootstraps can inject their own ActionHookGateway or
FilterHookGateway and SiteContextProvider instead of using the native
WordPress adapters.
Install
Use actions
Create the dispatcher after WordPress is loaded. Subscribe each site-bound callback while its intended site is active, and retain the returned handle for explicit teardown:
The dispatcher registers its own wrapper, not the original consumer callback.
Consequently, remove_action($hook, $originalCallback) cannot remove this
registration; call unsubscribe() on the returned handle instead.
Use filters
Filter subscriptions use the same context and lifecycle rules. When the captured context is inactive, the wrapper returns the current filtered value unchanged so later callbacks continue to receive the correct value:
Filter subscriptions require acceptedArguments to be at least 1. The
wrapper must receive the current filtered value in order to pass it through
safely when its captured context is inactive.
As with actions, remove a managed filter through its subscription handle rather
than by passing the original consumer callback to remove_filter(). See the
complete public contract.
Development
Integration tests load WordPress's real WP_Hook implementation from the
checkout identified by WP_CORE_DIR, including its native multisite
switch/restore lifecycle. The coverage command requires Xdebug or PCOV and
enforces at least 90% production line coverage.
License
MIT.