router = $this->createRouter($basePath); $this->initializeRouterMap(); } /** * Main behavior of the FrontController * * @return void */ public function run(): void { $match = $this->router->match(); if ($match != null) { $this->handleMatch($match); } else { $this->displayViewByKind(ViewHttpResponse::twig("error.html.twig", [], 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; } /** * Initialize project's routes * * @return void */ private function initializeRouterMap(): void { $this->router->map("GET", "/", "UserController"); $this->router->map("GET|POST", "/[a:action]?/[i:id]", "UserController"); $this->router->map("GET|POST", "/tactic/[a:action]/[i:idTactic]?", "UserController"); } /** * @param array $match * @return void */ private function handleMatch(array $match): void { $tag = $match['target']; $action = $this->getAction($match); $params = $match["params"]; unset($params['action']); $this->handleResponseByType($this->tryToCall($tag, $action, array_values($params))); } /** * @param string $controller * @param string $action * @param array $params * @return HttpResponse */ private function tryToCall(string $controller, string $action, array $params): HttpResponse { $controller = $this->getController($controller); if (is_callable([$controller, $action])) { return call_user_func_array([$controller, $action], $params); } else { return ViewHttpResponse::twig("error.html.twig", [], HttpCodes::NOT_FOUND); } } /** * Get the right method to call to do an action * * @param array $match * @return string */ private function getAction(array $match): string { if (isset($match["params"]["action"])) { return $match["params"]["action"]; } return "default"; } /** * Initialize the right controller by the user's role * * @param string $controller * @return mixed */ private function getController(string $controller) { $namespace = "\\App\\Controller\\"; $controller = $namespace . $controller; return new $controller(); } /** * Redirect the return by the response's type * * @param HttpResponse $response * @return void */ private function handleResponseByType(HttpResponse $response): void { http_response_code($response->getCode()); 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; } } }