--no-edit
continuous-integration/drone/push Build is passing Details

pull/10/head
Vivien DUFOUR 1 year ago
parent 2a3dd432ba
commit 03945892df

@ -14,6 +14,8 @@ use App\Http\JsonHttpResponse;
use App\Http\ViewHttpResponse; use App\Http\ViewHttpResponse;
use App\Model\TacticModel; use App\Model\TacticModel;
use Twig\Loader\FilesystemLoader; use Twig\Loader\FilesystemLoader;
use App\Validation\ValidationFail;
use App\Controller\ErrorController;
$loader = new FilesystemLoader('../src/Views/'); $loader = new FilesystemLoader('../src/Views/');
@ -28,7 +30,7 @@ $router->setBasePath($basePath);
$sampleFormController = new SampleFormController(new FormResultGateway($con), $twig); $sampleFormController = new SampleFormController(new FormResultGateway($con), $twig);
$editorController = new EditorController(new TacticModel(new TacticInfoGateway($con))); $editorController = new EditorController(new TacticModel(new TacticInfoGateway($con)));
$errorController = new \App\Controller\ErrorController(new FormResultGateway($con), $twig);
$router->map("GET", "/", fn() => $sampleFormController->displayFormReact()); $router->map("GET", "/", fn() => $sampleFormController->displayFormReact());
$router->map("POST", "/submit", fn() => $sampleFormController->submitFormReact($_POST)); $router->map("POST", "/submit", fn() => $sampleFormController->submitFormReact($_POST));
@ -41,8 +43,7 @@ $match = $router->match();
if ($match == null) { if ($match == null) {
http_response_code(404); http_response_code(404);
$errorController->displayError("404"); ErrorController::displayFailures([ValidationFail::notFound("Cette page n'existe pas")], $twig);
echo "Page non trouvée";
return; return;
} }

@ -6,6 +6,7 @@ use App\Http\HttpCodes;
use App\Http\HttpRequest; use App\Http\HttpRequest;
use App\Http\HttpResponse; use App\Http\HttpResponse;
use App\Http\JsonHttpResponse; use App\Http\JsonHttpResponse;
use App\Http\ViewHttpResponse;
use App\Validation\ValidationFail; use App\Validation\ValidationFail;
class Control { class Control {
@ -17,14 +18,18 @@ class Control {
* THe callback must accept an HttpRequest, and return an HttpResponse object. * THe callback must accept an HttpRequest, and return an HttpResponse object.
* @return HttpResponse * @return HttpResponse
*/ */
public static function runChecked(array $schema, callable $run): HttpResponse { public static function runChecked(array $schema, callable $run, bool $errorInJson): HttpResponse {
$request_body = file_get_contents('php://input'); $request_body = file_get_contents('php://input');
$payload_obj = json_decode($request_body); $payload_obj = json_decode($request_body);
if (!$payload_obj instanceof \stdClass) { if (!$payload_obj instanceof \stdClass) {
return new JsonHttpResponse([new ValidationFail("bad-payload", "request body is not a valid json object"), HttpCodes::BAD_REQUEST]); $fail = new ValidationFail("bad-payload", "request body is not a valid json object");
if($errorInJson) {
return new JsonHttpResponse([$fail, HttpCodes::BAD_REQUEST]);
}
return ViewHttpResponse::twig("error.html.twig", ["failures" => [$fail]], HttpCodes::BAD_REQUEST);
} }
$payload = get_object_vars($payload_obj); $payload = get_object_vars($payload_obj);
return self::runCheckedFrom($payload, $schema, $run); return self::runCheckedFrom($payload, $schema, $run, $errorInJson);
} }
/** /**
@ -35,16 +40,22 @@ class Control {
* THe callback must accept an HttpRequest, and return an HttpResponse object. * THe callback must accept an HttpRequest, and return an HttpResponse object.
* @return HttpResponse * @return HttpResponse
*/ */
public static function runCheckedFrom(array $data, array $schema, callable $run): HttpResponse { public static function runCheckedFrom(array $data, array $schema, callable $run, bool $errorInJson): HttpResponse {
$fails = []; $fails = [];
$request = HttpRequest::from($data, $fails, $schema); $request = HttpRequest::from($data, $fails, $schema);
if (!empty($fails)) { if (!empty($fails)) {
return new JsonHttpResponse($fails, HttpCodes::BAD_REQUEST); if($errorInJson) {
return new JsonHttpResponse($fails, HttpCodes::BAD_REQUEST);
}
return ViewHttpResponse::twig("error.html.twig", ['failures' => $fails], HttpCodes::BAD_REQUEST);
} }
return call_user_func_array($run, [$request]); return call_user_func_array($run, [$request]);
} }
} }

@ -3,7 +3,6 @@
namespace App\Controller; namespace App\Controller;
require_once __DIR__ . "/../react-display.php"; require_once __DIR__ . "/../react-display.php";
use App\Gateway\FormResultGateway;
use \Twig\Environment; use \Twig\Environment;
use Twig\Error\LoaderError; use Twig\Error\LoaderError;
use Twig\Error\RuntimeError; use Twig\Error\RuntimeError;
@ -11,22 +10,9 @@ use Twig\Error\SyntaxError;
class ErrorController class ErrorController
{ {
private FormResultGateway $gateway; public static function displayFailures(array $failures, Environment $twig) {
private Environment $twig;
/**
* @param FormResultGateway $gateway
*/
public function __construct(FormResultGateway $gateway, Environment $twig)
{
$this->gateway = $gateway;
$this->twig = $twig;
}
public function displayError($error) {
$error = array("error" => $error);
try { try {
echo $this->twig->render('error.html.twig', $error); $twig->display("error.html.twig", ['failures' => $failures]);
} catch (LoaderError | RuntimeError | SyntaxError $e) { } catch (LoaderError | RuntimeError | SyntaxError $e) {
echo "Twig error: $e"; echo "Twig error: $e";
} }

@ -32,14 +32,14 @@ class SampleFormController {
private function submitForm(array $form, callable $response): HttpResponse { private function submitForm(array $form, callable $response): HttpResponse {
return Control::runCheckedFrom($form, [ return Control::runCheckedFrom($form, [
"name" => [Validators::lenBetween(0, 32), Validators::name()], "name" => [Validators::lenBetween(0, 32), Validators::name("Le nom ne peut contenir que des lettres, des chiffres et des accents")],
"description" => [Validators::lenBetween(0, 512)] "description" => [Validators::lenBetween(0, 512)]
], function (HttpRequest $req) use ($response) { ], function (HttpRequest $req) use ($response) {
$description = htmlspecialchars($req["description"]); $description = htmlspecialchars($req["description"]);
$this->gateway->insert($req["name"], $description); $this->gateway->insert($req["name"], $description);
$results = ["results" => $this->gateway->listResults()]; $results = ["results" => $this->gateway->listResults()];
return call_user_func_array($response, [$results]); return call_user_func_array($response, [$results]);
}); }, false);
} }
public function submitFormTwig(array $form): HttpResponse { public function submitFormTwig(array $form): HttpResponse {

@ -14,7 +14,7 @@ class FieldValidationFail extends ValidationFail {
* @param string $message * @param string $message
*/ */
public function __construct(string $fieldName, string $message) { public function __construct(string $fieldName, string $message) {
parent::__construct("field", $message); parent::__construct("Champ invalide", $message);
$this->fieldName = $fieldName; $this->fieldName = $fieldName;
} }

@ -20,7 +20,7 @@ class Validation {
foreach ($validators as $validator) { foreach ($validators as $validator) {
$error = $validator->validate($valName, $val); $error = $validator->validate($valName, $val);
if ($error != null) { if ($error != null) {
$failures[] = $error; $failures = array_merge($failures, $error);
$had_errors = true; $had_errors = true;
} }
} }

@ -10,18 +10,18 @@ class Validators {
/** /**
* @return Validator a validator that validates a given regex * @return Validator a validator that validates a given regex
*/ */
public static function regex(string $regex): Validator { public static function regex(string $regex, string $msg = null): Validator {
return new SimpleFunctionValidator( return new SimpleFunctionValidator(
fn(string $str) => preg_match($regex, $str), fn(string $str) => preg_match($regex, $str),
fn(string $name) => [new FieldValidationFail($name, "field does not validates pattern $regex")] fn(string $name) => [new FieldValidationFail($name, $msg == null ? "field does not validates pattern $regex" : $msg)]
); );
} }
/** /**
* @return Validator a validator that validates strings that only contains numbers, letters, accents letters, `-` and `_`. * @return Validator a validator that validates strings that only contains numbers, letters, accents letters, `-` and `_`.
*/ */
public static function name(): Validator { public static function name($msg = null): Validator {
return self::regex("/^[0-9a-zA-Zà-üÀ-Ü_-]*$/"); return self::regex("/^[0-9a-zA-Zà-üÀ-Ü_-]*$/", $msg);
} }
/** /**

@ -1,10 +1,8 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Error</title> <title>Error</title>
{% block stylesheets %}
<style> <style>
body { body {
display: flex; display: flex;
@ -18,12 +16,14 @@
h1 { h1 {
color: #da6110; color: #da6110;
text-align: center; text-align: center;
margin-bottom: 15px} margin-bottom: 15px
}
h2 { h2 {
text-align: center; text-align: center;
margin-bottom: 15px; margin-bottom: 15px;
margin-top: 15px} margin-top: 15px
}
.button { .button {
display: block; display: block;
@ -41,20 +41,14 @@
background-color: #da6110 background-color: #da6110
} }
</style> </style>
{% endblock %} </head>
</head>
<body> <body>
<h1>IQBall</h1> <h1>IQBall</h1>
{% if error == "404" %} {% for fail in failures %}
<h2>Erreur 404 : cette page n'existe pas</h2> <h2>{{ fail.getKind() }} : {{ fail.getMessage() }}</h2>
{% elseif error == "401" %} {% endfor %}
<h2>Erreur 401 : vous devez vous authentifier afin d'accèder à cette page</h2>
{% elseif error == "403" %}
<h2>Erreur 403 : vous n'avez pas les autorisations nécessaires pour accèder à cette page</h2>
{% endif %}
<button class="button" onclick="location.href='/'" type="button">Retour à la page d'accueil</button> <button class="button" onclick="location.href='/'" type="button">Retour à la page d'accueil</button>

Loading…
Cancel
Save