From fcb3e114a7f9bdbcfd90f9283dd2c2588da09590 Mon Sep 17 00:00:00 2001 From: Madeorsk Date: Fri, 8 Nov 2024 15:59:15 +0100 Subject: [PATCH] Initialize Nest events library. --- .gitignore | 6 ++++ composer.json | 27 +++++++++++++++ composer.lock | 56 ++++++++++++++++++++++++++++++ src/Event.php | 7 ++++ src/EventsManager.php | 81 +++++++++++++++++++++++++++++++++++++++++++ src/HasEvents.php | 39 +++++++++++++++++++++ 6 files changed, 216 insertions(+) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 src/Event.php create mode 100644 src/EventsManager.php create mode 100644 src/HasEvents.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2dfd9ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# IDEA +.idea/ +*.iml + +# Composer +vendor/ diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..4d8555b --- /dev/null +++ b/composer.json @@ -0,0 +1,27 @@ +{ + "version": "1.0", + "name": "nest/events", + "description": "Nest events implementation.", + "type": "library", + "authors": [ + { + "name": "Madeorsk", + "email": "madeorsk@protonmail.com" + } + ], + "autoload": { + "psr-4": { + "Nest\\Events\\": "src/" + } + }, + "repositories": [ + { + "type": "vcs", + "url": "https://code.zeptotech.net/Nest/Core" + } + ], + "require": { + "php": "^8.3", + "nest/core": "dev-main" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..98230ab --- /dev/null +++ b/composer.lock @@ -0,0 +1,56 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "4185bcac56ba1943814494a50cebd442", + "packages": [ + { + "name": "nest/core", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://code.zeptotech.net/Nest/Core", + "reference": "22296b8d7c8b528089189a8d9500395424cb6468" + }, + "require": { + "php": "^8.3" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "Nest\\": "src/" + }, + "files": [ + "src/Utils/Array.php", + "src/Utils/Paths.php", + "src/Utils/Reflection.php", + "src/Utils/String.php" + ] + }, + "authors": [ + { + "name": "Madeorsk", + "email": "madeorsk@protonmail.com" + } + ], + "description": "Nest framework core.", + "time": "2024-11-08T11:12:38+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "nest/core": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.3" + }, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/src/Event.php b/src/Event.php new file mode 100644 index 0000000..cf2348f --- /dev/null +++ b/src/Event.php @@ -0,0 +1,7 @@ + + */ + protected array $listeners = []; + + /** + * Add an event listener to the listeners list. + * @template T of Event + * @param class-string $eventType The event type class to listen for. + * @param callable(T $event): (void|bool) $listener The event listener to add. If false is returned, stop event propagation. + * @return void + * @throws InvalidTypeException + */ + public function addListener(string $eventType, callable $listener): void + { + expect_type($eventType, Event::class); + + // Initialize the listeners list if it's empty. + if (empty($this->listeners[$eventType])) $this->listeners[$eventType] = []; + // Add the listener. + $this->listeners[$eventType][] = $listener; + } + + /** + * Remove the given listener from the listeners list. + * @template T of Event + * @param class-string $eventType The event type class. + * @param callable(T $event): (void|bool) $listener The listener to remove. + * @return void + * @throws InvalidTypeException + */ + public function removeListener(string $eventType, callable $listener): void + { + expect_type($eventType, Event::class); + + if (!empty($this->listeners[$eventType])) + { + foreach ($this->listeners[$eventType] as $key => $currentListener) + { // For each listeners, if it's matching the given one, remove it. + if ($currentListener == $listener) unset($this->listeners[$eventType][$key]); + } + } + } + + /** + * Fire an event. + * @param Event $event The event to fire. + * @return void + */ + public function fire(Event $event): void + { + foreach (get_all_classes($event) as $className) + { // For each class, from the most specific to the least specific. + if (!empty($this->listeners[$className])) + { // If there are listeners for the current class. + foreach ($this->listeners[$className] as $listener) + { // Call each listener. + $result = $listener($event); + if ($result === false) + // If the result is false, stop firing. + return; + } + } + } + } +} diff --git a/src/HasEvents.php b/src/HasEvents.php new file mode 100644 index 0000000..19fa2af --- /dev/null +++ b/src/HasEvents.php @@ -0,0 +1,39 @@ +eventsManager)) $this->eventsManager = new EventsManager(); + + return $this->eventsManager; + } + + /** + * Add a listener for the given event type. + * @template T of Event + * @param class-string $eventType The event type class to listen for. + * @param callable(T $event): (void|bool) $eventListener The event listener. If false is returned, stop event propagation. + * @return void + * @throws InvalidTypeException + */ + public function listen(string $eventType, callable $eventListener): void + { + $this->getEventsManager()->addListener($eventType, $eventListener); + } +}