error-view #10

Merged
vivien.dufour merged 10 commits from error-view into master 1 year ago

@ -14,6 +14,8 @@ use App\Http\JsonHttpResponse;
use App\Http\ViewHttpResponse;
use App\Model\TacticModel;
use Twig\Loader\FilesystemLoader;
use App\Validation\ValidationFail;
use App\Controller\ErrorController;
$loader = new FilesystemLoader('../src/Views/');
@ -29,6 +31,7 @@ $router->setBasePath($basePath);
$sampleFormController = new SampleFormController(new FormResultGateway($con), $twig);
$editorController = new EditorController(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());
@ -39,9 +42,8 @@ $router->map("GET", "/tactic/[i:id]/edit", fn(int $id) => $editorController->ope
$match = $router->match();
if ($match == null) {
// TODO redirect to a 404 not found page instead (issue #1)
http_response_code(404);
echo "Page non trouvée";
ErrorController::displayFailures([ValidationFail::notFound("Cette page n'existe pas")], $twig);
return;
}

@ -6,6 +6,7 @@ use App\Http\HttpCodes;
use App\Http\HttpRequest;
use App\Http\HttpResponse;
use App\Http\JsonHttpResponse;
use App\Http\ViewHttpResponse;
use App\Validation\ValidationFail;
class Control {
@ -17,14 +18,18 @@ class Control {
* THe callback must accept an HttpRequest, and return an HttpResponse object.
* @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');
$payload_obj = json_decode($request_body);
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);
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.
* @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 = [];
$request = HttpRequest::from($data, $fails, $schema);
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]);
}
}

@ -0,0 +1,20 @@
<?php
namespace App\Controller;
require_once __DIR__ . "/../react-display.php";
use \Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
class ErrorController
{
public static function displayFailures(array $failures, Environment $twig) {
try {
vivien.dufour marked this conversation as resolved
Review

why use a gateway in something that only displays an error view ?
Moreover, it is not used anywhere in the class, you should remove it

why use a gateway in something that only displays an error view ? Moreover, it is not used anywhere in the class, you should remove it
$twig->display("error.html.twig", ['failures' => $failures]);
} catch (LoaderError | RuntimeError | SyntaxError $e) {
echo "Twig error: $e";
}
}
}
vivien.dufour marked this conversation as resolved
Review

Remove the constructor, the $twig will be passed to the displayError function directly, and made static.

Remove the constructor, the `$twig` will be passed to the displayError function directly, and made static.

@ -32,14 +32,14 @@ class SampleFormController {
private function submitForm(array $form, callable $response): HttpResponse {
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)]
], function (HttpRequest $req) use ($response) {
$description = htmlspecialchars($req["description"]);
$this->gateway->insert($req["name"], $description);
$results = ["results" => $this->gateway->listResults()];
return call_user_func_array($response, [$results]);
});
}, false);
}
public function submitFormTwig(array $form): HttpResponse {

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

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

@ -10,18 +10,18 @@ class Validators {
/**
* @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(
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 `_`.
*/
public static function name(): Validator {
return self::regex("/^[0-9a-zA-Zà-üÀ-Ü_-]*$/");
public static function name($msg = null): Validator {
return self::regex("/^[0-9a-zA-Zà-üÀ-Ü_-]*$/", $msg);
}
/**

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Error</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
}
h1 {
color: #da6110;
text-align: center;
margin-bottom: 15px
}
vivien.dufour marked this conversation as resolved
Review
-  		margin-top: 15px}
+		margin-top: 15px
+	}
```diff - margin-top: 15px} + margin-top: 15px + } ```
h2 {
text-align: center;
margin-bottom: 15px;
margin-top: 15px
}
.button {
display: block;
cursor : pointer;
background-color: white;
color : black;
text-align: center;
font-size: 20px;
border-radius: 12px;
border : 2px solid #da6110;
margin-top: 15px;
}
.button:hover {
background-color: #da6110
}
</style>
</head>
<body>
<h1>IQBall</h1>
{% for fail in failures %}
<h2>{{ fail.getKind() }} : {{ fail.getMessage() }}</h2>
{% endfor %}
<button class="button" onclick="location.href='/'" type="button">Retour à la page d'accueil</button>
</body>
</html>
vivien.dufour marked this conversation as resolved
Review

This is not easily extensible, if we want to add more error codes and/or message, we will need to modify this file.
You can simply do something like that :

- {% if error == "404" %}
-     <h2>Erreur 404 : cette page n'existe pas</h2>
- {% elseif error == "401" %}
-     <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 %}
+ <h2>{{ error_type }} : {{ error_message }} </h2>

You'll then need to pass those two new variables to the view's argument :

$twig->display("error.html.twig", ["error_type" => $error_type, "error_message" => $error_message])
This is not easily extensible, if we want to add more error codes and/or message, we will need to modify this file. You can simply do something like that : ```diff - {% if error == "404" %} - <h2>Erreur 404 : cette page n'existe pas</h2> - {% elseif error == "401" %} - <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 %} + <h2>{{ error_type }} : {{ error_message }} </h2> ``` You'll then need to pass those two new variables to the view's argument : ```php $twig->display("error.html.twig", ["error_type" => $error_type, "error_message" => $error_message]) ```
Loading…
Cancel
Save