EventDispatcher
Reference implementation of {@see MilpaEventDispatcherInterface}. Central hub for string-named, event-driven communication between plugins: exact and dot-segment wildcard subscriptions, priority ordering, listener error isolation (a throwing handler is logged and does not stop the rest), a pluggable async (queue) seam — see {@see setAsyncDispatcher()} and the `$async` semantics documented on {@see dispatch()} — and honors the {@see InterceptionSlot} interception contract (KEYSTONE, core 0.5) documented on {@see dispatch()}: an optional `$payload['slot']` a handler can stop or short-circuit, purely additive and inert when absent.
EventDispatcher::__construct()
public function __construct(Psr\Log\LoggerInterface $logger):Parameters
| Name | Type | Description |
|---|---|---|
| $logger | Psr\Log\LoggerInterface |
EventDispatcher::setAsyncDispatcher()
public function setAsyncDispatcher(callable $dispatcher): voidWire the async dispatcher (typically a queue service) that `dispatch(..., async: true)` hands events to. Without this call, `$async=true` degrades to synchronous dispatch — see the `$async` semantics on {@see dispatch()}.
Parameters
| Name | Type | Description |
|---|---|---|
| $dispatcher | callable | fn(string $eventName, array $payload): void |
EventDispatcher::dispatch()
public function dispatch(string $eventName, array $payload = [], bool $async = false): void{@inheritdoc} `$async` semantics for this implementation, per the MAY/MUST contract on {@see MilpaEventDispatcherInterface::dispatch()}: with an async dispatcher wired via {@see setAsyncDispatcher()}, `$async=true` hands the event to that callable instead of invoking subscribers inline — a conformant queue dispatch, not a fallback. Without one wired, `$async=true` degrades to synchronous dispatch (subscribers run inline, in the same call) — a conformant MAY fallback, never a silent drop; the event is always either queued or run. Interception (KEYSTONE, core 0.5) for this implementation: after EACH handler's error-isolating try/catch — unconditionally, whether or not that handler threw — this dispatcher checks whether `$payload['slot']` is an {@see InterceptionSlot} and, if `$slot->isStopped()`, stops invoking the remaining handlers for this dispatch (priority order is preserved up to that point — a higher-priority handler that stops means lower-priority handlers never run). A payload without a `'slot'` key, or with a `'slot'` that is not an {@see InterceptionSlot}, is completely unaffected — byte-identical to the pre-interception behavior. `$async=true` combined with an {@see InterceptionSlot} in the payload throws {@see \InvalidArgumentException} before anything else happens — see the guard at the top of this method.
Parameters
| Name | Type | Description |
|---|---|---|
| $eventName | string | |
| $payload | array | |
| $async | bool |
Throws
\InvalidArgumentException if `$async` is true and `$payload['slot']` is an {@see InterceptionSlot} — interception is inherently synchronous
EventDispatcher::subscribe()
public function subscribe(string $eventName, callable $handler, int $priority = 0): void{@inheritdoc}
Parameters
| Name | Type | Description |
|---|---|---|
| $eventName | string | |
| $handler | callable | |
| $priority | int |
EventDispatcher::getSubscribers()
public function getSubscribers(string $eventName): array{@inheritdoc}
Parameters
| Name | Type | Description |
|---|---|---|
| $eventName | string |
EventDispatcher::hasSubscribers()
public function hasSubscribers(string $eventName): bool{@inheritdoc}
Parameters
| Name | Type | Description |
|---|---|---|
| $eventName | string |
EventDispatcher::getRegisteredPatterns()
public function getRegisteredPatterns(): arrayGet all registered event patterns (for debugging).