AzuraCast/src/CallableEventDispatcher.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);
}
}