From 26ecbe68c53c639020a40913efbdcef02e60faf5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:11:24 +0200
Subject: [PATCH 01/11] feat(validation): install beberlai/assert

---
 composer.json |   3 +-
 composer.lock | 418 ++++++++++++++++++++++++++++++++------------------
 2 files changed, 270 insertions(+), 151 deletions(-)

diff --git a/composer.json b/composer.json
index ab22d27..e3ca3c6 100755
--- a/composer.json
+++ b/composer.json
@@ -24,7 +24,8 @@
     "psr/http-message": "^1.0",
     "psr/simple-cache": "^1.0",
     "ext-pdo": "*",
-    "psr/http-server-handler": "^1.0"
+    "psr/http-server-handler": "^1.0",
+    "beberlei/assert": "^3.3"
   },
   "require-dev": {
     "pestphp/pest": "^1.0",
diff --git a/composer.lock b/composer.lock
index cb04663..53e27fe 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,75 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "3c442e38a813291bbfc8487c35087244",
+    "content-hash": "63e64e9b09f424ec9984b300c65f7033",
     "packages": [
+        {
+            "name": "beberlei/assert",
+            "version": "v3.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/beberlei/assert.git",
+                "reference": "5e721d7e937ca3ba2cdec1e1adf195f9e5188372"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/beberlei/assert/zipball/5e721d7e937ca3ba2cdec1e1adf195f9e5188372",
+                "reference": "5e721d7e937ca3ba2cdec1e1adf195f9e5188372",
+                "shasum": ""
+            },
+            "require": {
+                "ext-ctype": "*",
+                "ext-json": "*",
+                "ext-mbstring": "*",
+                "ext-simplexml": "*",
+                "php": "^7.0 || ^8.0"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "*",
+                "phpstan/phpstan": "*",
+                "phpunit/phpunit": ">=6.0.0",
+                "yoast/phpunit-polyfills": "^0.1.0"
+            },
+            "suggest": {
+                "ext-intl": "Needed to allow Assertion::count(), Assertion::isCountable(), Assertion::minCount(), and Assertion::maxCount() to operate on ResourceBundles"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Assert\\": "lib/Assert"
+                },
+                "files": [
+                    "lib/Assert/functions.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de",
+                    "role": "Lead Developer"
+                },
+                {
+                    "name": "Richard Quadling",
+                    "email": "rquadling@gmail.com",
+                    "role": "Collaborator"
+                }
+            ],
+            "description": "Thin assertion library for input validation in business models.",
+            "keywords": [
+                "assert",
+                "assertion",
+                "validation"
+            ],
+            "support": {
+                "issues": "https://github.com/beberlei/assert/issues",
+                "source": "https://github.com/beberlei/assert/tree/v3.3.1"
+            },
+            "time": "2021-04-18T20:11:03+00:00"
+        },
         {
             "name": "psr/http-message",
             "version": "1.0.1",
@@ -171,16 +238,16 @@
     "packages-dev": [
         {
             "name": "composer/semver",
-            "version": "3.2.4",
+            "version": "3.2.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/semver.git",
-                "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464"
+                "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/semver/zipball/a02fdf930a3c1c3ed3a49b5f63859c0c20e10464",
-                "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464",
+                "url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9",
+                "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9",
                 "shasum": ""
             },
             "require": {
@@ -232,7 +299,7 @@
             "support": {
                 "irc": "irc://irc.freenode.org/composer",
                 "issues": "https://github.com/composer/semver/issues",
-                "source": "https://github.com/composer/semver/tree/3.2.4"
+                "source": "https://github.com/composer/semver/tree/3.2.5"
             },
             "funding": [
                 {
@@ -248,20 +315,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2020-11-13T08:59:24+00:00"
+            "time": "2021-05-24T12:41:47+00:00"
         },
         {
             "name": "composer/xdebug-handler",
-            "version": "2.0.0",
+            "version": "2.0.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/xdebug-handler.git",
-                "reference": "31d57697eb1971712a08031cfaff5a846d10bdf5"
+                "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/31d57697eb1971712a08031cfaff5a846d10bdf5",
-                "reference": "31d57697eb1971712a08031cfaff5a846d10bdf5",
+                "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/964adcdd3a28bf9ed5d9ac6450064e0d71ed7496",
+                "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496",
                 "shasum": ""
             },
             "require": {
@@ -296,7 +363,7 @@
             "support": {
                 "irc": "irc://irc.freenode.org/composer",
                 "issues": "https://github.com/composer/xdebug-handler/issues",
-                "source": "https://github.com/composer/xdebug-handler/tree/2.0.0"
+                "source": "https://github.com/composer/xdebug-handler/tree/2.0.1"
             },
             "funding": [
                 {
@@ -312,32 +379,34 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-04-09T19:40:06+00:00"
+            "time": "2021-05-05T19:37:51+00:00"
         },
         {
             "name": "doctrine/annotations",
-            "version": "1.12.1",
+            "version": "1.13.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/annotations.git",
-                "reference": "b17c5014ef81d212ac539f07a1001832df1b6d3b"
+                "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/annotations/zipball/b17c5014ef81d212ac539f07a1001832df1b6d3b",
-                "reference": "b17c5014ef81d212ac539f07a1001832df1b6d3b",
+                "url": "https://api.github.com/repos/doctrine/annotations/zipball/e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f",
+                "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f",
                 "shasum": ""
             },
             "require": {
                 "doctrine/lexer": "1.*",
                 "ext-tokenizer": "*",
-                "php": "^7.1 || ^8.0"
+                "php": "^7.1 || ^8.0",
+                "psr/cache": "^1 || ^2 || ^3"
             },
             "require-dev": {
-                "doctrine/cache": "1.*",
+                "doctrine/cache": "^1.11 || ^2.0",
                 "doctrine/coding-standard": "^6.0 || ^8.1",
                 "phpstan/phpstan": "^0.12.20",
-                "phpunit/phpunit": "^7.5 || ^9.1.5"
+                "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5",
+                "symfony/cache": "^4.4 || ^5.2"
             },
             "type": "library",
             "autoload": {
@@ -380,9 +449,9 @@
             ],
             "support": {
                 "issues": "https://github.com/doctrine/annotations/issues",
-                "source": "https://github.com/doctrine/annotations/tree/1.12.1"
+                "source": "https://github.com/doctrine/annotations/tree/1.13.1"
             },
-            "time": "2021-02-21T21:00:45+00:00"
+            "time": "2021-05-16T18:07:53+00:00"
         },
         {
             "name": "doctrine/instantiator",
@@ -1224,16 +1293,16 @@
         },
         {
             "name": "pestphp/pest",
-            "version": "v1.1.0",
+            "version": "v1.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/pestphp/pest.git",
-                "reference": "c6a2e3b4d0eb129ad8eab2d6c8603a5e6c68f12b"
+                "reference": "9133b88d6550023207fef892bef5f38dc07e6b30"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/pestphp/pest/zipball/c6a2e3b4d0eb129ad8eab2d6c8603a5e6c68f12b",
-                "reference": "c6a2e3b4d0eb129ad8eab2d6c8603a5e6c68f12b",
+                "url": "https://api.github.com/repos/pestphp/pest/zipball/9133b88d6550023207fef892bef5f38dc07e6b30",
+                "reference": "9133b88d6550023207fef892bef5f38dc07e6b30",
                 "shasum": ""
             },
             "require": {
@@ -1249,7 +1318,6 @@
                 "illuminate/console": "^8.32.1",
                 "illuminate/support": "^8.32.1",
                 "laravel/dusk": "^6.13.0",
-                "mockery/mockery": "^1.4.3",
                 "pestphp/pest-dev-tools": "dev-master"
             },
             "bin": [
@@ -1301,7 +1369,7 @@
             ],
             "support": {
                 "issues": "https://github.com/pestphp/pest/issues",
-                "source": "https://github.com/pestphp/pest/tree/v1.1.0"
+                "source": "https://github.com/pestphp/pest/tree/v1.3.0"
             },
             "funding": [
                 {
@@ -1329,7 +1397,7 @@
                     "type": "patreon"
                 }
             ],
-            "time": "2021-05-02T22:41:59+00:00"
+            "time": "2021-05-23T21:06:11+00:00"
         },
         {
             "name": "pestphp/pest-plugin",
@@ -1481,16 +1549,16 @@
         },
         {
             "name": "pestphp/pest-plugin-expectations",
-            "version": "v1.0.1",
+            "version": "v1.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/pestphp/pest-plugin-expectations.git",
-                "reference": "e543acd6d0ca33c9bdaae05d4dffbfc8c66a0285"
+                "reference": "4c27ae98979a082200797657432c81be3cf0706b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/pestphp/pest-plugin-expectations/zipball/e543acd6d0ca33c9bdaae05d4dffbfc8c66a0285",
-                "reference": "e543acd6d0ca33c9bdaae05d4dffbfc8c66a0285",
+                "url": "https://api.github.com/repos/pestphp/pest-plugin-expectations/zipball/4c27ae98979a082200797657432c81be3cf0706b",
+                "reference": "4c27ae98979a082200797657432c81be3cf0706b",
                 "shasum": ""
             },
             "require": {
@@ -1533,7 +1601,7 @@
                 "unit"
             ],
             "support": {
-                "source": "https://github.com/pestphp/pest-plugin-expectations/tree/v1.0.1"
+                "source": "https://github.com/pestphp/pest-plugin-expectations/tree/v1.3.0"
             },
             "funding": [
                 {
@@ -1549,20 +1617,20 @@
                     "type": "patreon"
                 }
             ],
-            "time": "2021-01-03T16:02:34+00:00"
+            "time": "2021-05-29T22:52:12+00:00"
         },
         {
             "name": "pestphp/pest-plugin-init",
-            "version": "v1.0.0",
+            "version": "v1.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/pestphp/pest-plugin-init.git",
-                "reference": "bd6fdb058ba5dc7a9f7f3645ad4e0bdc34cf0026"
+                "reference": "cb3dfa1a9887aafb3d0b4db0fb8f6171ce69b49e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/pestphp/pest-plugin-init/zipball/bd6fdb058ba5dc7a9f7f3645ad4e0bdc34cf0026",
-                "reference": "bd6fdb058ba5dc7a9f7f3645ad4e0bdc34cf0026",
+                "url": "https://api.github.com/repos/pestphp/pest-plugin-init/zipball/cb3dfa1a9887aafb3d0b4db0fb8f6171ce69b49e",
+                "reference": "cb3dfa1a9887aafb3d0b4db0fb8f6171ce69b49e",
                 "shasum": ""
             },
             "require": {
@@ -1608,7 +1676,7 @@
                 "unit"
             ],
             "support": {
-                "source": "https://github.com/pestphp/pest-plugin-init/tree/v1.0.0"
+                "source": "https://github.com/pestphp/pest-plugin-init/tree/v1.1.0"
             },
             "funding": [
                 {
@@ -1624,7 +1692,7 @@
                     "type": "patreon"
                 }
             ],
-            "time": "2021-01-03T15:47:48+00:00"
+            "time": "2021-05-10T16:31:00+00:00"
         },
         {
             "name": "phar-io/manifest",
@@ -2016,16 +2084,16 @@
         },
         {
             "name": "phpstan/phpstan",
-            "version": "0.12.85",
+            "version": "0.12.88",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpstan/phpstan.git",
-                "reference": "20e6333c0067875ad7697cd8acdf245c6ef69d03"
+                "reference": "464d1a81af49409c41074aa6640ed0c4cbd9bb68"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/20e6333c0067875ad7697cd8acdf245c6ef69d03",
-                "reference": "20e6333c0067875ad7697cd8acdf245c6ef69d03",
+                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/464d1a81af49409c41074aa6640ed0c4cbd9bb68",
+                "reference": "464d1a81af49409c41074aa6640ed0c4cbd9bb68",
                 "shasum": ""
             },
             "require": {
@@ -2056,7 +2124,7 @@
             "description": "PHPStan - PHP Static Analysis Tool",
             "support": {
                 "issues": "https://github.com/phpstan/phpstan/issues",
-                "source": "https://github.com/phpstan/phpstan/tree/0.12.85"
+                "source": "https://github.com/phpstan/phpstan/tree/0.12.88"
             },
             "funding": [
                 {
@@ -2072,7 +2140,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-04-27T14:13:16+00:00"
+            "time": "2021-05-17T12:24:49+00:00"
         },
         {
             "name": "phpunit/php-code-coverage",
@@ -2495,6 +2563,55 @@
             ],
             "time": "2021-03-23T07:16:29+00:00"
         },
+        {
+            "name": "psr/cache",
+            "version": "3.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/cache.git",
+                "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+                "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Cache\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for caching libraries",
+            "keywords": [
+                "cache",
+                "psr",
+                "psr-6"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/cache/tree/3.0.0"
+            },
+            "time": "2021-02-03T23:26:27+00:00"
+        },
         {
             "name": "psr/container",
             "version": "1.1.1",
@@ -3705,20 +3822,21 @@
         },
         {
             "name": "symfony/console",
-            "version": "v5.2.7",
+            "version": "v5.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "90374b8ed059325b49a29b55b3f8bb4062c87629"
+                "reference": "058553870f7809087fa80fa734704a21b9bcaeb2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/90374b8ed059325b49a29b55b3f8bb4062c87629",
-                "reference": "90374b8ed059325b49a29b55b3f8bb4062c87629",
+                "url": "https://api.github.com/repos/symfony/console/zipball/058553870f7809087fa80fa734704a21b9bcaeb2",
+                "reference": "058553870f7809087fa80fa734704a21b9bcaeb2",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.2.5",
+                "symfony/deprecation-contracts": "^2.1",
                 "symfony/polyfill-mbstring": "~1.0",
                 "symfony/polyfill-php73": "^1.8",
                 "symfony/polyfill-php80": "^1.15",
@@ -3782,7 +3900,7 @@
                 "terminal"
             ],
             "support": {
-                "source": "https://github.com/symfony/console/tree/v5.2.7"
+                "source": "https://github.com/symfony/console/tree/v5.3.0"
             },
             "funding": [
                 {
@@ -3798,7 +3916,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-04-19T14:07:32+00:00"
+            "time": "2021-05-26T17:43:10+00:00"
         },
         {
             "name": "symfony/deprecation-contracts",
@@ -3869,16 +3987,16 @@
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v5.2.4",
+            "version": "v5.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git",
-                "reference": "d08d6ec121a425897951900ab692b612a61d6240"
+                "reference": "67a5f354afa8e2f231081b3fa11a5912f933c3ce"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d08d6ec121a425897951900ab692b612a61d6240",
-                "reference": "d08d6ec121a425897951900ab692b612a61d6240",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/67a5f354afa8e2f231081b3fa11a5912f933c3ce",
+                "reference": "67a5f354afa8e2f231081b3fa11a5912f933c3ce",
                 "shasum": ""
             },
             "require": {
@@ -3934,7 +4052,7 @@
             "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/event-dispatcher/tree/v5.2.4"
+                "source": "https://github.com/symfony/event-dispatcher/tree/v5.3.0"
             },
             "funding": [
                 {
@@ -3950,7 +4068,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-02-18T17:12:37+00:00"
+            "time": "2021-05-26T17:43:10+00:00"
         },
         {
             "name": "symfony/event-dispatcher-contracts",
@@ -4033,16 +4151,16 @@
         },
         {
             "name": "symfony/filesystem",
-            "version": "v5.2.7",
+            "version": "v5.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/filesystem.git",
-                "reference": "056e92acc21d977c37e6ea8e97374b2a6c8551b0"
+                "reference": "348116319d7fb7d1faa781d26a48922428013eb2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/filesystem/zipball/056e92acc21d977c37e6ea8e97374b2a6c8551b0",
-                "reference": "056e92acc21d977c37e6ea8e97374b2a6c8551b0",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/348116319d7fb7d1faa781d26a48922428013eb2",
+                "reference": "348116319d7fb7d1faa781d26a48922428013eb2",
                 "shasum": ""
             },
             "require": {
@@ -4075,7 +4193,7 @@
             "description": "Provides basic utilities for the filesystem",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/filesystem/tree/v5.2.7"
+                "source": "https://github.com/symfony/filesystem/tree/v5.3.0"
             },
             "funding": [
                 {
@@ -4091,20 +4209,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-04-01T10:42:13+00:00"
+            "time": "2021-05-26T17:43:10+00:00"
         },
         {
             "name": "symfony/finder",
-            "version": "v5.2.4",
+            "version": "v5.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/finder.git",
-                "reference": "0d639a0943822626290d169965804f79400e6a04"
+                "reference": "0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/finder/zipball/0d639a0943822626290d169965804f79400e6a04",
-                "reference": "0d639a0943822626290d169965804f79400e6a04",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6",
+                "reference": "0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6",
                 "shasum": ""
             },
             "require": {
@@ -4136,7 +4254,7 @@
             "description": "Finds files and directories via an intuitive fluent interface",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/finder/tree/v5.2.4"
+                "source": "https://github.com/symfony/finder/tree/v5.3.0"
             },
             "funding": [
                 {
@@ -4152,20 +4270,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-02-15T18:55:04+00:00"
+            "time": "2021-05-26T12:52:38+00:00"
         },
         {
             "name": "symfony/options-resolver",
-            "version": "v5.2.4",
+            "version": "v5.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/options-resolver.git",
-                "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce"
+                "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce",
-                "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce",
+                "url": "https://api.github.com/repos/symfony/options-resolver/zipball/162e886ca035869866d233a2bfef70cc28f9bbe5",
+                "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5",
                 "shasum": ""
             },
             "require": {
@@ -4205,7 +4323,7 @@
                 "options"
             ],
             "support": {
-                "source": "https://github.com/symfony/options-resolver/tree/v5.2.4"
+                "source": "https://github.com/symfony/options-resolver/tree/v5.3.0"
             },
             "funding": [
                 {
@@ -4221,20 +4339,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-01-27T12:56:27+00:00"
+            "time": "2021-05-26T17:43:10+00:00"
         },
         {
             "name": "symfony/polyfill-ctype",
-            "version": "v1.22.1",
+            "version": "v1.23.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-ctype.git",
-                "reference": "c6c942b1ac76c82448322025e084cadc56048b4e"
+                "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e",
-                "reference": "c6c942b1ac76c82448322025e084cadc56048b4e",
+                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
+                "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
                 "shasum": ""
             },
             "require": {
@@ -4246,7 +4364,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.22-dev"
+                    "dev-main": "1.23-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -4284,7 +4402,7 @@
                 "portable"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1"
+                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
             },
             "funding": [
                 {
@@ -4300,20 +4418,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-01-07T16:49:33+00:00"
+            "time": "2021-02-19T12:13:01+00:00"
         },
         {
             "name": "symfony/polyfill-intl-grapheme",
-            "version": "v1.22.1",
+            "version": "v1.23.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
-                "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170"
+                "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5601e09b69f26c1828b13b6bb87cb07cddba3170",
-                "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/24b72c6baa32c746a4d0840147c9715e42bb68ab",
+                "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab",
                 "shasum": ""
             },
             "require": {
@@ -4325,7 +4443,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.22-dev"
+                    "dev-main": "1.23-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -4365,7 +4483,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1"
+                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.0"
             },
             "funding": [
                 {
@@ -4381,20 +4499,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-01-22T09:19:47+00:00"
+            "time": "2021-05-27T09:17:38+00:00"
         },
         {
             "name": "symfony/polyfill-intl-normalizer",
-            "version": "v1.22.1",
+            "version": "v1.23.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
-                "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248"
+                "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/43a0283138253ed1d48d352ab6d0bdb3f809f248",
-                "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
+                "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
                 "shasum": ""
             },
             "require": {
@@ -4406,7 +4524,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.22-dev"
+                    "dev-main": "1.23-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -4449,7 +4567,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1"
+                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0"
             },
             "funding": [
                 {
@@ -4465,20 +4583,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-01-22T09:19:47+00:00"
+            "time": "2021-02-19T12:13:01+00:00"
         },
         {
             "name": "symfony/polyfill-mbstring",
-            "version": "v1.22.1",
+            "version": "v1.23.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-mbstring.git",
-                "reference": "5232de97ee3b75b0360528dae24e73db49566ab1"
+                "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1",
-                "reference": "5232de97ee3b75b0360528dae24e73db49566ab1",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
+                "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
                 "shasum": ""
             },
             "require": {
@@ -4490,7 +4608,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.22-dev"
+                    "dev-main": "1.23-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -4529,7 +4647,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1"
+                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0"
             },
             "funding": [
                 {
@@ -4545,20 +4663,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-01-22T09:19:47+00:00"
+            "time": "2021-05-27T09:27:20+00:00"
         },
         {
             "name": "symfony/polyfill-php72",
-            "version": "v1.22.1",
+            "version": "v1.23.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php72.git",
-                "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9"
+                "reference": "9a142215a36a3888e30d0a9eeea9766764e96976"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9",
-                "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9",
+                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976",
+                "reference": "9a142215a36a3888e30d0a9eeea9766764e96976",
                 "shasum": ""
             },
             "require": {
@@ -4567,7 +4685,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.22-dev"
+                    "dev-main": "1.23-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -4605,7 +4723,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php72/tree/v1.22.1"
+                "source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0"
             },
             "funding": [
                 {
@@ -4621,20 +4739,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-01-07T16:49:33+00:00"
+            "time": "2021-05-27T09:17:38+00:00"
         },
         {
             "name": "symfony/polyfill-php73",
-            "version": "v1.22.1",
+            "version": "v1.23.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php73.git",
-                "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2"
+                "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2",
-                "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2",
+                "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010",
+                "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010",
                 "shasum": ""
             },
             "require": {
@@ -4643,7 +4761,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.22-dev"
+                    "dev-main": "1.23-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -4684,7 +4802,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1"
+                "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0"
             },
             "funding": [
                 {
@@ -4700,20 +4818,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-01-07T16:49:33+00:00"
+            "time": "2021-02-19T12:13:01+00:00"
         },
         {
             "name": "symfony/polyfill-php80",
-            "version": "v1.22.1",
+            "version": "v1.23.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php80.git",
-                "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91"
+                "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91",
-                "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91",
+                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0",
+                "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0",
                 "shasum": ""
             },
             "require": {
@@ -4722,7 +4840,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "1.22-dev"
+                    "dev-main": "1.23-dev"
                 },
                 "thanks": {
                     "name": "symfony/polyfill",
@@ -4767,7 +4885,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1"
+                "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0"
             },
             "funding": [
                 {
@@ -4783,20 +4901,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-01-07T16:49:33+00:00"
+            "time": "2021-02-19T12:13:01+00:00"
         },
         {
             "name": "symfony/process",
-            "version": "v5.2.7",
+            "version": "v5.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/process.git",
-                "reference": "98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e"
+                "reference": "53e36cb1c160505cdaf1ef201501669c4c317191"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/process/zipball/98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e",
-                "reference": "98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e",
+                "url": "https://api.github.com/repos/symfony/process/zipball/53e36cb1c160505cdaf1ef201501669c4c317191",
+                "reference": "53e36cb1c160505cdaf1ef201501669c4c317191",
                 "shasum": ""
             },
             "require": {
@@ -4829,7 +4947,7 @@
             "description": "Executes commands in sub-processes",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/process/tree/v5.3.0-BETA1"
+                "source": "https://github.com/symfony/process/tree/v5.3.0"
             },
             "funding": [
                 {
@@ -4845,7 +4963,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-04-08T10:27:02+00:00"
+            "time": "2021-05-26T12:52:38+00:00"
         },
         {
             "name": "symfony/service-contracts",
@@ -4928,16 +5046,16 @@
         },
         {
             "name": "symfony/stopwatch",
-            "version": "v5.2.7",
+            "version": "v5.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/stopwatch.git",
-                "reference": "d99310c33e833def36419c284f60e8027d359678"
+                "reference": "313d02f59d6543311865007e5ff4ace05b35ee65"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/d99310c33e833def36419c284f60e8027d359678",
-                "reference": "d99310c33e833def36419c284f60e8027d359678",
+                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/313d02f59d6543311865007e5ff4ace05b35ee65",
+                "reference": "313d02f59d6543311865007e5ff4ace05b35ee65",
                 "shasum": ""
             },
             "require": {
@@ -4970,7 +5088,7 @@
             "description": "Provides a way to profile code",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/stopwatch/tree/v5.3.0-BETA1"
+                "source": "https://github.com/symfony/stopwatch/tree/v5.3.0"
             },
             "funding": [
                 {
@@ -4986,20 +5104,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-03-29T15:28:41+00:00"
+            "time": "2021-05-26T17:43:10+00:00"
         },
         {
             "name": "symfony/string",
-            "version": "v5.2.6",
+            "version": "v5.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/string.git",
-                "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572"
+                "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/string/zipball/ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572",
-                "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572",
+                "url": "https://api.github.com/repos/symfony/string/zipball/a9a0f8b6aafc5d2d1c116dcccd1573a95153515b",
+                "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b",
                 "shasum": ""
             },
             "require": {
@@ -5053,7 +5171,7 @@
                 "utf8"
             ],
             "support": {
-                "source": "https://github.com/symfony/string/tree/v5.2.6"
+                "source": "https://github.com/symfony/string/tree/v5.3.0"
             },
             "funding": [
                 {
@@ -5069,20 +5187,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-03-17T17:12:15+00:00"
+            "time": "2021-05-26T17:43:10+00:00"
         },
         {
             "name": "symfony/var-dumper",
-            "version": "v5.2.7",
+            "version": "v5.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-dumper.git",
-                "reference": "27cb9f7cfa3853c736425c7233a8f68814b19636"
+                "reference": "1d3953e627fe4b5f6df503f356b6545ada6351f3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/27cb9f7cfa3853c736425c7233a8f68814b19636",
-                "reference": "27cb9f7cfa3853c736425c7233a8f68814b19636",
+                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1d3953e627fe4b5f6df503f356b6545ada6351f3",
+                "reference": "1d3953e627fe4b5f6df503f356b6545ada6351f3",
                 "shasum": ""
             },
             "require": {
@@ -5141,7 +5259,7 @@
                 "dump"
             ],
             "support": {
-                "source": "https://github.com/symfony/var-dumper/tree/v5.2.7"
+                "source": "https://github.com/symfony/var-dumper/tree/v5.3.0"
             },
             "funding": [
                 {
@@ -5157,7 +5275,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-04-19T14:07:32+00:00"
+            "time": "2021-05-27T12:28:50+00:00"
         },
         {
             "name": "theseer/tokenizer",

From bb0b1a5cd01aa497d0385d2f304cd92c57d19ddf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:11:38 +0200
Subject: [PATCH 02/11] feat(validation): validator contract

---
 .../Validation/ValidatorInterface.php         | 42 +++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 src/AGerault/Contracts/Validation/ValidatorInterface.php

diff --git a/src/AGerault/Contracts/Validation/ValidatorInterface.php b/src/AGerault/Contracts/Validation/ValidatorInterface.php
new file mode 100644
index 0000000..4d0fa81
--- /dev/null
+++ b/src/AGerault/Contracts/Validation/ValidatorInterface.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace AGerault\Framework\Contracts\Validation;
+
+interface ValidatorInterface
+{
+    /**
+     * @return bool Return whether all the rules passed
+     */
+    public function isValid(): bool;
+
+    /**
+     * @return array An associative array for errors
+     */
+    public function validate(): array;
+
+    /**
+     * @return array All fields passing their rules
+     */
+    public function validated(): array;
+
+    /**
+     * @return array An associative array to match fields with a set of rules
+     */
+    public function rules(): array;
+
+    /**
+     * @return array An associative array with inputs name and value
+     */
+    public function inputs(): array;
+
+    /**
+     * @param string $field
+     * @return mixed The input value
+     */
+    public function input(string $field): mixed;
+
+    /**
+     * @return array
+     */
+    public function errors(): array;
+}

From 883028a66a555294627ad867379d3c15160bef1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:12:24 +0200
Subject: [PATCH 03/11] feat(validation): basic abstract class for validator

---
 src/AGerault/Validation/Validator.php | 62 +++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 src/AGerault/Validation/Validator.php

diff --git a/src/AGerault/Validation/Validator.php b/src/AGerault/Validation/Validator.php
new file mode 100644
index 0000000..a699cd4
--- /dev/null
+++ b/src/AGerault/Validation/Validator.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace AGerault\Framework\Validation;
+
+use AGerault\Framework\Contracts\Validation\ValidatorInterface;
+use AGerault\Framework\Validation\Rules\Rule;
+
+abstract class Validator implements ValidatorInterface
+{
+    protected array $validated;
+    protected array $errors;
+
+    public function __construct(protected array $inputs) {}
+
+    public function isValid(): bool
+    {
+        $this->errors = [];
+
+        foreach ($this->rules() as $field => $ruleSet) {
+            $value = $this->inputs[$field];
+
+            /**
+             * @var Rule $rule
+             */
+            foreach ($ruleSet as $rule) {
+                $assertion = call_user_func($rule);
+                if (! $assertion) {
+                    $this->errors[$rule::class] = $rule->onFailMessage();
+                }
+            }
+            $this->validated[$field] = $value;
+        }
+
+        return count($this->errors) === 0;
+    }
+
+    public function validated(): array
+    {
+        $this->isValid();
+        return $this->validated;
+    }
+
+    public function validate(): array
+    {
+        return $this->isValid() ? [] : $this->errors;
+    }
+
+    public function inputs(): array
+    {
+        return $this->inputs;
+    }
+
+    public function input(string $field): mixed
+    {
+        return $this->inputs[$field];
+    }
+
+    public function errors(): array
+    {
+        return $this->errors;
+    }
+}

From 9caaf20d9f3569fc4abf5b00151bdb12ccaf9028 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:13:04 +0200
Subject: [PATCH 04/11] feat(validation): rule contract

---
 src/AGerault/Contracts/Validation/RuleInterface.php | 10 ++++++++++
 1 file changed, 10 insertions(+)
 create mode 100644 src/AGerault/Contracts/Validation/RuleInterface.php

diff --git a/src/AGerault/Contracts/Validation/RuleInterface.php b/src/AGerault/Contracts/Validation/RuleInterface.php
new file mode 100644
index 0000000..ad8ef60
--- /dev/null
+++ b/src/AGerault/Contracts/Validation/RuleInterface.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace AGerault\Framework\Contracts\Validation;
+
+interface RuleInterface
+{
+    public function validate(): bool;
+
+    public function onFailMessage(): string;
+}

From 4e740fa8f5bf5561c83cbf1aa8c126b6bc676b5b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:13:20 +0200
Subject: [PATCH 05/11] feat(validation): abstract rule class

---
 src/AGerault/Validation/Rules/Rule.php | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 src/AGerault/Validation/Rules/Rule.php

diff --git a/src/AGerault/Validation/Rules/Rule.php b/src/AGerault/Validation/Rules/Rule.php
new file mode 100644
index 0000000..47f3155
--- /dev/null
+++ b/src/AGerault/Validation/Rules/Rule.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace AGerault\Framework\Validation\Rules;
+
+use AGerault\Framework\Contracts\Validation\RuleInterface;
+
+abstract class Rule implements RuleInterface
+{
+    protected string $message = "";
+    protected mixed $value;
+
+    /**
+     * Rule constructor.
+     * @param mixed $value
+     */
+    public function __construct(mixed $value)
+    {
+        $this->value = $value;
+    }
+
+    public function __invoke(): bool
+    {
+        return $this->validate();
+    }
+}

From cbf882d2d4c4bdd96a1d61a019132c04ee01b7d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:13:36 +0200
Subject: [PATCH 06/11] feat(validation): email rule

---
 src/AGerault/Validation/Rules/EmailRule.php | 24 +++++++++++++++++
 tests/Unit/Validation/EmailRuleTest.php     | 30 +++++++++++++++++++++
 2 files changed, 54 insertions(+)
 create mode 100644 src/AGerault/Validation/Rules/EmailRule.php
 create mode 100644 tests/Unit/Validation/EmailRuleTest.php

diff --git a/src/AGerault/Validation/Rules/EmailRule.php b/src/AGerault/Validation/Rules/EmailRule.php
new file mode 100644
index 0000000..5fb1a0d
--- /dev/null
+++ b/src/AGerault/Validation/Rules/EmailRule.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace AGerault\Framework\Validation\Rules;
+
+use Assert\Assertion;
+use Assert\AssertionFailedException;
+
+class EmailRule extends Rule
+{
+    public function validate(): bool
+    {
+        try {
+            Assertion::email($this->value);
+            return true;
+        } catch (AssertionFailedException) {
+            return false;
+        }
+    }
+
+    public function onFailMessage(): string
+    {
+        return "{$this->value} is not a valid email address";
+    }
+}
diff --git a/tests/Unit/Validation/EmailRuleTest.php b/tests/Unit/Validation/EmailRuleTest.php
new file mode 100644
index 0000000..45f9222
--- /dev/null
+++ b/tests/Unit/Validation/EmailRuleTest.php
@@ -0,0 +1,30 @@
+<?php
+
+use AGerault\Framework\Validation\Rules\EmailRule;
+
+it(
+    "should pass the email test",
+    function () {
+        $rule = new EmailRule("gerault-alexandre@orange.fr");
+
+        expect($rule->validate())->toBeTrue();
+    }
+);
+
+it(
+    "should not pass the email test when we do not provide a correct email",
+    function () {
+        $rule = new EmailRule("1234");
+
+        expect($rule->validate())->toBeFalse();
+    }
+);
+
+it(
+    "should give the error message",
+    function () {
+        $rule = new EmailRule("1234");
+
+        expect($rule->onFailMessage())->toBe("1234 is not a valid email address");
+    }
+);

From 0f55a0a9d793d6bd1a7996544ff61d9c093611a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:14:24 +0200
Subject: [PATCH 07/11] feat(validation): exist rule

---
 src/AGerault/Validation/Rules/ExistRule.php | 36 +++++++++++++++++++++
 1 file changed, 36 insertions(+)
 create mode 100644 src/AGerault/Validation/Rules/ExistRule.php

diff --git a/src/AGerault/Validation/Rules/ExistRule.php b/src/AGerault/Validation/Rules/ExistRule.php
new file mode 100644
index 0000000..a14383b
--- /dev/null
+++ b/src/AGerault/Validation/Rules/ExistRule.php
@@ -0,0 +1,36 @@
+<?php
+
+
+namespace AGerault\Framework\Validation\Rules;
+
+
+use AGerault\Framework\Database\QueryBuilder;
+
+class ExistRule extends Rule
+{
+    public function __construct(
+        mixed $value,
+        protected \PDO $pdo,
+        protected string $table,
+        protected string $column
+    ) {
+        parent::__construct($value);
+    }
+
+    public function validate(): bool
+    {
+        $query = new QueryBuilder();
+        $query = $query->from($this->table)->where($this->column, '=')->toSql();
+
+        $pdoQuery = $this->pdo->prepare($query);
+        $pdoQuery->bindParam(":{$this->column}", $this->value);
+        $pdoQuery->execute();
+
+        return count($pdoQuery->fetchAll()) >= 1;
+    }
+
+    public function onFailMessage(): string
+    {
+        return "{$this->value} does not exist in table {$this->table} for column `{$this->column}`";
+    }
+}

From 14f3e43711a967bb857d5ffe9f5fa3ab6125142b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:14:34 +0200
Subject: [PATCH 08/11] feat(validation): unique rule

---
 src/AGerault/Validation/Rules/UniqueRule.php | 34 ++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 src/AGerault/Validation/Rules/UniqueRule.php

diff --git a/src/AGerault/Validation/Rules/UniqueRule.php b/src/AGerault/Validation/Rules/UniqueRule.php
new file mode 100644
index 0000000..41c724a
--- /dev/null
+++ b/src/AGerault/Validation/Rules/UniqueRule.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace AGerault\Framework\Validation\Rules;
+
+use AGerault\Framework\Database\QueryBuilder;
+
+class UniqueRule extends Rule
+{
+    public function __construct(
+        mixed $value,
+        protected \PDO $pdo,
+        protected string $table,
+        protected string $column
+    ) {
+        parent::__construct($value);
+    }
+
+    public function validate(): bool
+    {
+        $query = new QueryBuilder();
+        $query = $query->from($this->table)->where($this->column, '=')->toSql();
+
+        $pdoQuery = $this->pdo->prepare($query);
+        $pdoQuery->bindParam(":{$this->column}", $this->value);
+        $pdoQuery->execute();
+
+        return count($pdoQuery->fetchAll()) === 0;
+    }
+
+    public function onFailMessage(): string
+    {
+        return "{$this->value} already exists in table {$this->table} for column `{$this->column}`";
+    }
+}

From 28b8975a6e61fb4d72c2db33f32ca76f832c39ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:14:55 +0200
Subject: [PATCH 09/11] feat(validation): check whether it's in array

---
 src/AGerault/Validation/Rules/InArrayRule.php | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 src/AGerault/Validation/Rules/InArrayRule.php

diff --git a/src/AGerault/Validation/Rules/InArrayRule.php b/src/AGerault/Validation/Rules/InArrayRule.php
new file mode 100644
index 0000000..0daa8f6
--- /dev/null
+++ b/src/AGerault/Validation/Rules/InArrayRule.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace AGerault\Framework\Validation\Rules;
+
+class InArrayRule extends Rule
+{
+    public function __construct(protected mixed $value, protected array $haystack)
+    {
+        parent::__construct($this->value);
+    }
+
+    public function validate(): bool
+    {
+        return in_array($this->value, $this->haystack);
+    }
+
+    public function onFailMessage(): string
+    {
+        return "Provided value is not in your array";
+    }
+}

From fea2278558a821f6bbfffa2a607b3f8172d16d94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:15:18 +0200
Subject: [PATCH 10/11] feat(validation): check whether values are strictly the
 same

---
 src/AGerault/Validation/Rules/SameRule.php | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 src/AGerault/Validation/Rules/SameRule.php

diff --git a/src/AGerault/Validation/Rules/SameRule.php b/src/AGerault/Validation/Rules/SameRule.php
new file mode 100644
index 0000000..ff02f3e
--- /dev/null
+++ b/src/AGerault/Validation/Rules/SameRule.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace AGerault\Framework\Validation\Rules;
+
+class SameRule extends Rule
+{
+    public function __construct(protected mixed $value, protected mixed $target)
+    {
+        parent::__construct($value);
+    }
+
+    public function validate(): bool
+    {
+        return $this->value === $this->target;
+    }
+
+    public function onFailMessage(): string
+    {
+        return "{$this->target} is not the same than {$this->value}";
+    }
+}

From 4c58ea93075cb7abe19d26a0b91089fa4ddb871a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alexandre=20G=C3=A9rault?= <alexandre@hexium.io>
Date: Tue, 15 Jun 2021 23:15:34 +0200
Subject: [PATCH 11/11] feat(validation): check whether value is a string

---
 src/AGerault/Validation/Rules/StringRule.php | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 src/AGerault/Validation/Rules/StringRule.php

diff --git a/src/AGerault/Validation/Rules/StringRule.php b/src/AGerault/Validation/Rules/StringRule.php
new file mode 100644
index 0000000..439d833
--- /dev/null
+++ b/src/AGerault/Validation/Rules/StringRule.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace AGerault\Framework\Validation\Rules;
+
+use Assert\Assert;
+use Assert\AssertionFailedException;
+
+class StringRule extends Rule
+{
+    public function validate(): bool
+    {
+        return is_string($this->value);
+    }
+
+    public function onFailMessage(): string
+    {
+        return "{$this->value} is not a valid string";
+    }
+}