Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 28 additions & 79 deletions flight/core/EventDispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,134 +6,83 @@

class EventDispatcher
{
/** @var self|null Singleton instance of the EventDispatcher */
private static ?self $instance = null;

/** @var array<string, array<int, callable>> */
/** @var array<string, callable[]> */
protected array $listeners = [];

/**
* Singleton instance of the EventDispatcher.
*
* @return self
*/
public static function getInstance(): self
{
if (self::$instance === null) {
self::$instance = new self();
}

return self::$instance;
}

/**
* Register a callback for an event.
*
* @param string $event Event name
* @param callable $callback Callback function
*/
public function on(string $event, callable $callback): void
{
if (isset($this->listeners[$event]) === false) {
$this->listeners[$event] = [];
}
$this->listeners[$event] ??= [];
$this->listeners[$event][] = $callback;
}

/**
* Trigger an event with optional arguments.
*
* @param string $event Event name
* @param mixed ...$args Arguments to pass to the callbacks
*
* @param mixed ...$args Arguments to pass to the listeners.
* @return mixed
*/
Comment thread
fadrian06 marked this conversation as resolved.
public function trigger(string $event, ...$args)
{
$result = null;
if (isset($this->listeners[$event]) === true) {
foreach ($this->listeners[$event] as $callback) {
$result = call_user_func_array($callback, $args);

// If you return false, it will break the loop and stop the other event listeners.
if ($result === false) {
break; // Stop executing further listeners
}
$listenerReturnValue = null;

foreach ($this->getListeners($event) as $listener) {
$listenerReturnValue = $listener(...$args);
Comment thread
fadrian06 marked this conversation as resolved.

if ($listenerReturnValue === false) {
break;
}
}
return $result;

return $listenerReturnValue;
}

/**
* Check if an event has any registered listeners.
*
* @param string $event Event name
*
* @return bool True if the event has listeners, false otherwise
*/
public function hasListeners(string $event): bool
{
return isset($this->listeners[$event]) === true && count($this->listeners[$event]) > 0;
return (
isset($this->listeners[$event])
&& is_array($this->listeners[$event])
&& count($this->listeners[$event])
);
}

/**
* Get all listeners registered for a specific event.
*
* @param string $event Event name
*
* @return array<int, callable> Array of callbacks registered for the event
*/
/** @return callable[] */
public function getListeners(string $event): array
{
return $this->listeners[$event] ?? [];
}

/**
* Get a list of all events that have registered listeners.
*
* @return array<int, string> Array of event names
*/
/** @return string[] */
public function getAllRegisteredEvents(): array
{
return array_keys($this->listeners);
}

/**
* Remove a specific listener for an event.
*
* @param string $event the event name
* @param callable $callback the exact callback to remove
*
* @return void
*/
public function removeListener(string $event, callable $callback): void
{
if (isset($this->listeners[$event]) === true && count($this->listeners[$event]) > 0) {
$this->listeners[$event] = array_filter($this->listeners[$event], function ($listener) use ($callback) {
return $listener !== $callback;
});
$this->listeners[$event] = array_values($this->listeners[$event]); // Re-index the array
if (!$this->hasListeners($event)) {
return;
}

$this->listeners[$event] = array_values(array_filter(
$this->getListeners($event),
static fn(callable $listener): bool => $listener !== $callback,
));
}

/**
* Remove all listeners for a specific event.
*
* @param string $event the event name
*
* @return void
*/
public function removeAllListeners(string $event): void
{
if (isset($this->listeners[$event]) === true) {
unset($this->listeners[$event]);
}
unset($this->listeners[$event]);
}

/**
* Remove the current singleton instance of the EventDispatcher.
*
* @return void
*/
public static function resetInstance(): void
{
self::$instance = null;
Expand Down