forked from fa/breadcrumb-the-shire
Six targeted improvements to the modular monolith platform: 1. Fix AddressBook session key prefix to follow module.<id>.* convention 2. Move ADDRESS_BOOK_VIEW permission constant from core PermissionService into module 3. Add declarative JSON schema for module manifests (.agents/contracts/) 4. Add `requires` field with missing-dependency and circular-dependency detection 5. Add lightweight fire-and-forget event dispatcher (user.created/deleted/login/logout) 6. Add module deactivation hook interface and CLI script (bin/module-deactivate.php) Includes 15 new architecture/unit tests covering all new functionality. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
|
|
}
|
|
}
|
|
}
|
|
}
|