Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a04cfae

Browse filesBrowse files
committed
[DoctrineBridge] Add argument to EntityValueResolver to set type aliases
This allows for fixing #51765; with a consequential Doctrine bundle update, the resolve_target_entities configuration can be injected similarly to ResolveTargetEntityListener in the Doctrine codebase. Alternatively the config and ValueResolver can be injected using a compiler pass in the Symfony core code, however the value resolver seems to be configured in the Doctrine bundle already.
1 parent 9b323c6 commit a04cfae
Copy full SHA for a04cfae

File tree

4 files changed

+59
-1
lines changed
Filter options

4 files changed

+59
-1
lines changed

‎src/Symfony/Bridge/Doctrine/ArgumentResolver/EntityValueResolver.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/ArgumentResolver/EntityValueResolver.php
+21
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,27 @@
3131
*/
3232
final class EntityValueResolver implements ValueResolverInterface
3333
{
34+
/** @var array<class-string, class-string> */
35+
private array $typeAliases = [];
36+
3437
public function __construct(
3538
private ManagerRegistry $registry,
3639
private ?ExpressionLanguage $expressionLanguage = null,
3740
private MapEntity $defaults = new MapEntity(),
3841
) {
3942
}
4043

44+
/**
45+
* Adds an original class name to resolve to a target class name.
46+
*
47+
* @param class-string $original
48+
* @param class-string $target
49+
*/
50+
public function addTypeAlias(string $original, string $target): void
51+
{
52+
$this->typeAliases[ltrim($original, '\\')] = ltrim($target, '\\');
53+
}
54+
4155
public function resolve(Request $request, ArgumentMetadata $argument): array
4256
{
4357
if (\is_object($request->attributes->get($argument->getName()))) {
@@ -50,6 +64,13 @@ public function resolve(Request $request, ArgumentMetadata $argument): array
5064
if (!$options->class || $options->disabled) {
5165
return [];
5266
}
67+
68+
if (isset($this->typeAliases[$options->class])) {
69+
// Overwriting the property of MapEntity at this point is safe,
70+
// since withDefaults called above created a clone of the original object.
71+
$options->class = $this->typeAliases[$options->class];
72+
}
73+
5374
if (!$manager = $this->getManager($options->objectManager, $options->class)) {
5475
return [];
5576
}

‎src/Symfony/Bridge/Doctrine/Attribute/MapEntity.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/Attribute/MapEntity.php
+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public function __construct(
5252
public function withDefaults(self $defaults, ?string $class): static
5353
{
5454
$clone = clone $this;
55-
$clone->class ??= class_exists($class ?? '') ? $class : null;
55+
$clone->class ??= class_exists($class ?? '') || interface_exists($class ?? '', false) ? $class : null;
5656
$clone->objectManager ??= $defaults->objectManager;
5757
$clone->expr ??= $defaults->expr;
5858
$clone->mapping ??= $defaults->mapping;

‎src/Symfony/Bridge/Doctrine/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/CHANGELOG.md
+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
7.1
55
---
66

7+
* Add type aliases support to `EntityValueResolver` through the `addTypeAlias` method
78
* Deprecate the `DoctrineExtractor::getTypes()` method, use `DoctrineExtractor::getType()` instead
89

910
7.0

‎src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php
+36
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,42 @@ public function testResolveWithId(string|int $id)
130130
$this->assertSame([$object], $resolver->resolve($request, $argument));
131131
}
132132

133+
/**
134+
* @dataProvider idsProvider
135+
*/
136+
public function testResolveWithIdAndTypeAlias(string|int $id)
137+
{
138+
$manager = $this->getMockBuilder(ObjectManager::class)->getMock();
139+
$registry = $this->createRegistry($manager);
140+
$resolver = new EntityValueResolver(
141+
$registry,
142+
null,
143+
new MapEntity(),
144+
);
145+
// Using \Throwable here because it is built in to PHP and an interface.
146+
$resolver->addTypeAlias('Throwable', 'stdClass');
147+
148+
$request = new Request();
149+
$request->attributes->set('id', $id);
150+
151+
$argument = $this->createArgument('Throwable', $mapEntity = new MapEntity(id: 'id'));
152+
153+
$repository = $this->getMockBuilder(ObjectRepository::class)->getMock();
154+
$repository->expects($this->once())
155+
->method('find')
156+
->with($id)
157+
->willReturn($object = new \stdClass());
158+
159+
$manager->expects($this->once())
160+
->method('getRepository')
161+
->with('stdClass')
162+
->willReturn($repository);
163+
164+
$this->assertSame([$object], $resolver->resolve($request, $argument));
165+
// Ensure the original MapEntity object was not updated
166+
$this->assertNull($mapEntity->class);
167+
}
168+
133169
public function testResolveWithNullId()
134170
{
135171
$manager = $this->getMockBuilder(ObjectManager::class)->getMock();

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.