From b2d7164be0d5a76443caa513242e9bfd79c56664 Mon Sep 17 00:00:00 2001 From: fadrian06 Date: Thu, 8 Feb 2024 15:37:55 -0400 Subject: [PATCH 1/5] Better Dispatcher documentation --- flight/core/Dispatcher.php | 20 ++++++++++---------- tests/DispatcherTest.php | 3 ++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/flight/core/Dispatcher.php b/flight/core/Dispatcher.php index d91b4b2..8cc78bc 100644 --- a/flight/core/Dispatcher.php +++ b/flight/core/Dispatcher.php @@ -49,26 +49,26 @@ class Dispatcher $output = ''; // Run pre-filters - $thereAreBeforeFilters = !empty($this->filters[$name]['before']); + $thereAreBeforeFilters = !empty($this->filters[$name][self::FILTER_BEFORE]); if ($thereAreBeforeFilters) { - $this->filter($this->filters[$name]['before'], $params, $output); + $this->filter($this->filters[$name][self::FILTER_BEFORE], $params, $output); } // Run requested method - $callback = $this->get($name); + $requestedMethod = $this->get($name); - if ($callback === null) { + if ($requestedMethod === null) { throw new Exception("Event '$name' isn't found."); } - $output = $callback(...$params); + $output = $requestedMethod(...$params); // Run post-filters - $thereAreAfterFilters = !empty($this->filters[$name]['after']); + $thereAreAfterFilters = !empty($this->filters[$name][self::FILTER_AFTER]); if ($thereAreAfterFilters) { - $this->filter($this->filters[$name]['after'], $params, $output); + $this->filter($this->filters[$name][self::FILTER_AFTER], $params, $output); } return $output; @@ -118,7 +118,7 @@ class Dispatcher } /** - * Clears an event. If no name is given, all events are removed. + * Clears an event. If no name is given, all events will be removed. * * @param ?string $name Event name */ @@ -165,7 +165,7 @@ class Dispatcher * @param array $params Method parameters * @param mixed $output Method output * - * @throws Exception If an event throws an `Exception`. + * @throws Exception If an event throws an `Exception` or if `$filters` contains an invalid filter. */ public static function filter(array $filters, array &$params, &$output): void { @@ -190,7 +190,7 @@ class Dispatcher * @param array $params Function parameters * * @return mixed Function results - * @throws Exception + * @throws Exception If `$callback` also throws an `Exception`. */ public static function execute($callback, array &$params = []) { diff --git a/tests/DispatcherTest.php b/tests/DispatcherTest.php index 97401ad..6cb628d 100644 --- a/tests/DispatcherTest.php +++ b/tests/DispatcherTest.php @@ -208,9 +208,10 @@ class DispatcherTest extends TestCase $params = []; $output = ''; + $invalidCallable = 'invalidGlobalFunction'; + $validCallable = function (): void { }; - $invalidCallable = 'invalidGlobalFunction'; Dispatcher::filter([$validCallable, $invalidCallable], $params, $output); } From be6a3fc7d6a7fc3020271a19ffaa825389a8e8a0 Mon Sep 17 00:00:00 2001 From: fadrian06 Date: Thu, 8 Feb 2024 16:04:58 -0400 Subject: [PATCH 2/5] Added test-coverage:win script --- composer.json | 1 + flight.sublime-project | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/composer.json b/composer.json index d36788d..536aa44 100644 --- a/composer.json +++ b/composer.json @@ -55,6 +55,7 @@ "scripts": { "test": "phpunit", "test-coverage": "rm clover.xml && XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=coverage --coverage-clover=clover.xml && vendor/bin/coverage-check clover.xml 100", + "test-coverage:win": "del clover.xml && phpunit --coverage-html=coverage --coverage-clover=clover.xml && coverage-check clover.xml 100", "lint": "phpstan --no-progress -cphpstan.neon", "beautify": "phpcbf --standard=phpcs.xml", "phpcs": "phpcs --standard=phpcs.xml -n" diff --git a/flight.sublime-project b/flight.sublime-project index 536f644..8f2848d 100644 --- a/flight.sublime-project +++ b/flight.sublime-project @@ -53,6 +53,11 @@ "name": "Format", "quiet": true, "shell_cmd": "composer beautify -- --no-colors" + }, + { + "name": "Test coverage", + "quiet": true, + "shell_cmd": "composer test-coverage:win -- --no-colors" } ], } From 327d04370974900c7ca76752d8f96a21d89114a1 Mon Sep 17 00:00:00 2001 From: fadrian06 Date: Thu, 8 Feb 2024 16:07:15 -0400 Subject: [PATCH 3/5] Separated Dispatcher::run in runPreFilters(), runEvent() and runPostFilters() --- flight/core/Dispatcher.php | 54 ++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/flight/core/Dispatcher.php b/flight/core/Dispatcher.php index 8cc78bc..73fda85 100644 --- a/flight/core/Dispatcher.php +++ b/flight/core/Dispatcher.php @@ -46,29 +46,61 @@ class Dispatcher */ public function run(string $name, array $params = []) { - $output = ''; + $this->runPreFilters($name, $params); + $output = $this->runEvent($name, $params); - // Run pre-filters - $thereAreBeforeFilters = !empty($this->filters[$name][self::FILTER_BEFORE]); + return $this->runPostFilters($name, $output); + } + + /** + * @param array &$params + * + * @return $this + * @throws Exception + */ + protected function runPreFilters(string $eventName, array &$params): self + { + $thereAreBeforeFilters = !empty($this->filters[$eventName][self::FILTER_BEFORE]); if ($thereAreBeforeFilters) { - $this->filter($this->filters[$name][self::FILTER_BEFORE], $params, $output); + $this->filter($this->filters[$eventName][self::FILTER_BEFORE], $params, $output); } - // Run requested method - $requestedMethod = $this->get($name); + return $this; + } + + /** + * @param array &$params + * @param mixed &$output + * + * @return void|mixed + * @throws Exception + */ + protected function runEvent(string $eventName, array &$params) + { + $requestedMethod = $this->get($eventName); if ($requestedMethod === null) { - throw new Exception("Event '$name' isn't found."); + throw new Exception("Event '$eventName' isn't found."); } - $output = $requestedMethod(...$params); + return $requestedMethod(...$params); + } + + /** + * @param mixed &$output + * + * @return mixed + * @throws Exception + */ + protected function runPostFilters(string $eventName, &$output) + { + static $params = []; - // Run post-filters - $thereAreAfterFilters = !empty($this->filters[$name][self::FILTER_AFTER]); + $thereAreAfterFilters = !empty($this->filters[$eventName][self::FILTER_AFTER]); if ($thereAreAfterFilters) { - $this->filter($this->filters[$name][self::FILTER_AFTER], $params, $output); + $this->filter($this->filters[$eventName][self::FILTER_AFTER], $params, $output); } return $output; From 50d258a997667bae321c1470bd5768148cdf1bf3 Mon Sep 17 00:00:00 2001 From: fadrian06 Date: Thu, 8 Feb 2024 16:09:20 -0400 Subject: [PATCH 4/5] Removed unnecessary Dispatcher::tests() --- tests/DispatcherTest.php | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/tests/DispatcherTest.php b/tests/DispatcherTest.php index 6cb628d..921aa97 100644 --- a/tests/DispatcherTest.php +++ b/tests/DispatcherTest.php @@ -193,7 +193,7 @@ class DispatcherTest extends TestCase ->set('myMethod', function (): string { return 'Original'; }) - ->hook('myMethod', 'invalid', function (array &$params, $output): void { + ->hook('myMethod', 'invalid', function (array &$params, &$output): void { $output = 'Overriden'; }); @@ -216,30 +216,6 @@ class DispatcherTest extends TestCase Dispatcher::filter([$validCallable, $invalidCallable], $params, $output); } - public function testCallFunction4Params(): void - { - $myFunction = function ($param1, $param2, $param3, $param4) { - return "hello{$param1}{$param2}{$param3}{$param4}"; - }; - - $params = ['param1', 'param2', 'param3', 'param4']; - $result = Dispatcher::callFunction($myFunction, $params); - - $this->assertSame('helloparam1param2param3param4', $result); - } - - public function testCallFunction5Params(): void - { - $myFunction = function ($param1, $param2, $param3, $param4, $param5) { - return "hello{$param1}{$param2}{$param3}{$param4}{$param5}"; - }; - - $params = ['param1', 'param2', 'param3', 'param4', 'param5']; - $result = Dispatcher::callFunction($myFunction, $params); - - $this->assertSame('helloparam1param2param3param4param5', $result); - } - public function testCallFunction6Params(): void { $func = function ($param1, $param2, $param3, $param4, $param5, $param6) { From 2b6fb46f483d20e95fa9d328b85b7df45c69b191 Mon Sep 17 00:00:00 2001 From: fadrian06 Date: Thu, 8 Feb 2024 16:24:25 -0400 Subject: [PATCH 5/5] DispatcherTest 100% test coverage --- tests/DispatcherTest.php | 24 ++++++++++++++++++++++++ tests/classes/TesterClass.php | 5 +++++ 2 files changed, 29 insertions(+) diff --git a/tests/DispatcherTest.php b/tests/DispatcherTest.php index 921aa97..826c190 100644 --- a/tests/DispatcherTest.php +++ b/tests/DispatcherTest.php @@ -7,9 +7,11 @@ namespace tests; use Closure; use Exception; use flight\core\Dispatcher; +use InvalidArgumentException; use PharIo\Manifest\InvalidEmailException; use tests\classes\Hello; use PHPUnit\Framework\TestCase; +use tests\classes\TesterClass; use TypeError; class DispatcherTest extends TestCase @@ -126,6 +128,28 @@ class DispatcherTest extends TestCase Dispatcher::execute(['NonExistentClass', 'nonExistentMethod']); } + public function testInvalidCallableString(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid callback specified.'); + + Dispatcher::execute('inexistentGlobalFunction'); + } + + public function testInvalidCallbackBecauseConstructorParameters(): void + { + $class = TesterClass::class; + $method = 'instanceMethod'; + $exceptionMessage = "Method '$class::$method' cannot be called statically. "; + $exceptionMessage .= "$class::__construct require 6 parameters"; + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage($exceptionMessage); + + static $params = []; + Dispatcher::invokeMethod([$class, $method], $params); + } + // It will be useful for executing instance Controller methods statically public function testCanExecuteAnNonStaticMethodStatically(): void { diff --git a/tests/classes/TesterClass.php b/tests/classes/TesterClass.php index 0a9ecbc..289ee04 100644 --- a/tests/classes/TesterClass.php +++ b/tests/classes/TesterClass.php @@ -22,4 +22,9 @@ class TesterClass $this->param5 = $param5; $this->param6 = $param6; } + + public function instanceMethod(): void + { + $this->param2 = $this->param1; + } }