router = $this->createRouter($basePath); $this->basePath = $basePath; } public function addRoute(string $method, string $path, Action $action): void { $this->router->map($method, $path, $action); } /** * @param MutableSessionHandle $session * @return void * @throws LoaderError * @throws RuntimeError * @throws SyntaxError */ public function run(MutableSessionHandle $session): void { $match = $this->router->match(); if ($match) { $this->handleMatch($match, $session); return; } $this->displayViewByKind(ViewHttpResponse::twig("error.html.twig", [ 'failures' => [ValidationFail::notFound("Could not find page ${_SERVER['REQUEST_URI']}.")], ], HttpCodes::NOT_FOUND)); } /** * Create a new instance of an AltoRouter * * @param string $basePath * @return AltoRouter */ public function createRouter(string $basePath): AltoRouter { $router = new AltoRouter(); $router->setBasePath($basePath); return $router; } /** * @param array $match * @param MutableSessionHandle $session * @return void */ private function handleMatch(array $match, MutableSessionHandle $session): void { $action = $match['target']; $params = array_values($match["params"]); $this->handleResponseByType($this->tryToCall($action, $params, $session)); } /** * @param Action $action * @param array $params * @param MutableSessionHandle $session * @return HttpResponse */ private function tryToCall(Action $action, array $params, MutableSessionHandle $session): HttpResponse { $account = null; if ($action->isAuthRequired()) { $account = $session->getAccount(); if ($account == null) { // put in the session the initial url the user wanted to get $session->setInitialTarget($_SERVER['REQUEST_URI']); return HttpResponse::redirect($this->basePath . "/login"); } } return $action->run($params, $session); } /** * Redirect the return by the response's type * * @param HttpResponse $response * @return void */ private function handleResponseByType(HttpResponse $response): void { http_response_code($response->getCode()); foreach ($response->getHeaders() as $header => $value) { header("$header: $value"); } if ($response instanceof ViewHttpResponse) { $this->displayViewByKind($response); } elseif ($response instanceof JsonHttpResponse) { header('Content-type: application/json'); echo $response->getJson(); } } /** * Use the right method to display the response * * @param ViewHttpResponse $response * @return void */ private function displayViewByKind(ViewHttpResponse $response): void { $file = $response->getFile(); $args = $response->getArguments(); switch ($response->getViewKind()) { case ViewHttpResponse::REACT_VIEW: send_react_front($file, $args); break; case ViewHttpResponse::TWIG_VIEW: try { $loader = new FilesystemLoader('../src/Views/'); $twig = new Environment($loader); $twig->display($file, $args); } catch (RuntimeError|SyntaxError|LoaderError $e) { http_response_code(500); echo "There was an error rendering your view, please refer to an administrator.\nlogs date: " . date("YYYD, d M Y H:i:s"); throw $e; } break; } } }