From c2ba2a8e6f3b01dd6cc9c9c952dd7f5c6258e1da Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Fri, 3 Oct 2025 10:07:29 -0400 Subject: [PATCH] Add tests for entities using the urilize relative slug handler option --- .../Handler/People/UrilizedOccupation.php | 183 ++++++++++++++++++ .../Fixture/Handler/People/UrilizedPerson.php | 93 +++++++++ .../Fixture/Handler/UrilizedArticle.php | 97 ++++++++++ .../Handler/UrilizedArticleRelativeSlug.php | 97 ++++++++++ .../Handlers/BothSlugHandlerTest.php | 103 +++++++++- .../Handlers/RelativeSlugHandlerTest.php | 86 +++++++- 6 files changed, 657 insertions(+), 2 deletions(-) create mode 100644 tests/Gedmo/Sluggable/Fixture/Handler/People/UrilizedOccupation.php create mode 100644 tests/Gedmo/Sluggable/Fixture/Handler/People/UrilizedPerson.php create mode 100644 tests/Gedmo/Sluggable/Fixture/Handler/UrilizedArticle.php create mode 100644 tests/Gedmo/Sluggable/Fixture/Handler/UrilizedArticleRelativeSlug.php diff --git a/tests/Gedmo/Sluggable/Fixture/Handler/People/UrilizedOccupation.php b/tests/Gedmo/Sluggable/Fixture/Handler/People/UrilizedOccupation.php new file mode 100644 index 0000000000..bdd165fbce --- /dev/null +++ b/tests/Gedmo/Sluggable/Fixture/Handler/People/UrilizedOccupation.php @@ -0,0 +1,183 @@ + 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\Handler\People; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; +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\Handler\TreeSlugHandler; +use Gedmo\Tree\Entity\Repository\NestedTreeRepository; + +/** + * @Gedmo\Tree(type="nested") + * + * @ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\NestedTreeRepository") + */ +#[ORM\Entity(repositoryClass: NestedTreeRepository::class)] +#[Gedmo\Tree(type: 'nested')] +class UrilizedOccupation +{ + /** + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: Types::INTEGER)] + private ?int $id = null; + + /** + * @ORM\Column(length=64) + */ + #[ORM\Column(length: 64)] + private ?string $title = null; + + /** + * @Gedmo\Slug(handlers={ + * @Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\TreeSlugHandler", options={ + * @Gedmo\SlugHandlerOption(name="parentRelationField", value="parent"), + * @Gedmo\SlugHandlerOption(name="separator", value="/") + * }), + * @Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\InversedRelativeSlugHandler", options={ + * @Gedmo\SlugHandlerOption(name="relationClass", value="Gedmo\Tests\Sluggable\Fixture\Handler\People\UrilizedPerson"), + * @Gedmo\SlugHandlerOption(name="mappedBy", value="occupation"), + * @Gedmo\SlugHandlerOption(name="inverseSlugField", value="slug") + * }) + * }, fields={"title"}) + * + * @ORM\Column(length=64, unique=true) + */ + #[Gedmo\Slug(fields: ['title'])] + #[Gedmo\SlugHandler(class: TreeSlugHandler::class, options: ['parentRelationField' => 'parent', 'separator' => '/'])] + #[Gedmo\SlugHandler(class: InversedRelativeSlugHandler::class, options: ['relationClass' => UrilizedPerson::class, 'mappedBy' => 'occupation', 'inverseSlugField' => 'slug'])] + #[ORM\Column(length: 64, unique: true)] + private ?string $slug = null; + + /** + * @Gedmo\TreeParent + * + * @ORM\ManyToOne(targetEntity="UrilizedOccupation") + * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE") + */ + #[ORM\ManyToOne(targetEntity: self::class)] + #[ORM\JoinColumn(name: 'parent_id', referencedColumnName: 'id', onDelete: 'CASCADE')] + #[Gedmo\TreeParent] + private ?UrilizedOccupation $parent = null; + + /** + * @var Collection + */ + private Collection $children; + + /** + * @Gedmo\TreeLeft + * + * @ORM\Column(type="integer") + */ + #[ORM\Column(type: Types::INTEGER)] + #[Gedmo\TreeLeft] + private ?int $lft = null; + + /** + * @Gedmo\TreeRight + * + * @ORM\Column(type="integer") + */ + #[ORM\Column(type: Types::INTEGER)] + #[Gedmo\TreeRight] + private ?int $rgt = null; + + /** + * @Gedmo\TreeRoot + * + * @ORM\Column(type="integer") + */ + #[ORM\Column(type: Types::INTEGER)] + #[Gedmo\TreeRoot] + private ?int $root = null; + + /** + * @Gedmo\TreeLevel + * + * @ORM\Column(name="lvl", type="integer") + */ + #[ORM\Column(name: 'lvl', type: Types::INTEGER)] + #[Gedmo\TreeLevel] + private ?int $level = null; + + public function __construct() + { + $this->children = new ArrayCollection(); + } + + public function setParent(?self $parent = null): void + { + $this->parent = $parent; + } + + /** + * @return Collection + */ + public function getChildren(): Collection + { + return $this->children; + } + + public function getParent(): ?self + { + return $this->parent; + } + + public function getRoot(): ?int + { + return $this->root; + } + + public function getLeft(): ?int + { + return $this->lft; + } + + public function getRight(): ?int + { + return $this->rgt; + } + + public function getLevel(): ?int + { + return $this->level; + } + + 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/Fixture/Handler/People/UrilizedPerson.php b/tests/Gedmo/Sluggable/Fixture/Handler/People/UrilizedPerson.php new file mode 100644 index 0000000000..655c152877 --- /dev/null +++ b/tests/Gedmo/Sluggable/Fixture/Handler/People/UrilizedPerson.php @@ -0,0 +1,93 @@ + 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\Handler\People; + +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 UrilizedPerson +{ + /** + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: Types::INTEGER)] + private ?int $id = null; + + /** + * @ORM\Column(length=64) + */ + #[ORM\Column(length: 64)] + private ?string $name = null; + + /** + * @Gedmo\Slug(handlers={ + * @Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\RelativeSlugHandler", options={ + * @Gedmo\SlugHandlerOption(name="relationField", value="occupation"), + * @Gedmo\SlugHandlerOption(name="relationSlugField", value="slug"), + * @Gedmo\SlugHandlerOption(name="separator", value="/"), + * @Gedmo\SlugHandlerOption(name="urilize", value=true), + * }) + * }, separator="-", updatable=true, fields={"name"}) + * + * @ORM\Column(name="slug", type="string", length=64, unique=true) + */ + #[Gedmo\Slug(separator: '-', updatable: true, fields: ['name'])] + #[Gedmo\SlugHandler(class: RelativeSlugHandler::class, options: ['relationField' => 'occupation', 'relationSlugField' => 'slug', 'separator' => '/', 'urilize' => true])] + #[ORM\Column(name: 'slug', type: Types::STRING, length: 64, unique: true)] + private ?string $slug = null; + + /** + * @ORM\ManyToOne(targetEntity="UrilizedOccupation") + */ + #[ORM\ManyToOne(targetEntity: UrilizedOccupation::class)] + private ?UrilizedOccupation $occupation = null; + + public function setOccupation(?UrilizedOccupation $occupation = null): void + { + $this->occupation = $occupation; + } + + public function getOccupation(): ?UrilizedOccupation + { + return $this->occupation; + } + + public function getId(): ?int + { + return $this->id; + } + + public function setName(?string $name): void + { + $this->name = $name; + } + + public function getName(): ?string + { + return $this->name; + } + + public function getSlug(): ?string + { + return $this->slug; + } +} diff --git a/tests/Gedmo/Sluggable/Fixture/Handler/UrilizedArticle.php b/tests/Gedmo/Sluggable/Fixture/Handler/UrilizedArticle.php new file mode 100644 index 0000000000..706b7dfcf5 --- /dev/null +++ b/tests/Gedmo/Sluggable/Fixture/Handler/UrilizedArticle.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\Handler; + +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 UrilizedArticle 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; + + /** + * @ORM\Column(name="code", type="string", length=16) + */ + #[ORM\Column(name: 'code', type: Types::STRING, length: 16)] + private ?string $code = 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\UrilizedArticleRelativeSlug"), + * @Gedmo\SlugHandlerOption(name="mappedBy", value="article"), + * @Gedmo\SlugHandlerOption(name="inverseSlugField", value="slug") + * }) + * }, separator="-", updatable=true, fields={"title", "code"}) + * + * @ORM\Column(name="slug", type="string", length=64, unique=true) + */ + #[Gedmo\Slug(separator: '-', updatable: true, fields: ['title', 'code'])] + #[Gedmo\SlugHandler(class: InversedRelativeSlugHandler::class, options: ['relationClass' => UrilizedArticleRelativeSlug::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/Handler/UrilizedArticleRelativeSlug.php b/tests/Gedmo/Sluggable/Fixture/Handler/UrilizedArticleRelativeSlug.php new file mode 100644 index 0000000000..3f8d8ae613 --- /dev/null +++ b/tests/Gedmo/Sluggable/Fixture/Handler/UrilizedArticleRelativeSlug.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\Handler; + +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 UrilizedArticleRelativeSlug +{ + /** + * @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' => 'slug', 'separator' => '/', 'urilize' => true])] + #[ORM\Column(name: 'slug', type: Types::STRING, length: 64, unique: true)] + private $slug; + + /** + * @ORM\ManyToOne(targetEntity="UrilizedArticle") + */ + #[ORM\ManyToOne(targetEntity: UrilizedArticle::class)] + private ?UrilizedArticle $article = null; + + public function setArticle(?UrilizedArticle $article = null): void + { + $this->article = $article; + } + + public function getArticle(): ?UrilizedArticle + { + 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/Handlers/BothSlugHandlerTest.php b/tests/Gedmo/Sluggable/Handlers/BothSlugHandlerTest.php index 7fe2424552..d1484bc9f0 100644 --- a/tests/Gedmo/Sluggable/Handlers/BothSlugHandlerTest.php +++ b/tests/Gedmo/Sluggable/Handlers/BothSlugHandlerTest.php @@ -15,6 +15,8 @@ use Gedmo\Sluggable\SluggableListener; use Gedmo\Tests\Sluggable\Fixture\Handler\People\Occupation; use Gedmo\Tests\Sluggable\Fixture\Handler\People\Person; +use Gedmo\Tests\Sluggable\Fixture\Handler\People\UrilizedOccupation; +use Gedmo\Tests\Sluggable\Fixture\Handler\People\UrilizedPerson; use Gedmo\Tests\Tool\BaseTestCaseORM; use Gedmo\Tree\TreeListener; @@ -49,6 +51,17 @@ public function testSlugGeneration(): void $hurty = $repo->findOneBy(['name' => 'Hurty']); static::assertSame('singer/hurty', $hurty->getSlug()); + + $repo = $this->em->getRepository(UrilizedPerson::class); + + $herzult = $repo->findOneBy(['name' => 'Herzult']); + static::assertSame('web/developer/php/herzult', $herzult->getSlug()); + + $gedi = $repo->findOneBy(['name' => 'Gedi']); + static::assertSame('web/developer/gedi', $gedi->getSlug()); + + $hurty = $repo->findOneBy(['name' => 'Hurty']); + static::assertSame('singer/hurty', $hurty->getSlug()); } public function testSlugUpdates(): void @@ -77,6 +90,30 @@ public function testSlugUpdates(): void $hurty = $repo->findOneBy(['name' => 'Hurty']); static::assertSame('artist/hurty', $hurty->getSlug()); + + $repo = $this->em->getRepository(UrilizedPerson::class); + + $gedi = $repo->findOneBy(['name' => 'Gedi']); + $gedi->setName('Upd Gedi'); + $this->em->persist($gedi); + $this->em->flush(); + + static::assertSame('web/developer/upd-gedi', $gedi->getSlug()); + + $artist = $this->em->getRepository(UrilizedOccupation::class)->findOneBy(['title' => 'Singer']); + $artist->setTitle('Artist'); + + $this->em->persist($artist); + $this->em->flush(); + + $gedi->setOccupation($artist); + $this->em->persist($gedi); + $this->em->flush(); + + static::assertSame('artist/upd-gedi', $gedi->getSlug()); + + $hurty = $repo->findOneBy(['name' => 'Hurty']); + static::assertSame('artist/hurty', $hurty->getSlug()); } public function test1093(): void @@ -110,10 +147,20 @@ protected function getUsedEntityFixtures(): array return [ Occupation::class, Person::class, + UrilizedOccupation::class, + UrilizedPerson::class, ]; } private function populate(): void + { + $this->populateEntities(); + $this->populateUrilizedEntities(); + + $this->em->flush(); + } + + private function populateEntities(): void { $repo = $this->em->getRepository(Occupation::class); @@ -167,7 +214,61 @@ private function populate(): void $hurty->setName('Hurty'); $hurty->setOccupation($singer); $this->em->persist($hurty); + } - $this->em->flush(); + private function populateUrilizedEntities(): void + { + $repo = $this->em->getRepository(UrilizedOccupation::class); + + $web = new UrilizedOccupation(); + $web->setTitle('Web'); + + $developer = new UrilizedOccupation(); + $developer->setTitle('Developer'); + + $designer = new UrilizedOccupation(); + $designer->setTitle('Designer'); + + $php = new UrilizedOccupation(); + $php->setTitle('PHP'); + + $singer = new UrilizedOccupation(); + $singer->setTitle('Singer'); + + $rock = new UrilizedOccupation(); + $rock->setTitle('Rock'); + + // Singer + // > Hurty + // -- Rock + // Web + // -- Designer + // -- Developer + // -- -- PHP + // -- -- > Herzult + // -- > Gedi + $repo + ->persistAsFirstChild($web) + ->persistAsFirstChild($singer) + ->persistAsFirstChildOf($developer, $web) + ->persistAsFirstChildOf($designer, $web) + ->persistAsLastChildOf($php, $developer) + ->persistAsLastChildOf($rock, $singer) + ; + + $herzult = new UrilizedPerson(); + $herzult->setName('Herzult'); + $herzult->setOccupation($php); + $this->em->persist($herzult); + + $gedi = new UrilizedPerson(); + $gedi->setName('Gedi'); + $gedi->setOccupation($developer); + $this->em->persist($gedi); + + $hurty = new UrilizedPerson(); + $hurty->setName('Hurty'); + $hurty->setOccupation($singer); + $this->em->persist($hurty); } } diff --git a/tests/Gedmo/Sluggable/Handlers/RelativeSlugHandlerTest.php b/tests/Gedmo/Sluggable/Handlers/RelativeSlugHandlerTest.php index 95478ff05d..7b322f6728 100644 --- a/tests/Gedmo/Sluggable/Handlers/RelativeSlugHandlerTest.php +++ b/tests/Gedmo/Sluggable/Handlers/RelativeSlugHandlerTest.php @@ -15,6 +15,8 @@ use Gedmo\Sluggable\SluggableListener; use Gedmo\Tests\Sluggable\Fixture\Handler\Article; use Gedmo\Tests\Sluggable\Fixture\Handler\ArticleRelativeSlug; +use Gedmo\Tests\Sluggable\Fixture\Handler\UrilizedArticle; +use Gedmo\Tests\Sluggable\Fixture\Handler\UrilizedArticleRelativeSlug; use Gedmo\Tests\Tool\BaseTestCaseORM; /** @@ -50,6 +52,20 @@ public function testSlugGeneration(): void $single = $repo->findOneBy(['title' => 'Single']); static::assertSame('single', $single->getSlug()); + + $repo = $this->em->getRepository(UrilizedArticleRelativeSlug::class); + + $thomas = $repo->findOneBy(['title' => 'Thomas']); + static::assertSame('sport-test/thomas', $thomas->getSlug()); + + $jen = $repo->findOneBy(['title' => 'Jen']); + static::assertSame('sport-test/jen', $jen->getSlug()); + + $john = $repo->findOneBy(['title' => 'John']); + static::assertSame('cars-code/john', $john->getSlug()); + + $single = $repo->findOneBy(['title' => 'Single']); + static::assertSame('single', $single->getSlug()); } public function testUpdateOperations(): void @@ -82,6 +98,34 @@ public function testUpdateOperations(): void $this->em->flush(); static::assertSame('cars-code/jen', $jen->getSlug()); + + $repo = $this->em->getRepository(UrilizedArticleRelativeSlug::class); + + $thomas = $repo->findOneBy(['title' => 'Thomas']); + $thomas->setTitle('Ninja'); + $this->em->persist($thomas); + $this->em->flush(); + + static::assertSame('sport-test/ninja', $thomas->getSlug()); + + $sport = $this->em->getRepository(UrilizedArticle::class)->findOneBy(['title' => 'Sport']); + $sport->setTitle('Martial Arts'); + + $this->em->persist($sport); + $this->em->flush(); + + static::assertSame('martial-arts-test/ninja', $thomas->getSlug()); + + $jen = $repo->findOneBy(['title' => 'Jen']); + static::assertSame('martial-arts-test/jen', $jen->getSlug()); + + $cars = $this->em->getRepository(UrilizedArticle::class)->findOneBy(['title' => 'Cars']); + $jen->setArticle($cars); + + $this->em->persist($jen); + $this->em->flush(); + + static::assertSame('cars-code/jen', $jen->getSlug()); } protected function getUsedEntityFixtures(): array @@ -89,10 +133,20 @@ protected function getUsedEntityFixtures(): array return [ ArticleRelativeSlug::class, Article::class, + UrilizedArticleRelativeSlug::class, + UrilizedArticle::class, ]; } private function populate(): void + { + $this->populateArticles(); + $this->populateUrilizedArticles(); + + $this->em->flush(); + } + + private function populateArticles(): void { $sport = new Article(); $sport->setTitle('Sport'); @@ -122,7 +176,37 @@ private function populate(): void $single = new ArticleRelativeSlug(); $single->setTitle('Single'); $this->em->persist($single); + } - $this->em->flush(); + private function populateUrilizedArticles(): void + { + $sport = new UrilizedArticle(); + $sport->setTitle('Sport'); + $sport->setCode('test'); + $this->em->persist($sport); + + $cars = new UrilizedArticle(); + $cars->setTitle('Cars'); + $cars->setCode('code'); + $this->em->persist($cars); + + $thomas = new UrilizedArticleRelativeSlug(); + $thomas->setTitle('Thomas'); + $thomas->setArticle($sport); + $this->em->persist($thomas); + + $jen = new UrilizedArticleRelativeSlug(); + $jen->setTitle('Jen'); + $jen->setArticle($sport); + $this->em->persist($jen); + + $john = new UrilizedArticleRelativeSlug(); + $john->setTitle('John'); + $john->setArticle($cars); + $this->em->persist($john); + + $single = new UrilizedArticleRelativeSlug(); + $single->setTitle('Single'); + $this->em->persist($single); } }