You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Application-Web/src/Controller/FrontController.php

170 lines
4.7 KiB

<?php
namespace App\Controller;
use AltoRouter;
use App\Http\HttpCodes;
use App\Http\HttpResponse;
use App\Http\JsonHttpResponse;
use App\Http\ViewHttpResponse;
use Exception;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Twig\Loader\FilesystemLoader;
class FrontController
{
private AltoRouter $router;
public function __construct(string $basePath)
{
$this->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<string, mixed> $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<int, mixed> $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<string, mixed> $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;
}
}
}