From 164dcefcb08a648eb21be6142cdd76da52e706d1 Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 3 Oct 2025 15:13:16 +0000 Subject: [PATCH] implement test and fix for #2990 --- src/Sluggable/Handler/RelativeSlugHandler.php | 4 + .../Sluggable/Fixture/Issue2990/Article.php | 91 +++++++++++++++++ .../Fixture/Issue2990/ArticleRelativeSlug.php | 97 +++++++++++++++++++ tests/Gedmo/Sluggable/Issue/Issue2990Test.php | 67 +++++++++++++ 4 files changed, 259 insertions(+) create mode 100644 tests/Gedmo/Sluggable/Fixture/Issue2990/Article.php create mode 100644 tests/Gedmo/Sluggable/Fixture/Issue2990/ArticleRelativeSlug.php create mode 100644 tests/Gedmo/Sluggable/Issue/Issue2990Test.php diff --git a/src/Sluggable/Handler/RelativeSlugHandler.php b/src/Sluggable/Handler/RelativeSlugHandler.php index 2fdac40b9a..344da781f1 100644 --- a/src/Sluggable/Handler/RelativeSlugHandler.php +++ b/src/Sluggable/Handler/RelativeSlugHandler.php @@ -126,6 +126,10 @@ public function transliterate($text, $separator, $object) $this->originalTransliterator, [$slug, $separator, $object] ); + $slug = call_user_func_array( + $this->sluggable->getUrlizer(), + [$slug, $separator, $object] + ); } $result = $slug.$this->usedOptions['separator'].$result; diff --git a/tests/Gedmo/Sluggable/Fixture/Issue2990/Article.php b/tests/Gedmo/Sluggable/Fixture/Issue2990/Article.php new file mode 100644 index 0000000000..5350bef102 --- /dev/null +++ b/tests/Gedmo/Sluggable/Fixture/Issue2990/Article.php @@ -0,0 +1,91 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Sluggable\Fixture\Issue2990; + +use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Mapping as ORM; +use Gedmo\Mapping\Annotation as Gedmo; +use Gedmo\Sluggable\Handler\InversedRelativeSlugHandler; +use Gedmo\Sluggable\Sluggable; + +/** + * @ORM\Entity + */ +#[ORM\Entity] +class Article implements Sluggable +{ + /** + * @var int|null + * + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: Types::INTEGER)] + private $id; + + /** + * @ORM\Column(name="title", type="string", length=64) + */ + #[ORM\Column(name: 'title', type: Types::STRING, length: 64)] + private ?string $title = null; + + /** + * @var string|null + * + * @Gedmo\Slug(handlers={ + * @Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\InversedRelativeSlugHandler", options={ + * @Gedmo\SlugHandlerOption(name="relationClass", value="Gedmo\Tests\Sluggable\Fixture\Handler\ArticleRelativeSlug"), + * @Gedmo\SlugHandlerOption(name="mappedBy", value="article"), + * @Gedmo\SlugHandlerOption(name="inverseSlugField", value="slug") + * }) + * }, separator="-", updatable=true, fields={"title"}) + * + * @ORM\Column(name="slug", type="string", length=64, unique=true) + */ + #[Gedmo\Slug(separator: '-', updatable: true, fields: ['title'])] + #[Gedmo\SlugHandler(class: InversedRelativeSlugHandler::class, options: ['relationClass' => ArticleRelativeSlug::class, 'mappedBy' => 'article', 'inverseSlugField' => 'slug'])] + #[ORM\Column(name: 'slug', type: Types::STRING, length: 64, unique: true)] + private $slug; + + public function getId(): ?int + { + return $this->id; + } + + public function setTitle(?string $title): void + { + $this->title = $title; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setCode(?string $code): void + { + $this->code = $code; + } + + public function getCode(): ?string + { + return $this->code; + } + + public function getSlug(): ?string + { + return $this->slug; + } +} diff --git a/tests/Gedmo/Sluggable/Fixture/Issue2990/ArticleRelativeSlug.php b/tests/Gedmo/Sluggable/Fixture/Issue2990/ArticleRelativeSlug.php new file mode 100644 index 0000000000..c745e2b051 --- /dev/null +++ b/tests/Gedmo/Sluggable/Fixture/Issue2990/ArticleRelativeSlug.php @@ -0,0 +1,97 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Sluggable\Fixture\Issue2990; + +use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Mapping as ORM; +use Gedmo\Mapping\Annotation as Gedmo; +use Gedmo\Sluggable\Handler\RelativeSlugHandler; + +/** + * @ORM\Entity + */ +#[ORM\Entity] +class ArticleRelativeSlug +{ + /** + * @var int|null + * + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: Types::INTEGER)] + private $id; + + /** + * @ORM\Column(length=64) + */ + #[ORM\Column(length: 64)] + private ?string $title = null; + + /** + * @var string|null + * + * @Gedmo\Slug(handlers={ + * @Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\RelativeSlugHandler", options={ + * @Gedmo\SlugHandlerOption(name="relationField", value="article"), + * @Gedmo\SlugHandlerOption(name="relationSlugField", value="slug"), + * @Gedmo\SlugHandlerOption(name="separator", value="/"), + * @Gedmo\SlugHandlerOption(name="urilize", value=true) + * }) + * }, separator="-", updatable=true, fields={"title"}) + * + * @ORM\Column(name="slug", type="string", length=64, unique=true) + */ + #[Gedmo\Slug(separator: '-', updatable: true, fields: ['title'])] + #[Gedmo\SlugHandler(class: RelativeSlugHandler::class, options: ['relationField' => 'article', 'relationSlugField' => 'title', 'separator' => '/', 'urilize' => true])] + #[ORM\Column(name: 'slug', type: Types::STRING, length: 64, unique: true)] + private $slug; + + /** + * @ORM\ManyToOne(targetEntity="Article") + */ + #[ORM\ManyToOne(targetEntity: Article::class)] + private ?Article $article = null; + + public function setArticle(?Article $article = null): void + { + $this->article = $article; + } + + public function getArticle(): ?Article + { + return $this->article; + } + + public function getId(): ?int + { + return $this->id; + } + + public function setTitle(?string $title): void + { + $this->title = $title; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function getSlug(): ?string + { + return $this->slug; + } +} diff --git a/tests/Gedmo/Sluggable/Issue/Issue2990Test.php b/tests/Gedmo/Sluggable/Issue/Issue2990Test.php new file mode 100644 index 0000000000..75a539cda6 --- /dev/null +++ b/tests/Gedmo/Sluggable/Issue/Issue2990Test.php @@ -0,0 +1,67 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Sluggable\Issue; + +use Doctrine\Common\EventManager; +use Gedmo\Sluggable\SluggableListener; +use Gedmo\Tests\Sluggable\Fixture\Issue2990\Article; +use Gedmo\Tests\Sluggable\Fixture\Issue2990\ArticleRelativeSlug; +use Gedmo\Tests\Tool\BaseTestCaseORM; + +/** + * These are tests for sluggable behavior + * + * @author Gediminas Morkevicius + */ +final class Issue2990Test extends BaseTestCaseORM +{ + protected function setUp(): void + { + parent::setUp(); + + $evm = new EventManager(); + $evm->addEventSubscriber(new SluggableListener()); + + $this->getDefaultMockSqliteEntityManager($evm); + } + + /** + * @group issue2990 + */ + public function testShouldHandleUrilizeProperly(): void + { + $article = new Article(); + $article->setTitle('My Title'); + + $this->em->persist($article); + $this->em->flush(); + + static::assertSame('my-title', $article->getSlug()); + + $relative = new ArticleRelativeSlug(); + $relative->setTitle('The Title'); + $relative->setArticle($article); + + $this->em->persist($relative); + $this->em->flush(); + + static::assertSame('my-title/the-title', $relative->getSlug()); + } + + protected function getUsedEntityFixtures(): array + { + return [ + Article::class, + ArticleRelativeSlug::class, + ]; + } +}