diff --git a/docs/filter-rules.md b/docs/filter-rules.md index 5062f02..166d792 100644 --- a/docs/filter-rules.md +++ b/docs/filter-rules.md @@ -21,6 +21,7 @@ filters, take a look at the callback filter-rule, or check out "Extending the Fi * [remove](#remove)() * [removeNull](#removenull)() * [replace](#replace)($search, $replace) +* [slug](#slug)($fieldToSlugFrom) * [string](#string)() * [stripHtml](#striphtml)($excludeTags = null) * [trim](#trim)($characters = null) @@ -149,7 +150,7 @@ Make sure the value is a float. $f = new Filter; $f->value('value')->float(); $result = $f->filter(['value' => '123.123']); -// array(1) { ["value"]=> float(123.123) } +// array(1) { ["value"]=> float(123.123) } ``` ## Int @@ -160,7 +161,7 @@ Make sure the value is a int. $f = new Filter; $f->value('value')->int(); $result = $f->filter(['value' => '123.123']); -// array(1) { ["value"]=> int(123) } +// array(1) { ["value"]=> int(123) } ``` ## Letters @@ -200,7 +201,7 @@ $result = $f->filter([ * array(2) { * ["price"]=> string(4) "5.00" * ["discount"]=> string(4) "2.93" - * } + * } */ ``` @@ -270,6 +271,35 @@ $result = $f->filter(['name' => 'hello im john']); // array(1) { ["name"]=> string(13) "hello-im-john" } ``` +## Slug + +Slugs the value of the field or the value of another one for use in an URL. + +```php +$f = new Filter; +$f->value('slug')->slug(); +$result = $f->filter(['slug' => 'Slug this !']); +// array(1) { ["slug"]=> string(9) "slug-this" } +``` + +Here we'll slug the value from another field. + +```php +$f = new Filter; +$f->value('slug')->slug('title'); +$result = $f->filter(['title' => 'Slug this title !']); +// array(2) { ["title"]=> string(17) "Slug this title !" ["slug"]=> string(15) "slug-this-title" } +``` + +If there is no value in the other field, the slug field won't appear in the filtered result : + +```php +$f = new Filter; +$f->value('slug')->slug('title'); +$result = $f->filter(['foo' => 'bar']); +// array(1) { ["foo"]=> string(3) "bar" } +``` + ## String Make sure the value is a string. diff --git a/src/FilterResource.php b/src/FilterResource.php index a263496..0c21931 100644 --- a/src/FilterResource.php +++ b/src/FilterResource.php @@ -229,6 +229,17 @@ public function replace($search, $replace) return $this->addRule(new FilterRule\Replace($search, $replace)); } + /** + * Results that returns a value slugged + * + * @param string|null $fieldToSlugFrom + * @return $this + */ + public function slug($fieldToSlugFrom = null) + { + return $this->addRule(new FilterRule\Slug($fieldToSlugFrom)); + } + /** * Returns rule that results a casted string * diff --git a/src/FilterRule/Slug.php b/src/FilterRule/Slug.php new file mode 100644 index 0000000..8d19e2b --- /dev/null +++ b/src/FilterRule/Slug.php @@ -0,0 +1,67 @@ +fieldToSlugFrom = $fieldToSlugFrom; + } + + /** + * Slug the value of either the actual field of the given one. + * + * @param mixed $value + * @return string + */ + public function filter($value) + { + if (empty($value) && isset($this->filterData[$this->fieldToSlugFrom])) { + $value = $this->filterData[$this->fieldToSlugFrom]; + } + + if (is_null($value)) { + return $this->setEmpty(); + } + + $value = transliterator_transliterate($this->transliterator, $value); + $value = iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", $value); + $value = preg_replace('/[-$?\s]+/', '-', $value); + $value = trim($value, '-'); + return strtolower($value); + } +} diff --git a/tests/FilterRule/SlugTest.php b/tests/FilterRule/SlugTest.php new file mode 100644 index 0000000..780642d --- /dev/null +++ b/tests/FilterRule/SlugTest.php @@ -0,0 +1,69 @@ +filter = new Filter(); + } + + /** + * @dataProvider getSlugResults + * @param string $value + * @param string $filteredValue + * @param string $field + * @param string $fieldValue + */ + public function testSlugFilterRule($value, $filteredValue, $field, $fieldValue) + { + $this->filter->value('test')->slug($field); + + $result = $this->filter->filter([ + 'test' => $value, + $field => $fieldValue, + ]); + + $this->assertSame($filteredValue, $result['test']); + } + + /** + * @return array + */ + public function getSlugResults() + { + return [ + ['', '', '', ''], + ['This is a great stuff to slug !', 'this-is-a-great-stuff-to-slug', '', ''], + ['That too with somê spéciàl châractèr$ from €ope !', 'that-too-with-some-special-character-from-europe', '', ''], + ['A æ Übérmensch på høyeste nivå! И я люблю PHP ! fi', 'a-ae-ubermensch-pa-hoyeste-niva-i-a-lublu-php-fi', '', ''], + ['', 'this-is-a-great-stuff-to-slug', 'test', 'This is a great stuff to slug !'], + ['', 'that-too-with-some-special-character-from-europe', 'test', 'That too with somê spéciàl châractèr$ from €ope !'], + ['', 'a-ae-ubermensch-pa-hoyeste-niva-i-a-lublu-php-fi', 'test', 'A æ Übérmensch på høyeste nivå! И я люблю PHP ! fi'], + ]; + } + + /** + * Test that a slug based of a non existing key, does not exist. + */ + public function testSlugFilterEmptyIfNotAvailable() + { + $this->filter->value('slug')->slug('title'); + + $result = $this->filter->filter([ + 'not-title' => 'Definitely not a title to slug', + ]); + + $this->assertSame(['not-title' => 'Definitely not a title to slug'], $result); + } +}