From fa26c5e83f5c7154bbf304b6ad1b8e194b399bc4 Mon Sep 17 00:00:00 2001
From: Thomas Flori <thflori@gmail.com>
Date: Fri, 6 Apr 2018 07:31:47 +0200
Subject: [PATCH] add slug validator

---
 README.md                            |  5 +-
 src/Validator.php                    |  1 +
 src/Validator/Alpha.php              |  2 +-
 src/Validator/AlphaNumeric.php       |  2 +-
 src/Validator/Slug.php               | 31 ++++++++++++
 tests/Validator/AlphaNumericTest.php |  2 +-
 tests/Validator/SlugTest.php         | 75 ++++++++++++++++++++++++++++
 7 files changed, 111 insertions(+), 7 deletions(-)
 create mode 100644 src/Validator/Slug.php
 create mode 100644 tests/Validator/SlugTest.php

diff --git a/README.md b/README.md
index 43e1c3f..a49389f 100644
--- a/README.md
+++ b/README.md
@@ -76,14 +76,11 @@ In this library the following validators are included:
 - `NotEmpty`: Value must not be empty
 - `Numeric`: Value must be numeric
 - `PregMatch`: Value must match regular expression `$pattern`
+- `Slug`: Value must contain only slug characters (a-z, 0-9, -, _)
 - `StrLen`: String length from value must be between `$min` and `$max`
 - `Truthful`: Converted to boolean the value must be true
 - `Url`: Value must be a valid URL
 
-Planned:
-
-- `Slug`: Value must contain only slug characters (a-z, 0-9, -, _)
-
 # Predefined Filters
 
 The following filters are included in this library:
diff --git a/src/Validator.php b/src/Validator.php
index 9df3d54..29e526b 100644
--- a/src/Validator.php
+++ b/src/Validator.php
@@ -31,6 +31,7 @@ use Verja\Validator\Not;
  * @method static Validator\NotEmpty notEmpty()
  * @method static Validator\Numeric numeric(string $decimalPoint = '.')
  * @method static Validator\PregMatch pregMatch(string $pattern)
+ * @method static Validator\Slug slug()
  * @method static Validator\StrLen strLen(int $min, int $max = 0)
  * @method static Validator\Truthful truthful()
  * @method static Validator\Url url(string $coverage = 'complete', $schemes = ['https', 'http', 'ftp'])
diff --git a/src/Validator/Alpha.php b/src/Validator/Alpha.php
index e6db418..153a39b 100644
--- a/src/Validator/Alpha.php
+++ b/src/Validator/Alpha.php
@@ -29,7 +29,7 @@ class Alpha extends Validator
     public function validate($value, array $context = []): bool
     {
         $regex = '/^[\pL\pM' . ($this->allowSpaces ? ' ' : '') . ']*$/u';
-        if (preg_match_all($regex, $value)) {
+        if (preg_match($regex, $value)) {
             return true;
         }
 
diff --git a/src/Validator/AlphaNumeric.php b/src/Validator/AlphaNumeric.php
index e9fde70..3583184 100644
--- a/src/Validator/AlphaNumeric.php
+++ b/src/Validator/AlphaNumeric.php
@@ -29,7 +29,7 @@ class AlphaNumeric extends Validator
     public function validate($value, array $context = []): bool
     {
         $regex = '/^[\pL\pM\pN' . ($this->allowSpaces ? ' ' : '') . ']*$/u';
-        if (preg_match_all($regex, $value)) {
+        if (preg_match($regex, $value)) {
             return true;
         }
 
diff --git a/src/Validator/Slug.php b/src/Validator/Slug.php
new file mode 100644
index 0000000..9ff50bd
--- /dev/null
+++ b/src/Validator/Slug.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Verja\Validator;
+
+use Verja\Error;
+use Verja\Validator;
+
+class Slug extends Validator
+{
+    /**
+     * Validate $value
+     *
+     * @param mixed $value
+     * @param array $context
+     * @return bool
+     */
+    public function validate($value, array $context = []): bool
+    {
+        $regex = '/^[0-9a-z-_]+$/u';
+        if (preg_match($regex, $value)) {
+            return true;
+        }
+
+        $this->error = new Error(
+            'NO_SLUG',
+            $value,
+            'value should be a valid slug'
+        );
+        return false;
+    }
+}
diff --git a/tests/Validator/AlphaNumericTest.php b/tests/Validator/AlphaNumericTest.php
index 62f536e..612849c 100644
--- a/tests/Validator/AlphaNumericTest.php
+++ b/tests/Validator/AlphaNumericTest.php
@@ -11,7 +11,7 @@ class AlphaNumericTest extends TestCase
     /** @dataProvider provideAlphanumericStrings
      * @param $value
      * @test */
-    public function acceptsStringsWithAlphabeticalCharacters($value)
+    public function acceptsStringsWithAlphanumericCharacters($value)
     {
         $validator = new AlphaNumeric();
 
diff --git a/tests/Validator/SlugTest.php b/tests/Validator/SlugTest.php
new file mode 100644
index 0000000..5ae35c2
--- /dev/null
+++ b/tests/Validator/SlugTest.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Verja\Test\Validator;
+
+use Verja\Error;
+use Verja\Test\TestCase;
+use Verja\Validator\Slug;
+
+class SlugTest extends TestCase
+{
+    /** @dataProvider provideSlugs
+     * @param $value
+     * @test */
+    public function acceptsStringsWithSlugs($value)
+    {
+        $validator = new Slug();
+
+        $result = $validator->validate($value);
+
+        self::assertTrue($result);
+    }
+
+    /** @dataProvider provideNonSlugs
+     * @param $value
+     * @test */
+    public function doesNotAcceptOtherCharacters($value)
+    {
+        $validator = new Slug();
+
+        $result = $validator->validate($value);
+
+        self::assertFalse($result);
+    }
+
+
+    /** @test */
+    public function storesAnErrorMessage()
+    {
+        $validator = new Slug();
+
+        $validator->validate('foo?');
+
+        self::assertEquals(
+            new Error(
+                'NO_SLUG',
+                'foo?',
+                'value should be a valid slug'
+            ),
+            $validator->getError()
+        );
+    }
+
+    public function provideSlugs()
+    {
+        return [
+            ['42'],
+            ['foobar'],
+            ['foo-bar'],
+            ['foo_bar'],
+        ];
+    }
+
+    public function provideNonSlugs()
+    {
+        return [
+            ['Û´Û²'], // Arabic 42
+            ['名'],
+            ['à'],
+            ['Müller'],
+            ['Karīna'],
+            ['string with space'],
+            [''], // empty is not valid
+        ];
+    }
+}
-- 
GitLab