60 lines
1.5 KiB
PHP
60 lines
1.5 KiB
PHP
<?php declare(strict_types=1);
|
|
|
|
namespace Lubian\AttributeMagic\Infrastructure\Event;
|
|
|
|
use Invoker\InvokerInterface;
|
|
|
|
use function Lubian\AttributeMagic\Infrastructure\arrayFilter;
|
|
use function usort;
|
|
|
|
final class Dispatcher
|
|
{
|
|
/**
|
|
* @param Listener[] $listeners
|
|
*/
|
|
public function __construct(
|
|
private readonly InvokerInterface $invoker,
|
|
private array $listeners = [],
|
|
) {
|
|
}
|
|
|
|
public function addListener(Listener $listener): void
|
|
{
|
|
$this->listeners[] = $listener;
|
|
}
|
|
|
|
/**
|
|
* @return Listener[]
|
|
*/
|
|
public function getListenerForEvent(GenericEvent $event): array
|
|
{
|
|
return arrayFilter(
|
|
$this->listeners,
|
|
static fn (Listener $l): bool => $l->eventClass === $event::class,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return Listener[]
|
|
*/
|
|
public function getSortedListenerForEvent(GenericEvent $event): array
|
|
{
|
|
$filtered = $this->getListenerForEvent($event);
|
|
usort($filtered, static fn (Listener $a, Listener $b): int => $a->priority <=> $b->priority);
|
|
return $filtered;
|
|
}
|
|
|
|
public function dispatch(GenericEvent $event): void
|
|
{
|
|
foreach ($this->getSortedListenerForEvent($event) as $listener) {
|
|
if ($event->stopped === true) {
|
|
return;
|
|
}
|
|
|
|
$this->invoker->call(
|
|
[$listener->listenerClass, $listener->listenerMethod],
|
|
[$event],
|
|
);
|
|
}
|
|
}
|
|
}
|