From f748096ad7518f901fac1ea295d4f7379e5201d9 Mon Sep 17 00:00:00 2001 From: NanoSector Date: Thu, 11 Apr 2024 20:05:28 +0200 Subject: [PATCH] Wire up type aliases support in EntityValueResolver This is an addendum to PR https://github.com/symfony/symfony/issues/51765 in the Symfony Doctrine Bridge, which adds type alias support to EntityValueResolver. This code injects the doctrine.orm.resolve_target_entities configuration into the EntityValueResolver class. --- src/DependencyInjection/DoctrineExtension.php | 17 +++++++++++++++++ tests/ContainerTest.php | 6 ++++++ .../DoctrineExtensionTest.php | 13 ++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/DependencyInjection/DoctrineExtension.php b/src/DependencyInjection/DoctrineExtension.php index 161626a7a..30ffc6e81 100644 --- a/src/DependencyInjection/DoctrineExtension.php +++ b/src/DependencyInjection/DoctrineExtension.php @@ -32,6 +32,7 @@ use Doctrine\Persistence\Reflection\RuntimeReflectionProperty; use InvalidArgumentException; use LogicException; +use ReflectionClass; use Symfony\Bridge\Doctrine\ArgumentResolver\EntityValueResolver; use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Bridge\Doctrine\DependencyInjection\AbstractDoctrineExtension; @@ -625,6 +626,22 @@ protected function ormLoad(array $config, ContainerBuilder $container) $def ->addTag('doctrine.event_listener', ['event' => Events::loadClassMetadata]) ->addTag('doctrine.event_listener', ['event' => Events::onClassMetadataNotFound]); + + // Symfony 7.1 and higher expose type alias support in the EntityValueResolver + if (class_exists(EntityValueResolver::class)) { + $valueResolverReflection = new ReflectionClass(EntityValueResolver::class); + + if ($valueResolverReflection->hasMethod('addTypeAlias')) { + $valueResolverDefinition = $container->getDefinition('doctrine.orm.entity_value_resolver'); + + foreach ($config['resolve_target_entities'] as $name => $implementation) { + $valueResolverDefinition->addMethodCall('addTypeAlias', [ + $name, + $implementation, + ]); + } + } + } } $container->registerForAutoconfiguration(ServiceEntityRepositoryInterface::class) diff --git a/tests/ContainerTest.php b/tests/ContainerTest.php index 54a6b26b3..e03154e8f 100644 --- a/tests/ContainerTest.php +++ b/tests/ContainerTest.php @@ -15,6 +15,7 @@ use Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\Mapping\Driver\MappingDriverChain; +use Symfony\Bridge\Doctrine\ArgumentResolver\EntityValueResolver; use Symfony\Bridge\Doctrine\CacheWarmer\ProxyCacheWarmer; use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector; use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor; @@ -23,6 +24,7 @@ use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\PhpArrayAdapter; +use function class_exists; use function interface_exists; class ContainerTest extends TestCase @@ -39,6 +41,10 @@ public function testContainer(): void $this->assertInstanceOf(Reader::class, $container->get('doctrine.orm.metadata.annotation_reader')); } + if (class_exists(EntityValueResolver::class)) { + $this->assertInstanceOf(EntityValueResolver::class, $container->get('doctrine.orm.entity_value_resolver')); + } + $this->assertInstanceOf(DoctrineDataCollector::class, $container->get('data_collector.doctrine')); $this->assertInstanceOf(DBALConfiguration::class, $container->get('doctrine.dbal.default_connection.configuration')); $this->assertInstanceOf(EventManager::class, $container->get('doctrine.dbal.default_connection.event_manager')); diff --git a/tests/DependencyInjection/DoctrineExtensionTest.php b/tests/DependencyInjection/DoctrineExtensionTest.php index b2a6e3c4e..4696582bf 100644 --- a/tests/DependencyInjection/DoctrineExtensionTest.php +++ b/tests/DependencyInjection/DoctrineExtensionTest.php @@ -37,6 +37,7 @@ use LogicException; use PHPUnit\Framework\TestCase; use ReflectionClass; +use Symfony\Bridge\Doctrine\ArgumentResolver\EntityValueResolver; use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Bridge\Doctrine\Messenger\DoctrineClearEntityManagerWorkerSubscriber; use Symfony\Component\Cache\Adapter\ArrayAdapter; @@ -1445,7 +1446,8 @@ public function testControllerResolver(bool $simpleEntityManagerConfig): void $config['orm'] = []; } - $config['orm']['controller_resolver'] = ['auto_mapping' => true]; + $config['orm']['controller_resolver'] = ['auto_mapping' => true]; + $config['orm']['resolve_target_entities'] = ['Throwable' => 'stdClass']; $extension->load([$config], $container); @@ -1453,6 +1455,15 @@ public function testControllerResolver(bool $simpleEntityManagerConfig): void $this->assertEquals([new Reference('doctrine'), new Reference('doctrine.orm.entity_value_resolver.expression_language', $container::IGNORE_ON_INVALID_REFERENCE)], $controllerResolver->getArguments()); + $resolverReflection = new ReflectionClass(EntityValueResolver::class); + $calls = $controllerResolver->getMethodCalls(); + + if ($resolverReflection->hasMethod('addTypeAlias')) { + self::assertEquals([['addTypeAlias', ['Throwable', 'stdClass']]], $calls); + } else { + self::assertEmpty($calls); + } + $container = $this->getContainer(); $config['orm']['controller_resolver'] = [