diff --git a/Documentation/http.puml b/Documentation/http.puml index b41135d..9fbe606 100644 --- a/Documentation/http.puml +++ b/Documentation/http.puml @@ -35,7 +35,7 @@ class ViewHttpResponse extends HttpResponse { - arguments: array - kind: int - + __construct(kind: int, file: string, arguments: array, code: int = HttpCodes::OK) + - __construct(kind: int, file: string, arguments: array, code: int = HttpCodes::OK) + getViewKind(): int + getFile(): string + getArguments(): array diff --git a/Documentation/php.puml b/Documentation/php.puml new file mode 100644 index 0000000..8641900 --- /dev/null +++ b/Documentation/php.puml @@ -0,0 +1,8 @@ +@startuml + +class FrontController { + - router : AltoRouter + +} + +@enduml \ No newline at end of file diff --git a/public/index.php b/public/index.php index edc4cb3..f898d7f 100644 --- a/public/index.php +++ b/public/index.php @@ -4,83 +4,10 @@ require "../vendor/autoload.php"; require "../config.php"; require "../sql/database.php"; require "utils.php"; +require "../src/react-display.php"; -use App\Connexion; -use App\Controller\EditorController; -use App\Controller\SampleFormController; -use App\Gateway\FormResultGateway; -use App\Gateway\TacticInfoGateway; -use App\Http\JsonHttpResponse; -use App\Http\ViewHttpResponse; -use App\Model\TacticModel; -use Twig\Loader\FilesystemLoader; -use App\Gateway\AuthGateway; -use App\Controller\AuthController; -use App\Validation\ValidationFail; -use App\Controller\ErrorController; -use App\Controller\VisualizerController; - -$loader = new FilesystemLoader('../src/Views/'); -$twig = new \Twig\Environment($loader); +use App\Controller\FrontController; $basePath = get_public_path(); -$con = new Connexion(get_database()); - -// routes initialization -$router = new AltoRouter(); -$router->setBasePath($basePath); - -$sampleFormController = new SampleFormController(new FormResultGateway($con)); -$authGateway = new AuthGateway($con); -$authController = new \App\Controller\AuthController(new \App\Model\AuthModel($authGateway)); -$editorController = new EditorController(new TacticModel(new TacticInfoGateway($con))); -$visualizerController = new VisualizerController(new TacticModel(new TacticInfoGateway($con))); - - -$router->map("GET", "/", fn() => $sampleFormController->displayFormReact()); -$router->map("POST", "/submit", fn() => $sampleFormController->submitFormReact($_POST)); -$router->map("GET", "/twig", fn() => $sampleFormController->displayFormTwig()); -$router->map("POST", "/submit-twig", fn() => $sampleFormController->submitFormTwig($_POST)); -$router->map("GET", "/register", fn() => $authController->displayRegister()); -$router->map("POST", "/register", fn() => $authController->confirmRegister($_POST)); -$router->map("GET", "/login", fn() => $authController->displayLogin()); -$router->map("POST", "/login", fn() => $authController->confirmLogin($_POST)); -$router->map("GET", "/tactic/new", fn() => $editorController->makeNew()); -$router->map("GET", "/tactic/[i:id]/edit", fn(int $id) => $editorController->openEditorFor($id)); -$router->map("GET", "/tactic/[i:id]", fn(int $id) => $visualizerController->openVisualizer($id)); - -$match = $router->match(); - -if ($match == null) { - http_response_code(404); - ErrorController::displayFailures([ValidationFail::notFound("Cette page n'existe pas")], $twig); - return; -} - -$response = call_user_func_array($match['target'], $match['params']); - -http_response_code($response->getCode()); - -if ($response instanceof ViewHttpResponse) { - $file = $response->getFile(); - $args = $response->getArguments(); - - switch ($response->getViewKind()) { - case ViewHttpResponse::REACT_VIEW: - send_react_front($file, $args); - break; - case ViewHttpResponse::TWIG_VIEW: - try { - $twig->display($file, $args); - } catch (\Twig\Error\RuntimeError|\Twig\Error\SyntaxError $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; - } - -} elseif ($response instanceof JsonHttpResponse) { - header('Content-type: application/json'); - echo $response->getJson(); -} +$frontController = new FrontController($basePath); +$frontController->run(); diff --git a/src/Controller/EditorController.php b/src/Controller/EditorController.php index ed270d1..eb07184 100644 --- a/src/Controller/EditorController.php +++ b/src/Controller/EditorController.php @@ -2,9 +2,10 @@ namespace App\Controller; +use App\Connexion; use App\Data\TacticInfo; +use App\Gateway\TacticInfoGateway; use App\Http\HttpCodes; -use App\Http\HttpRequest; use App\Http\HttpResponse; use App\Http\JsonHttpResponse; use App\Http\ViewHttpResponse; @@ -13,18 +14,15 @@ use App\Model\TacticModel; class EditorController { private TacticModel $model; - /** - * @param TacticModel $model - */ - public function __construct(TacticModel $model) { - $this->model = $model; + public function __construct() { + $this->model = new TacticModel(new TacticInfoGateway(new Connexion(get_database()))); } private function openEditor(TacticInfo $tactic): HttpResponse { return ViewHttpResponse::react("views/Editor.tsx", ["name" => $tactic->getName(), "id" => $tactic->getId()]); } - public function makeNew(): HttpResponse { + public function create(): HttpResponse { $tactic = $this->model->makeNewDefault(); return $this->openEditor($tactic); } @@ -34,7 +32,7 @@ class EditorController { * @param int $id the targeted tactic identifier * @return HttpResponse */ - public function openEditorFor(int $id): HttpResponse { + public function edit(int $id): HttpResponse { $tactic = $this->model->get($id); if ($tactic == null) { diff --git a/src/Controller/FrontController.php b/src/Controller/FrontController.php new file mode 100644 index 0000000..66d5d4f --- /dev/null +++ b/src/Controller/FrontController.php @@ -0,0 +1,162 @@ +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", "/[a:action]?", "UserController"); + $this->router->map("GET", "/tactic/[a:action]/[i:idTactic]?", "EditorController"); + } + + /** + * @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); + try { + if (is_callable([$controller, $action])) { + return call_user_func_array([$controller, $action], $params); + } else { + return ViewHttpResponse::twig("error.html.twig", [], HttpCodes::NOT_FOUND); + } + } catch (Exception $e) { + 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; + } + } +} diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php new file mode 100644 index 0000000..930cd67 --- /dev/null +++ b/src/Controller/UserController.php @@ -0,0 +1,16 @@ + + + + + + + Document + + +

Page Home à faire

+ + \ No newline at end of file