128 lines
3.4 KiB
PHP
128 lines
3.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App;
|
|
|
|
use App\Container\ContainerAwareTrait;
|
|
use Closure;
|
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
|
|
|
use function is_array;
|
|
use function is_string;
|
|
|
|
final class CallableEventDispatcher extends EventDispatcher implements CallableEventDispatcherInterface
|
|
{
|
|
use ContainerAwareTrait;
|
|
|
|
/**
|
|
* @param array|class-string $className
|
|
*/
|
|
public function addServiceSubscriber(array|string $className): void
|
|
{
|
|
if (is_array($className)) {
|
|
foreach ($className as $service) {
|
|
$this->addServiceSubscriber($service);
|
|
}
|
|
return;
|
|
}
|
|
|
|
foreach ($className::getSubscribedEvents() as $eventName => $params) {
|
|
if (is_string($params)) {
|
|
$this->addCallableListener(
|
|
$eventName,
|
|
$className,
|
|
$params
|
|
);
|
|
} elseif (is_string($params[0])) {
|
|
$this->addCallableListener(
|
|
$eventName,
|
|
$className,
|
|
$params[0],
|
|
$params[1] ?? 0
|
|
);
|
|
} else {
|
|
foreach ($params as $listener) {
|
|
$this->addCallableListener(
|
|
$eventName,
|
|
$className,
|
|
$listener[0],
|
|
$listener[1] ?? 0
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array|class-string $className
|
|
*/
|
|
public function removeServiceSubscriber(array|string $className): void
|
|
{
|
|
if (is_array($className)) {
|
|
foreach ($className as $service) {
|
|
$this->removeServiceSubscriber($service);
|
|
}
|
|
return;
|
|
}
|
|
|
|
foreach ($className::getSubscribedEvents() as $eventName => $params) {
|
|
if (is_array($params) && is_array($params[0])) {
|
|
foreach ($params as $listener) {
|
|
$this->removeCallableListener(
|
|
$eventName,
|
|
$className,
|
|
$listener[0]
|
|
);
|
|
}
|
|
} else {
|
|
$this->removeCallableListener(
|
|
$eventName,
|
|
$className,
|
|
is_string($params) ? $params : $params[0]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param class-string $className
|
|
*/
|
|
public function addCallableListener(
|
|
string $eventName,
|
|
string $className,
|
|
?string $method = '__invoke',
|
|
int $priority = 0
|
|
): void {
|
|
$this->addListener(
|
|
$eventName,
|
|
$this->getCallable($className, $method),
|
|
$priority
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param class-string $className
|
|
*/
|
|
public function removeCallableListener(
|
|
string $eventName,
|
|
string $className,
|
|
?string $method = '__invoke'
|
|
): void {
|
|
$this->removeListener(
|
|
$eventName,
|
|
$this->getCallable($className, $method)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param class-string $className
|
|
*/
|
|
private function getCallable(
|
|
string $className,
|
|
?string $method = '__invoke'
|
|
): Closure {
|
|
return fn(...$args) => $this->di->get($className)->$method(...$args);
|
|
}
|
|
}
|