Skip to content

Commit feedb02

Browse files
committed
1 parent 8d658b4 commit feedb02

File tree

3 files changed

+279
-0
lines changed

3 files changed

+279
-0
lines changed

composer.json

+3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@
6464
"phpstan/phpstan-doctrine": "^1.0",
6565
"phpstan/phpstan-phpunit": "^1.0",
6666
"phpunit/phpunit": "^9.6",
67+
"psr/container": "^1.0 | ^2.0",
6768
"rector/rector": "^0.19",
6869
"symfony/console": "^5.4 || ^6.0 || ^7.0",
70+
"symfony/doctrine-bridge": "^5.4 || ^6.0 || ^7.0",
6971
"symfony/phpunit-bridge": "^6.0 || ^7.0",
72+
"symfony/uid": "^5.4 || ^6.0 || ^7.0",
7073
"symfony/yaml": "^5.4 || ^6.0 || ^7.0"
7174
},
7275
"conflict": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Doctrine Behavioral Extensions package.
7+
* (c) Gediminas Morkevicius <[email protected]> http://www.gediminasm.org
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Gedmo\Tests\Tree\Fixture\Issue2701;
13+
14+
use Doctrine\Common\Collections\ArrayCollection;
15+
use Doctrine\Common\Collections\Collection;
16+
use Doctrine\DBAL\Types\Types;
17+
use Doctrine\ORM\Mapping as ORM;
18+
use Gedmo\Mapping\Annotation as Gedmo;
19+
use Gedmo\Tree\Entity\Repository\NestedTreeRepository;
20+
use Symfony\Bridge\Doctrine\Types\UlidType;
21+
use Symfony\Component\Uid\Ulid;
22+
23+
/**
24+
* @Gedmo\Tree(type="nested")
25+
*
26+
* @ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\NestedTreeRepository")
27+
* @ORM\Table(indexes={@ORM\Index(columns={"lft", "rgt"}, name="idx_tree")})
28+
*/
29+
#[Gedmo\Tree(type: 'nested')]
30+
#[ORM\Entity(repositoryClass: NestedTreeRepository::class)]
31+
#[ORM\Index(columns: ['lft', 'rgt'], name: 'idx_tree')]
32+
class Category
33+
{
34+
/**
35+
* @ORM\Column(type="ulid", unique=true)
36+
* @ORM\Id
37+
* @ORM\GeneratedValue(strategy="CUSTOM")
38+
* @ORM\CustomIdGenerator(class="doctrine.ulid_generator")
39+
*/
40+
#[ORM\Id]
41+
#[ORM\Column(type: UlidType::NAME, unique: true)]
42+
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
43+
#[ORM\CustomIdGenerator(class: 'doctrine.ulid_generator')]
44+
private ?Ulid $id = null;
45+
46+
/**
47+
* @ORM\Column(length=255)
48+
*/
49+
#[ORM\Column(length: 255)]
50+
private ?string $name = null;
51+
52+
/**
53+
* @Gedmo\TreeLeft
54+
*
55+
* @ORM\Column(name="lft", type="integer")
56+
*/
57+
#[Gedmo\TreeLeft]
58+
#[ORM\Column(name: 'lft', type: Types::INTEGER)]
59+
public ?int $lft;
60+
61+
/**
62+
* @Gedmo\TreeLevel
63+
*
64+
* @ORM\Column(name="lvl", type="integer")
65+
*/
66+
#[Gedmo\TreeLevel]
67+
#[ORM\Column(name: 'lvl', type: Types::INTEGER)]
68+
private ?int $lvl;
69+
70+
/**
71+
* @Gedmo\TreeRight
72+
*
73+
* @ORM\Column(name="rgt", type="integer")
74+
*/
75+
#[Gedmo\TreeRight]
76+
#[ORM\Column(name: 'rgt', type: Types::INTEGER)]
77+
public ?int $rgt;
78+
79+
/**
80+
* @Gedmo\TreeRoot
81+
*
82+
* @ORM\ManyToOne(targetEntity="Gedmo\Tests\Tree\Fixture\Issue2701\Category")
83+
* @ORM\JoinColumn(name="tree_root", referencedColumnName="id", onDelete="CASCADE")
84+
*/
85+
#[Gedmo\TreeRoot]
86+
#[ORM\ManyToOne(targetEntity: self::class)]
87+
#[ORM\JoinColumn(name: 'tree_root', referencedColumnName: 'id', onDelete: 'CASCADE')]
88+
private ?self $root;
89+
90+
/**
91+
* @Gedmo\TreeParent
92+
*
93+
* @ORM\ManyToOne(targetEntity="Gedmo\Tests\Tree\Fixture\Issue2701\Category", inversedBy="children")
94+
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
95+
*/
96+
#[Gedmo\TreeParent]
97+
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
98+
#[ORM\JoinColumn(name: 'parent_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
99+
private ?self $parent;
100+
101+
/**
102+
* @var Collection<int, self>|self[]
103+
*
104+
* @ORM\OneToMany(targetEntity="Gedmo\Tests\Tree\Fixture\Issue2701\Category", mappedBy="parent")
105+
* @ORM\OrderBy({"lft" = "ASC"})
106+
*/
107+
#[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')]
108+
#[ORM\OrderBy(['lft' => 'ASC'])]
109+
private Collection $children;
110+
111+
public function __construct()
112+
{
113+
$this->children = new ArrayCollection();
114+
}
115+
116+
public function getId(): ?Ulid
117+
{
118+
return $this->id;
119+
}
120+
121+
public function getName(): ?string
122+
{
123+
return $this->name;
124+
}
125+
126+
public function setName(string $name): static
127+
{
128+
$this->name = $name;
129+
130+
return $this;
131+
}
132+
133+
public function setTranslatableLocale(string $locale): void
134+
{
135+
$this->locale = $locale;
136+
}
137+
138+
public function getRoot(): ?self
139+
{
140+
return $this->root;
141+
}
142+
143+
public function setParent(?self $parent = null): void
144+
{
145+
$this->parent = $parent;
146+
}
147+
148+
public function getParent(): ?self
149+
{
150+
return $this->parent;
151+
}
152+
}
+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Doctrine Behavioral Extensions package.
7+
* (c) Gediminas Morkevicius <[email protected]> http://www.gediminasm.org
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Gedmo\Tests\Tree\Issue;
13+
14+
use Doctrine\Bundle\DoctrineBundle\Mapping\ClassMetadataFactory;
15+
use Doctrine\Bundle\DoctrineBundle\Mapping\MappingDriver;
16+
use Doctrine\Common\EventManager;
17+
use Doctrine\DBAL\Types\Type;
18+
use Doctrine\Persistence\Mapping\Driver\MappingDriver as MappingDriverInterface;
19+
use Gedmo\Tests\Tool\BaseTestCaseORM;
20+
use Gedmo\Tests\Tree\Fixture\Issue2701\Category;
21+
use Gedmo\Tree\TreeListener;
22+
use Psr\Container\ContainerInterface;
23+
use Psr\Container\NotFoundExceptionInterface;
24+
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
25+
use Symfony\Bridge\Doctrine\Types\UlidType;
26+
use Symfony\Component\Uid\Factory\UlidFactory;
27+
28+
final class Issue2701Test extends BaseTestCaseORM
29+
{
30+
private TreeListener $listener;
31+
32+
protected function setUp(): void
33+
{
34+
parent::setUp();
35+
36+
$this->listener = new TreeListener();
37+
38+
$evm = new EventManager();
39+
$evm->addEventSubscriber($this->listener);
40+
41+
$config = $this->getDefaultConfiguration();
42+
$config->setClassMetadataFactoryName(ClassMetadataFactory::class);
43+
44+
$mappingDriver = $config->getMetadataDriverImpl();
45+
46+
assert($mappingDriver instanceof MappingDriverInterface);
47+
48+
$config->setMetadataDriverImpl(new MappingDriver($mappingDriver, $this->createIdGeneratorLocator()));
49+
50+
Type::addType(UlidType::NAME, UlidType::class);
51+
52+
$this->getDefaultMockSqliteEntityManager($evm, $config);
53+
}
54+
55+
protected function tearDown(): void
56+
{
57+
parent::tearDown();
58+
59+
// To avoid state bleedout between test cases, we will clear the type registry using brute force
60+
$refl = (new \ReflectionClass(Type::class))->getProperty('typeRegistry');
61+
$refl->setAccessible(true);
62+
$refl->setValue(Type::class, null);
63+
}
64+
65+
public function testGetNextSiblingsWithoutIdentifierMethod(): void
66+
{
67+
$food = new Category();
68+
$food->setName('Food');
69+
70+
$fruits = new Category();
71+
$fruits->setName('Fruits');
72+
$fruits->setParent($food);
73+
74+
$vegetables = new Category();
75+
$vegetables->setName('Vegetables');
76+
$vegetables->setParent($food);
77+
78+
$carrots = new Category();
79+
$carrots->setName('Carrots');
80+
$carrots->setParent($vegetables);
81+
82+
$this->em->persist($food);
83+
$this->em->persist($fruits);
84+
$this->em->persist($vegetables);
85+
$this->em->persist($carrots);
86+
$this->em->flush();
87+
88+
$categoryRepository = $this->em->getRepository(Category::class);
89+
90+
static::assertTrue($categoryRepository->verify());
91+
}
92+
93+
protected function createIdGeneratorLocator(): ContainerInterface
94+
{
95+
return new class(new UlidGenerator(new UlidFactory())) implements ContainerInterface {
96+
private UlidGenerator $ulidGenerator;
97+
98+
public function __construct(UlidGenerator $ulidGenerator)
99+
{
100+
$this->ulidGenerator = $ulidGenerator;
101+
}
102+
103+
public function get(string $id)
104+
{
105+
if ('doctrine.ulid_generator' === $id) {
106+
return $this->ulidGenerator;
107+
}
108+
109+
throw new class(sprintf('Service ID "%s" not found.', $id)) extends \InvalidArgumentException implements NotFoundExceptionInterface {
110+
};
111+
}
112+
113+
public function has(string $id): bool
114+
{
115+
return 'doctrine.ulid_generator' === $id;
116+
}
117+
};
118+
}
119+
120+
protected function getUsedEntityFixtures(): array
121+
{
122+
return [Category::class];
123+
}
124+
}

0 commit comments

Comments
 (0)