2022-08-19 19:48:37 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Webman\Event;
|
|
|
|
|
|
|
|
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
|
use support\Log;
|
|
|
|
|
|
|
|
|
|
class Event
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
protected static $eventMap = [];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
protected static $prefixEventMap = [];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var int
|
|
|
|
|
*/
|
|
|
|
|
protected static $id = 0;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var LoggerInterface
|
|
|
|
|
*/
|
|
|
|
|
protected static $logger;
|
|
|
|
|
|
|
|
|
|
/**
|
2022-11-28 19:11:12 +08:00
|
|
|
* @param mixed $event_name
|
|
|
|
|
* @param callable $listener
|
2022-08-19 19:48:37 +08:00
|
|
|
* @return int
|
|
|
|
|
*/
|
2022-11-28 19:11:12 +08:00
|
|
|
public static function on($event_name, callable $listener): int
|
2022-08-19 19:48:37 +08:00
|
|
|
{
|
2022-11-28 19:11:12 +08:00
|
|
|
$is_prefix_name = $event_name[strlen($event_name) - 1] === '*';
|
2022-08-19 19:48:37 +08:00
|
|
|
if ($is_prefix_name) {
|
2022-11-28 19:11:12 +08:00
|
|
|
static::$prefixEventMap[substr($event_name, 0, -1)][++static::$id] = $listener;
|
2022-08-19 19:48:37 +08:00
|
|
|
} else {
|
2022-11-28 19:11:12 +08:00
|
|
|
static::$eventMap[$event_name][++static::$id] = $listener;
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
return static::$id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-11-28 19:11:12 +08:00
|
|
|
* @param mixed $event_name
|
|
|
|
|
* @param integer $id
|
2022-08-19 19:48:37 +08:00
|
|
|
* @return int
|
|
|
|
|
*/
|
|
|
|
|
public static function off($event_name, int $id): int
|
|
|
|
|
{
|
|
|
|
|
if (isset(static::$eventMap[$event_name][$id])) {
|
|
|
|
|
unset(static::$eventMap[$event_name][$id]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param mixed $event_name
|
|
|
|
|
* @param mixed $data
|
|
|
|
|
* @param bool $halt
|
|
|
|
|
* @return array|null|mixed
|
|
|
|
|
*/
|
|
|
|
|
public static function emit($event_name, $data, $halt = false)
|
|
|
|
|
{
|
|
|
|
|
$success_count = 0;
|
|
|
|
|
$listeners = static::getListeners($event_name);
|
|
|
|
|
$responses = [];
|
|
|
|
|
foreach ($listeners as $listener) {
|
|
|
|
|
try {
|
|
|
|
|
$response = $listener($data, $event_name);
|
2022-11-28 19:11:12 +08:00
|
|
|
} catch (\Throwable $e) {
|
|
|
|
|
$responses[] = $e;
|
2022-08-19 19:48:37 +08:00
|
|
|
if (!static::$logger && is_callable('\support\Log::error')) {
|
|
|
|
|
static::$logger = Log::channel();
|
|
|
|
|
}
|
|
|
|
|
if (static::$logger) {
|
2022-11-28 19:11:12 +08:00
|
|
|
static::$logger->error($e);
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
$responses[] = $response;
|
|
|
|
|
if ($halt && !is_null($response)) {
|
|
|
|
|
return $response;
|
|
|
|
|
}
|
2022-11-28 19:11:12 +08:00
|
|
|
if ($response === false) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
return $halt ? null : $responses;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public static function list(): array
|
|
|
|
|
{
|
2022-11-28 19:11:12 +08:00
|
|
|
$listeners = [];
|
2022-08-19 19:48:37 +08:00
|
|
|
foreach (static::$eventMap as $event_name => $callback_items) {
|
|
|
|
|
foreach ($callback_items as $id => $callback_item) {
|
2022-11-28 19:11:12 +08:00
|
|
|
$listeners[$id] = [$event_name, $callback_item];
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
foreach (static::$prefixEventMap as $event_name => $callback_items) {
|
|
|
|
|
foreach ($callback_items as $id => $callback_item) {
|
2022-11-28 19:11:12 +08:00
|
|
|
$listeners[$id] = [$event_name . '*', $callback_item];
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
}
|
2022-11-28 19:11:12 +08:00
|
|
|
ksort($listeners);
|
|
|
|
|
return $listeners;
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param mixed $event_name
|
|
|
|
|
* @return callable[]
|
|
|
|
|
*/
|
|
|
|
|
public static function getListeners($event_name): array
|
|
|
|
|
{
|
|
|
|
|
$listeners = static::$eventMap[$event_name] ?? [];
|
|
|
|
|
foreach (static::$prefixEventMap as $name => $callback_items) {
|
|
|
|
|
if (strpos($event_name, $name) === 0) {
|
|
|
|
|
$listeners = array_merge($listeners, $callback_items);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ksort($listeners);
|
|
|
|
|
return $listeners;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param mixed $event_name
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public static function hasListener($event_name): bool
|
|
|
|
|
{
|
|
|
|
|
return !empty(static::getListeners($event_name));
|
|
|
|
|
}
|
|
|
|
|
}
|