/** * Route to the appropriate controller/method combination for a Request. * * If no custom routes were added, or a matching route is not found, the default routing behavior * is to split the path, then try to find a valid controller by successively concatenating the * parts of the path together to form namespaced classes by appending the path parts to the * ControllerNamespace until a valid Controller class is found. * * For instance, a Request for the path "/bundle/controller/action/param1/param2" would first try * to find a class called \ControllerNamespace\Bundle and failing that, would then try to find * \ControllerNamespace\Bundle\Controller and finding that is a valid class, would then call its * Action method, passing in the "param1" and "param2" as method parameters (after any MethodArgs * that might have been configured). * * @param Request $request * @param Response $response * @throws RouterException * @throws AuthenticationException */ public function Route(Request $request, Response $response) { $path = $request->PathInfo; $auth = null; foreach ($this->authTypes as $route => $authInterface) { if (strpos($path, $route) === 0) { $auth = $authInterface; if (!$auth instanceof AuthInterface) { throw new RouterException(sprintf("The authentication type specified for %s must implement AuthInterface", $request->PathInfo)); } break; } } $route = $this->getRoute($path); /** @var $controller \Fluxoft\Rebar\Controller */ $controller = new $route['controller']($request, $response, $auth); if (!is_callable([$controller, $route['action']])) { throw new RouterException(sprintf('Could not find a method called %s in %s.', $route['action'], $route['controller'])); } if (method_exists($controller, 'Setup')) { $this->callControllerMethodWithParams($controller, 'Setup', $this->SetupArgs); } try { $controller->Authorize($route['action']); } catch (AccessDeniedException $e) { $response->Halt(403, $e->getMessage()); } catch (MethodNotAllowedException $e) { $response->Halt(405, $e->getMessage()); } catch (CrossOriginException $e) { $response->Halt(403, $e->getMessage()); } // If this is an options request, and no exceptions were thrown for Authorize, // immediately return a 200 OK and do not even run the controller method. if (strtoupper($request->Method) === 'OPTIONS') { $response->Halt(200, 'OK'); } /* * Add any configured MethodArgs to the array that will be used to call the controller * method, and then any URL params that were returned. */ $actionParams = []; foreach ($this->MethodArgs as $arg) { $actionParams[] = $arg; } foreach ($route['url'] as $urlParam) { $actionParams[] = $urlParam; } $this->callControllerMethodWithParams($controller, $route['action'], $actionParams); $controller->Display(); if (method_exists($controller, 'Cleanup')) { $this->callControllerMethodWithParams($controller, 'Cleanup', $this->CleanupArgs); } }