diff --git a/src/Knp/DoctrineBehaviors/Model/Sluggable/Sluggable.php b/src/Knp/DoctrineBehaviors/Model/Sluggable/Sluggable.php index 91ec588f..0b752c0c 100644 --- a/src/Knp/DoctrineBehaviors/Model/Sluggable/Sluggable.php +++ b/src/Knp/DoctrineBehaviors/Model/Sluggable/Sluggable.php @@ -60,7 +60,7 @@ public function setSlug($slug) return $this; } - + /** * Returns the entity's slug. * @@ -76,28 +76,39 @@ public function getSlug() */ public function generateSlug() { - if ( $this->getRegenerateSlugOnUpdate() || empty( $this->slug ) ) { + if ($this->getRegenerateSlugOnUpdate() || empty($this->slug)) { $fields = $this->getSluggableFields(); $usableValues = []; foreach ($fields as $field) { // Too bad empty is a language construct...otherwise we could use the return value in a write context :) $val = $this->{$field}; - if ( !empty( $val ) ) { + if (!empty($val)) { $usableValues[] = $val; } } - if ( count($usableValues) < 1 ) { - throw new \UnexpectedValueException('Sluggable expects to have at least one usable (non-empty) field from the following: [ ' . implode($fields, ',') .' ]'); + if (count($usableValues) < 1) { + throw new \UnexpectedValueException('Sluggable expects to have at least one usable (non-empty) field from the following: [ ' . implode($fields, ',') . ' ]'); } // generate the slug itself - $sluggableText = implode($usableValues, ' '); - $urlized = strtolower( trim( preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', iconv('UTF-8', 'ASCII//TRANSLIT', $sluggableText) ), $this->getSlugDelimiter() ) ); - $urlized = preg_replace("/[\/_|+ -]+/", $this->getSlugDelimiter(), $urlized); - - $this->slug = $urlized; + $this->slug = $this->transliterate(implode($usableValues, ' ')); } } + + /** + * This method should transliterate given string + * Feel free to override this any way you want. + * + * @param string + * @return string + */ + protected function transliterate($string) + { + $string = transliterator_transliterate("Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC; [:Punctuation:] Remove; Lower();", $string); + $string = preg_replace('/[-\s]+/', '-', $string); + + return trim($string, '-'); + } } diff --git a/src/Knp/DoctrineBehaviors/Model/Sluggable/Utils.php b/src/Knp/DoctrineBehaviors/Model/Sluggable/Utils.php new file mode 100644 index 00000000..e420bafa --- /dev/null +++ b/src/Knp/DoctrineBehaviors/Model/Sluggable/Utils.php @@ -0,0 +1,32 @@ + + */ +class Utils +{ + private static $ru_alphabet = array( 'а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п','р','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я'); + private static $translit_alphabet = array('a','b','v','g','d','e','yo','zh', 'z', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u','f', 'h', 'ts', 'ch', 'sh', 'sch', '', 'y', 'j', 'e', 'yu', 'ya'); + + /** + * This method prepares string to be an url's part + * @param string $string + * @return string + */ + public static function transliterateRussian($string) + { + $string = function_exists('mb_strtolower') ? mb_strtolower($string, 'UTF-8') : strtolower($string); + + $string = str_replace(self::$ru_alphabet, self::$translit_alphabet, $string); + + $string = transliterator_transliterate("Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC; [:Punctuation:] Remove;", $string); + $string = preg_replace('/[-\s]+/', '-', $string); + + return trim($string, '-'); + } +} \ No newline at end of file diff --git a/tests/Knp/DoctrineBehaviors/ORM/SluggableTest.php b/tests/Knp/DoctrineBehaviors/ORM/SluggableTest.php index 9bc9baf4..fc740e42 100644 --- a/tests/Knp/DoctrineBehaviors/ORM/SluggableTest.php +++ b/tests/Knp/DoctrineBehaviors/ORM/SluggableTest.php @@ -97,4 +97,40 @@ public function testUpdatedSlug() $this->assertEquals($entity->getSlug(), $expected); } + + /** + * @test + */ + public function shouldTransliterateSlug() + { + $em = $this->getEntityManager(); + $entity = new \BehaviorFixtures\ORM\SluggableEntity(); + + $expected = 'privet'; + + $entity->setName('Привет!'); + + $em->persist($entity); + $em->flush(); + + $this->assertEquals($expected, $entity->getSlug()); + } + + /** + * @test + */ + public function shouldTransliterateSlugInRussian() + { + $em = $this->getEntityManager(); + $entity = new \BehaviorFixtures\ORM\RussianSluggableEntity(); + + $expected = 'ya-budu-zhdatj-tebya'; + + $entity->setName('Я буду ждать тебя!'); + + $em->persist($entity); + $em->flush(); + + $this->assertEquals($expected, $entity->getSlug()); + } } diff --git a/tests/fixtures/BehaviorFixtures/ORM/RussianSluggableEntity.php b/tests/fixtures/BehaviorFixtures/ORM/RussianSluggableEntity.php new file mode 100644 index 00000000..f83e28df --- /dev/null +++ b/tests/fixtures/BehaviorFixtures/ORM/RussianSluggableEntity.php @@ -0,0 +1,18 @@ +