diff options
Diffstat (limited to 'src/Router.php')
-rw-r--r-- | src/Router.php | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/src/Router.php b/src/Router.php index 5cc2108..7a4f5c8 100644 --- a/src/Router.php +++ b/src/Router.php @@ -94,22 +94,62 @@ class Router } /** - * Add middleware call to router + * Add middleware call to router. * - * @param callback $middleware + * @param string $path Middleware is only applied for this path (including subdirectories), may be omitted + * @param callable $middleware * @return Router $this */ - public function add($middleware) + public function add($path, $middleware = null) { + if (!isset($middleware)) { + $middleware = $path; + $path = null; + } + + if (!empty($path) && !ctype_digit($path) && $path[0] !== '/') { + trigger_error("Middleware path '$path' doesn't start with a '/'", E_USER_NOTICE); + } + if (!is_callable($middleware)) { throw new \InvalidArgumentException("Middleware should be callable"); } + if (!empty($path)) { + $middleware = $this->wrapMiddleware($path, $middleware); + } + $this->middlewares[] = $middleware; - + return $this; } + /** + * Wrap middleware, so it's only applied to a specified path + * + * @param string $path + * @param callable $middleware + * @return callable + */ + protected function wrapMiddleware($path, $middleware) + { + return function( + ServerRequestInterface $request, + ResponseInterface $response, + $next + ) use ($middleware, $path) { + $uriPath = $request->getUri()->getPath(); + + if ($uriPath === $path || strpos($uriPath, rtrim($path, '/') . '/') === 0) { + $ret = $middleware($request, $response, $next); + } else { + $ret = $next($request, $response); + } + + return $ret; + }; + } + /** * Run the action for the request @@ -137,7 +177,7 @@ class Router return $this->run($request, $response, $next); } - $stack = array_merge([[$this, 'run']], $this->middlewares); + $stack = array_reverse(array_merge($this->middlewares, [[$this, 'run']])); // Turn the stack into a call chain foreach ($stack as $handle) { |