Skip to content
This repository was archived by the owner on Feb 12, 2023. It is now read-only.

Commit 260ef51

Browse files
committed
feat: Slugifier added
1 parent c4fcf2f commit 260ef51

File tree

3 files changed

+136
-2
lines changed

3 files changed

+136
-2
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"psr/container": "^1.0"
1717
},
1818
"suggest": {
19-
"ext-libxml": "TagAndAttributeRemover needs this extention"
19+
"ext-libxml": "TagAndAttributeRemover needs this extention",
20+
"ext-intl": "Slugify needs this extension"
2021
},
2122
"require-dev": {
2223
"codeception/codeception": "^4.1",
@@ -38,7 +39,6 @@
3839
}
3940
},
4041
"scripts": {
41-
4242
"cs-check": "vendor/bin/phpcs --standard=Doctrine",
4343
"cs-fix": "vendor/bin/phpcbf --standard=Doctrine"
4444

src/Slugifier.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Selami\Stdlib;
6+
7+
use Selami\Stdlib\Exception\InvalidArgumentException;
8+
use Transliterator;
9+
10+
class Slugifier
11+
{
12+
/**
13+
* @var string|array $subject
14+
*/
15+
private $subject;
16+
17+
private Transliterator $transliterator;
18+
/**
19+
* @param string|iterable $subject
20+
*/
21+
private function __construct($subject)
22+
{
23+
$this->subject = $subject;
24+
$this->transliterator = Transliterator::create('Any-Latin; Latin-ASCII');
25+
}
26+
/**
27+
* @param mixed<string|iterable> $subject
28+
* @return string|iterable<string>
29+
*/
30+
public static function slugify($subject)
31+
{
32+
return (new self($subject))
33+
->getSlugifiedResult();
34+
}
35+
/**
36+
* @return string|iterable<string>
37+
*/
38+
private function getSlugifiedResult()
39+
{
40+
if (is_iterable($this->subject)) {
41+
return $this->getSlugifiedIterable($this->subject);
42+
}
43+
return $this->getSlugifiedString($this->subject);
44+
}
45+
46+
private function getSlugifiedString($subject) : string
47+
{
48+
49+
if (!is_string($subject)) {
50+
throw new InvalidArgumentException(
51+
sprintf('Only string or array of strings accepted but %s given', gettype($subject))
52+
);
53+
}
54+
$stringWithRemovedDiacritics = $this->transliterator->transliterate($subject);
55+
$stringWithRemovedWhite = preg_replace(['/\-/','/[\W]+/'], [' ','-'], $stringWithRemovedDiacritics);
56+
return strtolower($stringWithRemovedWhite);
57+
}
58+
59+
/**
60+
* @param iterable $subject
61+
* @return iterable<string>
62+
*/
63+
private function getSlugifiedIterable(iterable $subject) : iterable
64+
{
65+
foreach ($subject as $item) {
66+
yield $this->getSlugifiedString($item);
67+
}
68+
}
69+
}

tests/unit/SlugifierTest.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace UnitTest;
6+
7+
use Codeception\Test\Unit;
8+
use Selami\Stdlib\Exception\InvalidArgumentException;
9+
use Selami\Stdlib\Slugifier;
10+
11+
class SlugifierTest extends Unit
12+
{
13+
protected $tester;
14+
15+
protected function _before(): void
16+
{
17+
}
18+
19+
protected function _after(): void
20+
{
21+
}
22+
23+
/**
24+
* @test
25+
* @dataProvider dataProvider
26+
*/
27+
public function shouldReturnSlugifySuccessfully($subjects, $expected): void
28+
{
29+
$actual = Slugifier::slugify($subjects);
30+
$index = 0;
31+
foreach ($actual as $item) {
32+
$this->assertEquals($expected[$index], $item, 'Returning expected slugs failed');
33+
$index++;
34+
}
35+
}
36+
/**
37+
* @test
38+
*/
39+
public function shouldThrowExceptionForInvalidInput(): void
40+
{
41+
$this->expectException(InvalidArgumentException::class);
42+
Slugifier::slugify(1234);
43+
}
44+
45+
public function dataProvider() : array
46+
{
47+
return [
48+
[
49+
[
50+
'Meinung: Impfstoff-Mangel für die Ärmsten - eine moralische Bankrotterklärung',
51+
'Türkiye\'nin İstanbul Sözleşmesi serüveni',
52+
'Во Франции прошли протесты против ужесточения мер',
53+
'1234'
54+
],
55+
[
56+
'meinung-impfstoff-mangel-fur-die-armsten-eine-moralische-bankrotterklarung',
57+
'turkiye-nin-istanbul-sozlesmesi-seruveni',
58+
'vo-francii-prosli-protesty-protiv-uzestocenia-mer',
59+
'1234'
60+
],
61+
]
62+
];
63+
}
64+
65+
}

0 commit comments

Comments
 (0)