From eda148b2b2cc832efa8588770fb3f8ec23cf7011 Mon Sep 17 00:00:00 2001 From: Mathieu Date: Wed, 6 Nov 2024 12:16:39 +0100 Subject: [PATCH] Fix wiring of PHP metadata drivers on doctrine/orm 3.x (#1832) --- composer.json | 2 +- psalm.xml.dist | 2 + src/DependencyInjection/DoctrineExtension.php | 38 +++++++++++++- .../AbstractDoctrineExtensionTest.php | 50 ++++--------------- .../DoctrineExtensionTest.php | 49 ++---------------- .../xml/orm_multiple_em_bundle_mappings.xml | 1 - .../xml/orm_single_em_bundle_mappings.xml | 1 - .../orm_single_em_default_table_options.xml | 1 - .../yml/orm_multiple_em_bundle_mappings.yml | 1 - .../yml/orm_single_em_bundle_mappings.yml | 1 - .../orm_single_em_default_table_options.yml | 1 - 11 files changed, 53 insertions(+), 94 deletions(-) diff --git a/composer.json b/composer.json index 7dfce1cf..0347ad01 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "symfony/console": "^5.4 || ^6.0 || ^7.0", "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", "symfony/deprecation-contracts": "^2.1 || ^3", - "symfony/doctrine-bridge": "^5.4.19 || ^6.0.7 || ^7.0", + "symfony/doctrine-bridge": "^5.4.46 || ^6.4.3 || ^7.0.3", "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0", "symfony/polyfill-php80": "^1.15", "symfony/service-contracts": "^1.1.1 || ^2.0 || ^3" diff --git a/psalm.xml.dist b/psalm.xml.dist index 16e9f0db..931a530a 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -40,6 +40,8 @@ + + diff --git a/src/DependencyInjection/DoctrineExtension.php b/src/DependencyInjection/DoctrineExtension.php index 30cbfa6f..bea0b8e9 100644 --- a/src/DependencyInjection/DoctrineExtension.php +++ b/src/DependencyInjection/DoctrineExtension.php @@ -22,13 +22,21 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Events; use Doctrine\ORM\Id\AbstractIdGenerator; +use Doctrine\ORM\Mapping\Driver\AnnotationDriver; +use Doctrine\ORM\Mapping\Driver\AttributeDriver; +use Doctrine\ORM\Mapping\Driver\PHPDriver as LegacyPHPDriver; use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver; +use Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver; +use Doctrine\ORM\Mapping\Driver\StaticPHPDriver as LegacyStaticPHPDriver; use Doctrine\ORM\Proxy\Autoloader; use Doctrine\ORM\Proxy\ProxyFactory; use Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand; use Doctrine\ORM\Tools\Console\Command\EnsureProductionSettingsCommand; use Doctrine\ORM\Tools\Export\ClassMetadataExporter; use Doctrine\ORM\UnitOfWork; +use Doctrine\Persistence\Mapping\Driver\MappingDriverChain; +use Doctrine\Persistence\Mapping\Driver\PHPDriver; +use Doctrine\Persistence\Mapping\Driver\StaticPHPDriver; use Doctrine\Persistence\Reflection\RuntimeReflectionProperty; use InvalidArgumentException; use LogicException; @@ -1163,7 +1171,35 @@ public function getConfiguration(array $config, ContainerBuilder $container): Co protected function getMetadataDriverClass(string $driverType): string { - return '%' . $this->getObjectManagerElementName('metadata.' . $driverType . '.class') . '%'; + switch ($driverType) { + case 'driver_chain': + return MappingDriverChain::class; + + case 'annotation': + if (! class_exists(AnnotationDriver::class)) { + throw new LogicException('The annotation driver is only available in doctrine/orm v2.'); + } + + return AnnotationDriver::class; + + case 'xml': + return SimplifiedXmlDriver::class; + + case 'yml': + return SimplifiedYamlDriver::class; + + case 'php': + return class_exists(PHPDriver::class) ? PHPDriver::class : LegacyPHPDriver::class; + + case 'staticphp': + return class_exists(StaticPHPDriver::class) ? StaticPHPDriver::class : LegacyStaticPHPDriver::class; + + case 'attribute': + return AttributeDriver::class; + + default: + throw new LogicException(sprintf('Unknown "%s" metadata driver type.', $driverType)); + } } private function loadMessengerServices(ContainerBuilder $container): void diff --git a/tests/DependencyInjection/AbstractDoctrineExtensionTest.php b/tests/DependencyInjection/AbstractDoctrineExtensionTest.php index 4c91dc2f..90918bdc 100644 --- a/tests/DependencyInjection/AbstractDoctrineExtensionTest.php +++ b/tests/DependencyInjection/AbstractDoctrineExtensionTest.php @@ -40,13 +40,11 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Security\Core\User\UserInterface; use function array_filter; use function array_intersect_key; use function array_keys; -use function array_merge; use function array_values; use function assert; use function class_exists; @@ -57,7 +55,6 @@ use function sprintf; use function sys_get_temp_dir; use function uniqid; -use function version_compare; use const DIRECTORY_SEPARATOR; @@ -543,40 +540,30 @@ public function testSingleEntityManagerMultipleMappingBundleDefinitions(): void self::markTestSkipped('This test requires ORM'); } - $container = $this->loadContainer('orm_single_em_bundle_mappings', ['YamlBundle', 'AnnotationsBundle', 'XmlBundle', 'AttributesBundle']); + $container = $this->loadContainer('orm_single_em_bundle_mappings', ['YamlBundle', 'XmlBundle', 'AttributesBundle']); $definition = $container->getDefinition('doctrine.orm.default_metadata_driver'); $this->assertDICDefinitionMethodCallAt(0, $definition, 'addDriver', [ - new Reference(version_compare(Kernel::VERSION, '7.0.0', '<') ? 'doctrine.orm.default_annotation_metadata_driver' : 'doctrine.orm.default_attribute_metadata_driver'), - 'Fixtures\Bundles\AnnotationsBundle\Entity', - ]); - - $this->assertDICDefinitionMethodCallAt(1, $definition, 'addDriver', [ new Reference('doctrine.orm.default_attribute_metadata_driver'), 'Fixtures\Bundles\AttributesBundle\Entity', ]); - $this->assertDICDefinitionMethodCallAt(2, $definition, 'addDriver', [ + $this->assertDICDefinitionMethodCallAt(1, $definition, 'addDriver', [ new Reference('doctrine.orm.default_yml_metadata_driver'), 'Fixtures\Bundles\YamlBundle\Entity', ]); - $this->assertDICDefinitionMethodCallAt(3, $definition, 'addDriver', [ + $this->assertDICDefinitionMethodCallAt(2, $definition, 'addDriver', [ new Reference('doctrine.orm.default_xml_metadata_driver'), 'Fixtures\Bundles\XmlBundle', ]); $attrDef = $container->getDefinition('doctrine.orm.default_attribute_metadata_driver'); $this->assertDICConstructorArguments($attrDef, [ - array_merge( - ! version_compare(Kernel::VERSION, '7.0.0', '<') ? [ - __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'AnnotationsBundle' . DIRECTORY_SEPARATOR . 'Entity', - ] : [], - [ - __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'AttributesBundle' . DIRECTORY_SEPARATOR . 'Entity', - ], - ), + [ + __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'AttributesBundle' . DIRECTORY_SEPARATOR . 'Entity', + ], ! class_exists(AnnotationDriver::class), ]); @@ -600,21 +587,15 @@ public function testMultipleEntityManagersMappingBundleDefinitions(): void self::markTestSkipped('This test requires ORM'); } - $container = $this->loadContainer('orm_multiple_em_bundle_mappings', ['YamlBundle', 'AnnotationsBundle', 'XmlBundle', 'AttributesBundle']); + $container = $this->loadContainer('orm_multiple_em_bundle_mappings', ['YamlBundle', 'XmlBundle', 'AttributesBundle']); $this->assertEquals(['em1' => 'doctrine.orm.em1_entity_manager', 'em2' => 'doctrine.orm.em2_entity_manager'], $container->getParameter('doctrine.entity_managers'), 'Set of the existing EntityManagers names is incorrect.'); $this->assertEquals('%doctrine.entity_managers%', $container->getDefinition('doctrine')->getArgument(2), 'Set of the existing EntityManagers names is incorrect.'); - $def1 = $container->getDefinition('doctrine.orm.em1_metadata_driver'); - $def2 = $container->getDefinition('doctrine.orm.em2_metadata_driver'); - $def1Id = version_compare(Kernel::VERSION, '7.0.0', '<') ? 'doctrine.orm.em1_annotation_metadata_driver' : 'doctrine.orm.em1_attribute_metadata_driver'; + $def1 = $container->getDefinition('doctrine.orm.em1_metadata_driver'); + $def2 = $container->getDefinition('doctrine.orm.em2_metadata_driver'); $this->assertDICDefinitionMethodCallAt(0, $def1, 'addDriver', [ - new Reference($def1Id), - 'Fixtures\Bundles\AnnotationsBundle\Entity', - ]); - - $this->assertDICDefinitionMethodCallAt(1, $def1, 'addDriver', [ new Reference('doctrine.orm.em1_attribute_metadata_driver'), 'Fixtures\Bundles\AttributesBundle\Entity', ]); @@ -629,17 +610,6 @@ public function testMultipleEntityManagersMappingBundleDefinitions(): void 'Fixtures\Bundles\XmlBundle', ]); - if (version_compare(Kernel::VERSION, '7.0.0', '<')) { - $annDef = $container->getDefinition($def1Id); - $this->assertDICConstructorArguments($annDef, [ - new Reference('doctrine.orm.metadata.annotation_reader'), - [ - __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'AnnotationsBundle' . DIRECTORY_SEPARATOR . 'Entity', - ], - ! class_exists(AnnotationDriver::class), - ]); - } - $ymlDef = $container->getDefinition('doctrine.orm.em2_yml_metadata_driver'); $this->assertDICConstructorArguments($ymlDef, [ [__DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'YamlBundle' . DIRECTORY_SEPARATOR . 'Resources' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'doctrine' => 'Fixtures\Bundles\YamlBundle\Entity'], @@ -659,7 +629,7 @@ public function testSingleEntityManagerDefaultTableOptions(): void self::markTestSkipped('This test requires ORM'); } - $container = $this->loadContainer('orm_single_em_default_table_options', ['YamlBundle', 'AnnotationsBundle', 'XmlBundle', 'AttributesBundle']); + $container = $this->loadContainer('orm_single_em_default_table_options', ['YamlBundle', 'XmlBundle', 'AttributesBundle']); $param = $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0); diff --git a/tests/DependencyInjection/DoctrineExtensionTest.php b/tests/DependencyInjection/DoctrineExtensionTest.php index f1d2f005..c3d25d8c 100644 --- a/tests/DependencyInjection/DoctrineExtensionTest.php +++ b/tests/DependencyInjection/DoctrineExtensionTest.php @@ -50,7 +50,6 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Messenger\Bridge\Doctrine\Transport\DoctrineTransportFactory; use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; use function array_values; use function class_exists; @@ -823,39 +822,6 @@ public function testXmlBundleMappingDetection(): void ]); } - public function testAnnotationsBundleMappingDetection(): void - { - if (! interface_exists(EntityManagerInterface::class)) { - self::markTestSkipped('This test requires ORM'); - } - - $container = $this->getContainer(['AnnotationsBundle']); - $extension = new DoctrineExtension(); - - $config = BundleConfigurationBuilder::createBuilder() - ->addBaseConnection() - ->addEntityManager([ - 'default_entity_manager' => 'default', - 'entity_managers' => [ - 'default' => [ - 'mappings' => [ - 'AnnotationsBundle' => [], - ], - ], - ], - ]) - ->build(); - $extension->load([$config], $container); - - $definition = $container->getDefinition('doctrine.orm.default_metadata_driver'); - $this->assertDICDefinitionMethodCallOnce($definition, 'addDriver', [ - new Reference(class_exists(AnnotationLoader::class) - ? 'doctrine.orm.default_annotation_metadata_driver' - : 'doctrine.orm.default_attribute_metadata_driver'), - 'Fixtures\Bundles\AnnotationsBundle\Entity', - ]); - } - /** @requires PHP 8 */ public function testAttributesBundleMappingDetection(): void { @@ -898,7 +864,7 @@ public function testOrmMergeConfigs(): void self::markTestSkipped('This test requires ORM'); } - $container = $this->getContainer(['XmlBundle', 'AnnotationsBundle', 'AttributesBundle']); + $container = $this->getContainer(['XmlBundle', 'AttributesBundle']); $extension = new DoctrineExtension(); $config1 = BundleConfigurationBuilder::createBuilder() @@ -908,10 +874,7 @@ public function testOrmMergeConfigs(): void 'default_entity_manager' => 'default', 'entity_managers' => [ 'default' => [ - 'mappings' => [ - 'AnnotationsBundle' => [], - 'AttributesBundle' => ['type' => 'attribute'], - ], + 'mappings' => ['AttributesBundle' => ['type' => 'attribute']], ], ], ]) @@ -934,16 +897,10 @@ public function testOrmMergeConfigs(): void $definition = $container->getDefinition('doctrine.orm.default_metadata_driver'); $this->assertDICDefinitionMethodCallAt(0, $definition, 'addDriver', [ - new Reference(class_exists(AnnotationLoader::class) - ? 'doctrine.orm.default_annotation_metadata_driver' - : 'doctrine.orm.default_attribute_metadata_driver'), - 'Fixtures\Bundles\AnnotationsBundle\Entity', - ]); - $this->assertDICDefinitionMethodCallAt(1, $definition, 'addDriver', [ new Reference('doctrine.orm.default_attribute_metadata_driver'), 'Fixtures\Bundles\AttributesBundle\Entity', ]); - $this->assertDICDefinitionMethodCallAt(2, $definition, 'addDriver', [ + $this->assertDICDefinitionMethodCallAt(1, $definition, 'addDriver', [ new Reference('doctrine.orm.default_xml_metadata_driver'), 'Fixtures\Bundles\XmlBundle\Entity', ]); diff --git a/tests/DependencyInjection/Fixtures/config/xml/orm_multiple_em_bundle_mappings.xml b/tests/DependencyInjection/Fixtures/config/xml/orm_multiple_em_bundle_mappings.xml index 07439af9..b85d2e40 100644 --- a/tests/DependencyInjection/Fixtures/config/xml/orm_multiple_em_bundle_mappings.xml +++ b/tests/DependencyInjection/Fixtures/config/xml/orm_multiple_em_bundle_mappings.xml @@ -13,7 +13,6 @@ - diff --git a/tests/DependencyInjection/Fixtures/config/xml/orm_single_em_bundle_mappings.xml b/tests/DependencyInjection/Fixtures/config/xml/orm_single_em_bundle_mappings.xml index 9e1a87e5..3022d034 100644 --- a/tests/DependencyInjection/Fixtures/config/xml/orm_single_em_bundle_mappings.xml +++ b/tests/DependencyInjection/Fixtures/config/xml/orm_single_em_bundle_mappings.xml @@ -12,7 +12,6 @@ - -