forked from fa/breadcrumb-the-shire
50 lines
1.4 KiB
PHP
50 lines
1.4 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace MintyPHP\App\Module;
|
||
|
|
|
||
|
|
use MintyPHP\App\AppContainer;
|
||
|
|
use MintyPHP\App\Module\Contracts\EventListener;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fire-and-forget event dispatcher for module lifecycle events.
|
||
|
|
*
|
||
|
|
* Listeners are declared in module manifests and lazy-resolved from the container.
|
||
|
|
* A failing listener does not break the dispatch chain — the exception is swallowed
|
||
|
|
* so that one misbehaving module cannot disrupt core flows.
|
||
|
|
*/
|
||
|
|
final class ModuleEventDispatcher
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* @param array<string, list<array{class: class-string, method: string}>> $listenerMap
|
||
|
|
*/
|
||
|
|
public function __construct(
|
||
|
|
private readonly array $listenerMap,
|
||
|
|
private readonly AppContainer $container
|
||
|
|
) {
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array<string, mixed> $payload
|
||
|
|
*/
|
||
|
|
public function dispatch(string $event, array $payload): void
|
||
|
|
{
|
||
|
|
$listeners = $this->listenerMap[$event] ?? [];
|
||
|
|
|
||
|
|
foreach ($listeners as $descriptor) {
|
||
|
|
try {
|
||
|
|
$class = $descriptor['class'];
|
||
|
|
$method = $descriptor['method'];
|
||
|
|
|
||
|
|
$listener = $this->container->get($class);
|
||
|
|
if (!$listener instanceof EventListener) {
|
||
|
|
$listener = new $class();
|
||
|
|
}
|
||
|
|
|
||
|
|
$listener->{$method}($event, $payload);
|
||
|
|
} catch (\Throwable) {
|
||
|
|
// Swallow — one failing listener must not break the chain.
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|