diff --git a/lib/Gedmo/Sluggable/Handler/SlugHandlerWithUniqueCallbackInterface.php b/lib/Gedmo/Sluggable/Handler/SlugHandlerWithUniqueCallbackInterface.php new file mode 100644 index 0000000000..11a9ff1da4 --- /dev/null +++ b/lib/Gedmo/Sluggable/Handler/SlugHandlerWithUniqueCallbackInterface.php @@ -0,0 +1,28 @@ + + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +interface SlugHandlerWithUniqueCallbackInterface extends SlugHandlerInterface +{ + /** + * Callback for slug handlers before it is made unique + * + * @param SluggableAdapter $ea + * @param array $config + * @param object $object + * @param string $slug + * + * @return void + */ + public function beforeMakingUnique(SluggableAdapter $ea, array &$config, $object, &$slug); +} diff --git a/lib/Gedmo/Sluggable/Handler/TreeSlugHandler.php b/lib/Gedmo/Sluggable/Handler/TreeSlugHandler.php index 32afe68491..ed62eeba96 100644 --- a/lib/Gedmo/Sluggable/Handler/TreeSlugHandler.php +++ b/lib/Gedmo/Sluggable/Handler/TreeSlugHandler.php @@ -17,7 +17,7 @@ * @author Gediminas Morkevicius * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -class TreeSlugHandler implements SlugHandlerInterface +class TreeSlugHandler implements SlugHandlerWithUniqueCallbackInterface { const SEPARATOR = '/'; @@ -128,10 +128,16 @@ public static function validate(array $options, ClassMetadata $meta) /** * {@inheritDoc} */ - public function onSlugCompletion(SluggableAdapter $ea, array &$config, $object, &$slug) + public function beforeMakingUnique(SluggableAdapter $ea, array &$config, $object, &$slug) { $slug = $this->transliterate($slug, $config['separator'], $object); + } + /** + * {@inheritDoc} + */ + public function onSlugCompletion(SluggableAdapter $ea, array &$config, $object, &$slug) + { if (!$this->isInsert) { $wrapped = AbstractWrapper::wrap($object, $this->om); $meta = $wrapped->getMetadata(); diff --git a/lib/Gedmo/Sluggable/SluggableListener.php b/lib/Gedmo/Sluggable/SluggableListener.php index 44c472ada7..e0fa5e6048 100644 --- a/lib/Gedmo/Sluggable/SluggableListener.php +++ b/lib/Gedmo/Sluggable/SluggableListener.php @@ -4,6 +4,7 @@ use Doctrine\Common\EventArgs; use Gedmo\Mapping\MappedEventSubscriber; +use Gedmo\Sluggable\Handler\SlugHandlerWithUniqueCallbackInterface; use Gedmo\Sluggable\Mapping\Event\SluggableAdapter; use Doctrine\Common\Persistence\ObjectManager; use Gedmo\Tool\Wrapper\AbstractWrapper; @@ -384,6 +385,16 @@ private function generateSlug(SluggableAdapter $ea, $object) $slug = null; } + // notify slug handlers --> beforeMakingUnique + if ($hasHandlers) { + foreach ($options['handlers'] as $class => $handlerOptions) { + $handler = $this->getHandler($class); + if ($handler instanceof SlugHandlerWithUniqueCallbackInterface) { + $handler->beforeMakingUnique($ea, $options, $object, $slug); + } + } + } + // make unique slug if requested if ($options['unique'] && null !== $slug) { $this->exponent = 0; diff --git a/tests/Gedmo/Sluggable/Handlers/TreeSlugHandlerUniqueTest.php b/tests/Gedmo/Sluggable/Handlers/TreeSlugHandlerUniqueTest.php new file mode 100644 index 0000000000..e4366159dc --- /dev/null +++ b/tests/Gedmo/Sluggable/Handlers/TreeSlugHandlerUniqueTest.php @@ -0,0 +1,71 @@ +addEventSubscriber(new SluggableListener()); + $evm->addEventSubscriber(new TreeListener()); + + $this->getMockSqliteEntityManager($evm); + } + + public function testUniqueRoot() + { + $foo1 = new TreeSlug(); + $foo1->setTitle('Foo'); + + $foo2 = new TreeSlug(); + $foo2->setTitle('Foo'); + + $this->em->persist($foo1); + $this->em->persist($foo2); + + $this->em->flush(); + + $this->assertEquals('foo', $foo1->getSlug()); + $this->assertEquals('foo-1', $foo2->getSlug()); + } + + public function testUniqueLeaf() + { + $root = new TreeSlug(); + $root->setTitle('root'); + + $foo1 = new TreeSlug(); + $foo1->setTitle('Foo'); + $foo1->setParent($root); + + $foo2 = new TreeSlug(); + $foo2->setTitle('Foo'); + $foo2->setParent($root); + + $this->em->persist($root); + $this->em->persist($foo1); + $this->em->persist($foo2); + + $this->em->flush(); + + $this->assertEquals('root/foo', $foo1->getSlug()); + $this->assertEquals('root/foo-1', $foo2->getSlug()); + } + + protected function getUsedEntityFixtures() + { + return array( + self::TARGET, + ); + } +}