summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid T. Sadler <davidtsadler@googlemail.com>2021-10-20 20:59:55 +0100
committerDavid T. Sadler <davidtsadler@googlemail.com>2021-10-20 20:59:55 +0100
commitd4122f116c937e0ec509d8cefe540146ec27a0cd (patch)
tree481f90c4d774d32c89e612594158fe4a2d7328a4
parent1a112ab14becaf6d41cd34c176cbe563d4ca9742 (diff)
Validate fields
-rw-r--r--public/create/index.php12
-rw-r--r--public/delete/confirm/index.php1
-rw-r--r--public/delete/index.php1
-rw-r--r--public/edit/index.php12
-rw-r--r--public/index.php1
-rw-r--r--public/store/index.php18
-rw-r--r--public/update/index.php18
-rw-r--r--src/DTS/Errors.php30
-rw-r--r--src/DTS/Session.php6
-rw-r--r--src/DTS/Validated.php14
-rw-r--r--src/DTS/Validator.php81
-rw-r--r--src/templates/create.php9
-rw-r--r--src/templates/edit.php9
13 files changed, 201 insertions, 11 deletions
diff --git a/public/create/index.php b/public/create/index.php
index 00ce794..786b8f2 100644
--- a/public/create/index.php
+++ b/public/create/index.php
@@ -3,21 +3,31 @@
declare(strict_types=1);
use DTS\Bookmark;
+use DTS\Errors;
+use DTS\Session;
use DTS\Template;
+
use function DTS\Functions\respondAndExit;
require_once(__DIR__.'/../../autoload.php');
$config = require_once(__DIR__.'/../../config.php');
+$session = Session::getInstance();
+
if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'GET') {
respondAndExit(405, 'Method Not Allowed');
}
+$errors = $session->get('errors', new Errors());
+
$template = new Template($config['path_to_templates']);
$bookmark = new Bookmark();
-$html = $template->render('create', compact('bookmark'));
+$html = $template->render('create', compact(
+ 'bookmark',
+ 'errors'
+));
respondAndExit(200, 'OK', $html);
diff --git a/public/delete/confirm/index.php b/public/delete/confirm/index.php
index 6636fe9..46c70f3 100644
--- a/public/delete/confirm/index.php
+++ b/public/delete/confirm/index.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
use DTS\BookmarkRepository;
use DTS\Template;
+
use function DTS\Functions\respondAndExit;
require_once(__DIR__.'/../../../autoload.php');
diff --git a/public/delete/index.php b/public/delete/index.php
index 9864c9a..fc677f3 100644
--- a/public/delete/index.php
+++ b/public/delete/index.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
use DTS\BookmarkRepository;
use DTS\Session;
+
use function DTS\Functions\respondAndExit;
use function DTS\Functions\redirectAndExit;
diff --git a/public/edit/index.php b/public/edit/index.php
index 9d3d4c0..fba5a90 100644
--- a/public/edit/index.php
+++ b/public/edit/index.php
@@ -3,17 +3,24 @@
declare(strict_types=1);
use DTS\BookmarkRepository;
+use DTS\Errors;
+use DTS\Session;
use DTS\Template;
+
use function DTS\Functions\respondAndExit;
require_once(__DIR__.'/../../autoload.php');
$config = require_once(__DIR__.'/../../config.php');
+$session = Session::getInstance();
+
if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'GET') {
respondAndExit(405, 'Method Not Allowed');
}
+$errors = $session->get('errors', new Errors());
+
$id = filter_input(INPUT_GET, 'id');
$bookmarks = new BookmarkRepository($config['path_to_repository']);
@@ -26,6 +33,9 @@ if ($bookmark === null) {
respondAndExit(404, 'Not Found');
}
-$html = $template->render('edit', compact('bookmark'));
+$html = $template->render('edit', compact(
+ 'bookmark',
+ 'errors'
+));
respondAndExit(200, 'OK', $html);
diff --git a/public/index.php b/public/index.php
index 025c9ec..248a3ec 100644
--- a/public/index.php
+++ b/public/index.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
use DTS\BookmarkRepository;
use DTS\Session;
use DTS\Template;
+
use function DTS\Functions\respondAndExit;
require_once(__DIR__.'/../autoload.php');
diff --git a/public/store/index.php b/public/store/index.php
index 45765d5..5279e69 100644
--- a/public/store/index.php
+++ b/public/store/index.php
@@ -5,6 +5,8 @@ declare(strict_types=1);
use DTS\Bookmark;
use DTS\BookmarkRepository;
use DTS\Session;
+use DTS\Validator;
+
use function DTS\Functions\redirectAndExit;
use function DTS\Functions\respondAndExit;
@@ -18,14 +20,24 @@ if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'POST') {
respondAndExit(405, 'Method Not Allowed');
}
+$validator = new Validator($_REQUEST);
+
+if ($validator->errors->count()) {
+ $session->set('errors', $validator->errors);
+
+ redirectAndExit('/create');
+}
+
+$validated = $validator->validated;
+
$bookmarks = new BookmarkRepository($config['path_to_repository']);
$bookmark = new Bookmark();
$bookmark->id = bin2hex(random_bytes(32));
-$bookmark->url = $_POST['url'];
-$bookmark->title = $_POST['title'];
-$bookmark->tag = $_POST['tag'];
+$bookmark->url = $validated->url;
+$bookmark->title = $validated->title;
+$bookmark->tag = $validated->tag;
$bookmark->addedAt = date('Y-m-d H:i:s');
$bookmark->unread = true;
diff --git a/public/update/index.php b/public/update/index.php
index 50d0dcf..d194dbd 100644
--- a/public/update/index.php
+++ b/public/update/index.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
use DTS\BookmarkRepository;
use DTS\Session;
+use DTS\Validator;
+
use function DTS\Functions\respondAndExit;
use function DTS\Functions\redirectAndExit;
@@ -27,9 +29,19 @@ if ($bookmark === null) {
respondAndExit(404, 'Not Found');
}
-$bookmark->url = $_POST['url'];
-$bookmark->title = $_POST['title'];
-$bookmark->tag = $_POST['tag'];
+$validator = new Validator($_REQUEST);
+
+if ($validator->errors->count()) {
+ $session->set('errors', $validator->errors);
+
+ redirectAndExit("/edit?id=$bookmark->id");
+}
+
+$validated = $validator->validated;
+
+$bookmark->url = $validated->url;
+$bookmark->title = $validated->title;
+$bookmark->tag = $validated->tag;
if (!$bookmarks->update($bookmark)) {
respondAndExit(500, 'Internal Server Error');
diff --git a/src/DTS/Errors.php b/src/DTS/Errors.php
new file mode 100644
index 0000000..3c1dd5d
--- /dev/null
+++ b/src/DTS/Errors.php
@@ -0,0 +1,30 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DTS;
+
+class Errors
+{
+ private $errors = [];
+
+ public function add(string $key, string $value): void
+ {
+ $this->errors[$key][] = $value;
+ }
+
+ public function get(string $key): array
+ {
+ return $this->errors[$key];
+ }
+
+ public function has(string $key): bool
+ {
+ return array_key_exists($key, $this->errors);
+ }
+
+ public function count(): int
+ {
+ return count($this->errors);
+ }
+}
diff --git a/src/DTS/Session.php b/src/DTS/Session.php
index 956f4e5..e5da42f 100644
--- a/src/DTS/Session.php
+++ b/src/DTS/Session.php
@@ -29,13 +29,13 @@ class Session
}
}
- public function set(string $key, string $value): void
+ public function set(string $key, mixed $value): void
{
$this->session[$key] = $_SESSION[$key] = $value;
}
- public function get(string $key): ?string
+ public function get(string $key, mixed $default = null): mixed
{
- return $this->session[$key] ?? null;
+ return $this->session[$key] ?? $default;
}
}
diff --git a/src/DTS/Validated.php b/src/DTS/Validated.php
new file mode 100644
index 0000000..5df8af7
--- /dev/null
+++ b/src/DTS/Validated.php
@@ -0,0 +1,14 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DTS;
+
+class Validated
+{
+ public ?string $url;
+
+ public ?string $title;
+
+ public ?string $tag;
+}
diff --git a/src/DTS/Validator.php b/src/DTS/Validator.php
new file mode 100644
index 0000000..7629e3b
--- /dev/null
+++ b/src/DTS/Validator.php
@@ -0,0 +1,81 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DTS;
+
+use DTS\Errors;
+use DTS\Validated;
+
+class Validator
+{
+ public Errors $errors;
+
+ public Validated $validated;
+
+ function __construct(array $request) {
+ $this->errors = new Errors();
+
+ $this->validated = new Validated();
+
+ $this->validateUrl($request['url'], 8, 512);
+
+ $this->validateTitle($request['title'], 8, 256);
+
+ $this->validateTag($request['tag'], 2, 8);
+ }
+
+ private function validateUrl(string $url, int $minLength, int $maxLength): void
+ {
+ $url = trim($url);
+
+ if (filter_var($url, FILTER_VALIDATE_URL) === false) {
+ $this->errors->add('url', 'Must be a URL');
+ }
+
+ if (strlen($url) < $minLength || strlen($url) > $maxLength) {
+ $this->errors->add('url', "Must be between $minLength and $maxLength in characters in length");
+ }
+
+ if (!$this->errors->has('url')) {
+ $this->validated->url = $url;
+ }
+ }
+
+ private function validateTitle(string $title, int $minLength, int $maxLength): void
+ {
+ $title = trim($title);
+
+ if ($title === '') {
+ return;
+ }
+
+ if (strlen($title) < $minLength || strlen($title) > $maxLength) {
+ $this->errors->add('title', "Must be between $minLength and $maxLength in characters in length");
+ }
+
+ if (!$this->errors->has('tite')) {
+ $this->validated->title = $title;
+ }
+ }
+
+ private function validateTag(string $tag, int $minLength, int $maxLength): void
+ {
+ $tag = trim($tag);
+
+ if ($tag === '') {
+ return;
+ }
+
+ if (strlen($tag) < $minLength || strlen($tag) > $maxLength) {
+ $this->errors->add('tag', "Must be between $minLength and $maxLength in characters in length");
+ }
+ if (preg_match('/\W/', $tag) === 1) {
+ $this->errors->add('tag', 'May only contain word characters');
+ }
+
+ if (!$this->errors->has('tag')) {
+ $this->validated->tag = strtolower($tag);
+ }
+ }
+}
diff --git a/src/templates/create.php b/src/templates/create.php
index 483e49e..2769290 100644
--- a/src/templates/create.php
+++ b/src/templates/create.php
@@ -9,8 +9,17 @@
<a href="/">Back</a>
<form action="/store" method="POST">
<input type="text" name="url" maxlength="512" autofocus><br>
+ <?php if ($errors->has('url')) { ?>
+ <p><?php echo implode(', ', $errors->get('url')); ?></p>
+ <?php } ?>
<input type="text" name="title" maxlength="256" ><br>
+ <?php if ($errors->has('title')) { ?>
+ <p><?php echo implode(', ', $errors->get('title')); ?></p>
+ <?php } ?>
<input type="text" name="tag" maxlength="8" ><br>
+ <?php if ($errors->has('tag')) { ?>
+ <p><?php echo implode(', ', $errors->get('tag')); ?></p>
+ <?php } ?>
<button type="submit">Add</button>
</form>
</body>
diff --git a/src/templates/edit.php b/src/templates/edit.php
index d5f5a08..c1b7bda 100644
--- a/src/templates/edit.php
+++ b/src/templates/edit.php
@@ -10,8 +10,17 @@
<form action="/update" method="POST">
<input type="hidden" name="id" value="<?php echo $bookmark->id; ?>"/>
<input type="text" name="url" maxlength="512" autofocus value="<?php echo $bookmark->url; ?>"><br>
+ <?php if ($errors->has('url')) { ?>
+ <p><?php echo implode(', ', $errors->get('url')); ?></p>
+ <?php } ?>
<input type="text" name="title" maxlength="256" value="<?php echo $bookmark->title; ?>"><br>
+ <?php if ($errors->has('title')) { ?>
+ <p><?php echo implode(', ', $errors->get('title')); ?></p>
+ <?php } ?>
<input type="text" name="tag" maxlength="8" value="<?php echo $bookmark->tag; ?>"><br>
+ <?php if ($errors->has('tag')) { ?>
+ <p><?php echo implode(', ', $errors->get('tag')); ?></p>
+ <?php } ?>
<button type="submit">Update</button>
</form>
</body>