diff --git a/flight/Engine.php b/flight/Engine.php index cacd19e..4f0f60a 100644 --- a/flight/Engine.php +++ b/flight/Engine.php @@ -35,7 +35,7 @@ use flight\net\Route; * * Routing * @method Route route(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') Routes a URL to a callback function with all applicable methods - * @method void group(string $pattern, callable $callback) Groups a set of routes together under a common prefix. + * @method void group(string $pattern, callable $callback, array $group_middlewares = []) Groups a set of routes together under a common prefix. * @method Route post(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') Routes a POST URL to a callback function. * @method Route put(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') Routes a PUT URL to a callback function. * @method Route patch(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') Routes a PATCH URL to a callback function. @@ -397,10 +397,7 @@ class Engine } // It's assumed if you don't declare before, that it will be assumed as the before method - $middleware_result = $this->dispatcher->execute( - $middleware_object, - $params - ); + $middleware_result = $middleware_object($route->params); if ($middleware_result === false) { $failed_middleware_check = true; @@ -430,10 +427,8 @@ class Engine continue; } - $middleware_result = $this->dispatcher->execute( - $middleware_object, - $params - ); + $middleware_result = $middleware_object($route->params); + if ($middleware_result === false) { $failed_middleware_check = true; break 2; @@ -528,12 +523,13 @@ class Engine /** * Routes a URL to a callback function. * - * @param string $pattern URL pattern to match - * @param callable $callback Callback function that includes the Router class as first parameter + * @param string $pattern URL pattern to match + * @param callable $callback Callback function that includes the Router class as first parameter + * @param array $group_middlewares The middleware to be applied to the route */ - public function _group(string $pattern, callable $callback): void + public function _group(string $pattern, callable $callback, array $group_middlewares = []): void { - $this->router()->group($pattern, $callback); + $this->router()->group($pattern, $callback, $group_middlewares); } /** diff --git a/flight/Flight.php b/flight/Flight.php index c5b61e0..a24a8f3 100644 --- a/flight/Flight.php +++ b/flight/Flight.php @@ -25,7 +25,7 @@ use flight\net\Route; * @method static void halt(int $code = 200, string $message = '') Stop the framework with an optional status code and message. * * @method static Route route(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') Maps a URL pattern to a callback with all applicable methods. - * @method static void group(string $pattern, callable $callback) Groups a set of routes together under a common prefix. + * @method static void group(string $pattern, callable $callback, array $group_middlewares = []) Groups a set of routes together under a common prefix. * @method static Route post(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') Routes a POST URL to a callback function. * @method static Route put(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') Routes a PUT URL to a callback function. * @method static Route patch(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') Routes a PATCH URL to a callback function. diff --git a/flight/core/Dispatcher.php b/flight/core/Dispatcher.php index 4ce6854..e31d3f9 100644 --- a/flight/core/Dispatcher.php +++ b/flight/core/Dispatcher.php @@ -53,7 +53,8 @@ class Dispatcher } // Run requested method - $output = self::execute($this->get($name), $params); + $callback = $this->get($name); + $output = $callback(...$params); // Run post-filters if (!empty($this->filters[$name]['after'])) { @@ -140,7 +141,7 @@ class Dispatcher { $args = [&$params, &$output]; foreach ($filters as $callback) { - $continue = self::execute($callback, $args); + $continue = $callback(...$args); if (false === $continue) { break; } @@ -178,27 +179,7 @@ class Dispatcher */ public static function callFunction($func, array &$params = []) { - // Call static method - if (\is_string($func) && false !== strpos($func, '::')) { - return \call_user_func_array($func, $params); - } - - switch (\count($params)) { - case 0: - return $func(); - case 1: - return $func($params[0]); - case 2: - return $func($params[0], $params[1]); - case 3: - return $func($params[0], $params[1], $params[2]); - case 4: - return $func($params[0], $params[1], $params[2], $params[3]); - case 5: - return $func($params[0], $params[1], $params[2], $params[3], $params[4]); - default: - return \call_user_func_array($func, $params); - } + return call_user_func_array($func, $params); } /** @@ -215,37 +196,9 @@ class Dispatcher $instance = \is_object($class); - switch (\count($params)) { - case 0: - return ($instance) ? - $class->$method() : - $class::$method(); - case 1: - return ($instance) ? - $class->$method($params[0]) : - $class::$method($params[0]); - case 2: - return ($instance) ? - $class->$method($params[0], $params[1]) : - $class::$method($params[0], $params[1]); - case 3: - return ($instance) ? - $class->$method($params[0], $params[1], $params[2]) : - $class::$method($params[0], $params[1], $params[2]); - // This will be refactored soon enough - // @codeCoverageIgnoreStart - case 4: - return ($instance) ? - $class->$method($params[0], $params[1], $params[2], $params[3]) : - $class::$method($params[0], $params[1], $params[2], $params[3]); - case 5: - return ($instance) ? - $class->$method($params[0], $params[1], $params[2], $params[3], $params[4]) : - $class::$method($params[0], $params[1], $params[2], $params[3], $params[4]); - default: - return \call_user_func_array($func, $params); - // @codeCoverageIgnoreEnd - } + return ($instance) ? + $class->$method(...$params) : + $class::$method(); } /** diff --git a/flight/core/Loader.php b/flight/core/Loader.php index d262e74..0a64fb6 100644 --- a/flight/core/Loader.php +++ b/flight/core/Loader.php @@ -136,30 +136,7 @@ class Loader return \call_user_func_array($class, $params); } - switch (\count($params)) { - case 0: - return new $class(); - case 1: - return new $class($params[0]); - // @codeCoverageIgnoreStart - case 2: - return new $class($params[0], $params[1]); - case 3: - return new $class($params[0], $params[1], $params[2]); - case 4: - return new $class($params[0], $params[1], $params[2], $params[3]); - case 5: - return new $class($params[0], $params[1], $params[2], $params[3], $params[4]); - // @codeCoverageIgnoreEnd - default: - try { - $refClass = new ReflectionClass($class); - - return $refClass->newInstanceArgs($params); - } catch (ReflectionException $e) { - throw new Exception("Cannot instantiate {$class}", 0, $e); - } - } + return new $class(...$params); } /** diff --git a/tests/EngineTest.php b/tests/EngineTest.php index 8c0697e..62fbf70 100644 --- a/tests/EngineTest.php +++ b/tests/EngineTest.php @@ -276,7 +276,7 @@ class EngineTest extends PHPUnit\Framework\TestCase public function testMiddlewareCallableFunction() { $engine = new Engine(); $engine->route('/path1/@id', function($id) { echo 'OK'.$id; }) - ->addMiddleware(function($id) { echo 'before'.$id; }); + ->addMiddleware(function($params) { echo 'before'.$params['id']; }); $engine->request()->url = '/path1/123'; $engine->start(); $this->expectOutputString('before123OK123'); @@ -291,7 +291,7 @@ class EngineTest extends PHPUnit\Framework\TestCase } }; $engine->route('/path1/@id', function($id) { echo 'OK'.$id; }) - ->addMiddleware(function($id) { echo 'before'.$id; return false; }); + ->addMiddleware(function($params) { echo 'before'.$params['id']; return false; }); $engine->request()->url = '/path1/123'; $engine->start(); $this->expectOutputString('Forbiddenbefore123'); @@ -300,8 +300,8 @@ class EngineTest extends PHPUnit\Framework\TestCase public function testMiddlewareClassBefore() { $middleware = new class { - public function before($id) { - echo 'before'.$id; + public function before($params) { + echo 'before'.$params['id']; } }; $engine = new Engine(); @@ -315,11 +315,11 @@ class EngineTest extends PHPUnit\Framework\TestCase public function testMiddlewareClassBeforeAndAfter() { $middleware = new class { - public function before($id) { - echo 'before'.$id; + public function before($params) { + echo 'before'.$params['id']; } - public function after($id) { - echo 'after'.$id; + public function after($params) { + echo 'after'.$params['id']; } }; $engine = new Engine(); @@ -333,8 +333,9 @@ class EngineTest extends PHPUnit\Framework\TestCase public function testMiddlewareClassAfter() { $middleware = new class { - public function after($id) { - echo 'after'.$id; + public function after($params) { + + echo 'after'.$params['id']; } }; $engine = new Engine(); @@ -345,4 +346,91 @@ class EngineTest extends PHPUnit\Framework\TestCase $engine->start(); $this->expectOutputString('OK123after123'); } + + public function testMiddlewareClassAfterFailedCheck() { + $middleware = new class { + public function after($params) { + echo 'after'.$params['id']; + return false; + } + }; + $engine = new class extends Engine { + public function _halt(int $code = 200, string $message = ''): void + { + $this->response()->status($code); + $this->response()->write($message); + } + }; + + $engine->route('/path1/@id', function($id) { echo 'OK'.$id; }) + ->addMiddleware($middleware); + $engine->request()->url = '/path1/123'; + $engine->start(); + $this->assertEquals(403, $engine->response()->status()); + $this->expectOutputString('ForbiddenOK123after123'); + } + + public function testMiddlewareCallableFunctionMultiple() { + $engine = new Engine(); + $engine->route('/path1/@id', function($id) { echo 'OK'.$id; }) + ->addMiddleware(function($params) { echo 'before1'.$params['id']; }) + ->addMiddleware(function($params) { echo 'before2'.$params['id']; }); + $engine->request()->url = '/path1/123'; + $engine->start(); + $this->expectOutputString('before1123before2123OK123'); + } + + // Pay attention to the order on how the middleware is executed in this test. + public function testMiddlewareClassCallableRouteMultiple() { + $middleware = new class { + public function before($params) { + echo 'before'.$params['another_id']; + } + public function after($params) { + echo 'after'.$params['id']; + } + }; + $middleware2 = new class { + public function before($params) { + echo 'before'.$params['id']; + } + public function after($params) { + echo 'after'.$params['id'].$params['another_id']; + } + }; + $engine = new Engine(); + $engine->route('/path1/@id/subpath1/@another_id', function() { echo 'OK'; })->addMiddleware([ $middleware, $middleware2 ]); + + $engine->request()->url = '/path1/123/subpath1/456'; + $engine->start(); + $this->expectOutputString('before456before123OKafter123456after123'); + } + + public function testMiddlewareClassGroupRouteMultipleBooyah() { + $middleware = new class { + public function before($params) { + echo 'before'.$params['another_id']; + } + public function after($params) { + echo 'after'.$params['id']; + } + }; + $middleware2 = new class { + public function before($params) { + echo 'before'.$params['id']; + } + public function after($params) { + echo 'after'.$params['id'].$params['another_id']; + } + }; + $engine = new Engine(); + $engine->group('/path1/@id', function($router) { + $router->map('/subpath1/@another_id', function() { echo 'OK'; }); + $router->map('/@cool_id', function() { echo 'OK'; }); + }, [ $middleware, $middleware2 ]); + + $engine->request()->url = '/path1/123/subpath1/456'; + $engine->start(); + $this->expectOutputString('before456before123OKafter123456after123'); + } } diff --git a/tests/LoaderTest.php b/tests/LoaderTest.php index ecadd0a..6c89a82 100644 --- a/tests/LoaderTest.php +++ b/tests/LoaderTest.php @@ -138,12 +138,6 @@ class LoaderTest extends PHPUnit\Framework\TestCase $this->assertEquals('Suzie', $TesterClass->param6); } - public function testNewInstance6ParamsBadClass() { - $this->expectException(Exception::class); - $this->expectExceptionMessage('Cannot instantiate BadClass'); - $TesterClass = $this->loader->newInstance('BadClass', ['Bob','Fred', 'Joe', 'Jane', 'Sally', 'Suzie']); - } - public function testAddDirectoryAsArray() { $loader = new class extends Loader { public function getDirectories() { diff --git a/tests/RouterTest.php b/tests/RouterTest.php index 6125f53..9fa77f2 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -298,6 +298,18 @@ class RouterTest extends PHPUnit\Framework\TestCase $this->check(); } + public function testRouteBeingReturned() { + $route = $this->router->map('/hi', function() {}); + $route_in_router = $this->router->getRoutes()[0]; + $this->assertSame($route, $route_in_router); + } + + public function testRouteSetAlias() { + $route = $this->router->map('/hi', function() {}); + $route->setAlias('hello'); + $this->assertEquals('hello', $route->alias); + } + // Test splat public function testSplatWildcard() {