/** * @param Request $request * @param Response $response * @param callable $next * @return Response */ public function __invoke(Request $request, Response $response, callable $next) { $dispatcher = new Dispatcher($this->collector->getData()); $result = $dispatcher->dispatch($request->getMethod(), $request->getUri()->getPath()); $code = $result[0]; if ($code != Dispatcher::FOUND) { return $next($request, $response); } /** @var Route $route */ $route = $result[1]; $params = $result[2]; $request = $request->withAttribute('params', $params)->withAttribute('route', $route); // set the route map match $this->routeMap->setRouteMatch($route); foreach ($params as $key => $value) { $request[$key] = $value; } // Custom middleware handler. // We have to iterate through middleware as it was added so that they retain the proper ordering. // We have to check if the middleware is a route and if it was the route matched during dispatching. // If so, we can call the route handler, otherwise, we need to skip over it. $middleware = $this->middleware; $callable = function ($request, $response) use(&$callable, &$middleware, $route, $next) { /** @var callable $layer */ $layer = array_shift($middleware); if ($layer instanceof Route) { if ($layer !== $route) { return $callable($request, $response, $next); } $layer = $this->resolver->resolve($route->getHandler()); return $layer($request, $response); } return $layer($request, $response, $callable); }; return $callable($request, $response); }