From 3a316498c92c129072b610872c860aa3f7dd53e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Thu, 6 Feb 2025 22:27:11 +0100 Subject: [PATCH] Ensure classes using the #[Entity] attribute are not declared as services --- src/DependencyInjection/DoctrineExtension.php | 13 ++++++ .../DoctrineExtensionTest.php | 40 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/DependencyInjection/DoctrineExtension.php b/src/DependencyInjection/DoctrineExtension.php index 6d2c95c7..9842d06d 100644 --- a/src/DependencyInjection/DoctrineExtension.php +++ b/src/DependencyInjection/DoctrineExtension.php @@ -27,6 +27,9 @@ use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver; use Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver; use Doctrine\ORM\Mapping\Driver\StaticPHPDriver as LegacyStaticPHPDriver; +use Doctrine\ORM\Mapping\Embeddable; +use Doctrine\ORM\Mapping\Entity; +use Doctrine\ORM\Mapping\MappedSuperclass; use Doctrine\ORM\Proxy\Autoloader; use Doctrine\ORM\Proxy\ProxyFactory; use Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand; @@ -644,6 +647,16 @@ protected function ormLoad(array $config, ContainerBuilder $container) ]); }); + $container->registerAttributeForAutoconfiguration(Embeddable::class, static function (ChildDefinition $definition) { + $definition->setAbstract(true)->addTag('container.excluded', ['source' => sprintf('with #[%s] attribute', Embeddable::class)]); + }); + $container->registerAttributeForAutoconfiguration(Entity::class, static function (ChildDefinition $definition) { + $definition->setAbstract(true)->addTag('container.excluded', ['source' => sprintf('with #[%s] attribute', Entity::class)]); + }); + $container->registerAttributeForAutoconfiguration(MappedSuperclass::class, static function (ChildDefinition $definition) { + $definition->setAbstract(true)->addTag('container.excluded', ['source' => sprintf('with #[%s] attribute', MappedSuperclass::class)]); + }); + /** @see DoctrineBundle::boot() */ $container->getDefinition($defaultEntityManagerDefinitionId) ->addTag('container.preload', [ diff --git a/tests/DependencyInjection/DoctrineExtensionTest.php b/tests/DependencyInjection/DoctrineExtensionTest.php index 51e69eec..055d9274 100644 --- a/tests/DependencyInjection/DoctrineExtensionTest.php +++ b/tests/DependencyInjection/DoctrineExtensionTest.php @@ -32,6 +32,9 @@ use Doctrine\ORM\Mapping\Driver\AttributeDriver; use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver; use Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver; +use Doctrine\ORM\Mapping\Embeddable; +use Doctrine\ORM\Mapping\Entity; +use Doctrine\ORM\Mapping\MappedSuperclass; use Doctrine\Persistence\Mapping\Driver\MappingDriverChain; use InvalidArgumentException; use LogicException; @@ -1165,6 +1168,43 @@ public static function cacheConfigurationProvider(): array ]; } + /** @return array */ + public static function provideAttributeExcludedFromContainer(): array + { + return [ + 'Embeddable' => [Embeddable::class], + 'Entity' => [Entity::class], + 'MappedSuperclass' => [MappedSuperclass::class], + ]; + } + + /** @dataProvider provideAttributeExcludedFromContainer */ + public function testEntityAttributeExcludesFromContainer(string $class) + { + if (! interface_exists(EntityManagerInterface::class)) { + self::markTestSkipped('This test requires ORM'); + } + + $container = $this->getContainer(); + $extension = new DoctrineExtension(); + + $config = BundleConfigurationBuilder::createBuilder() + ->addBaseConnection() + ->addBaseEntityManager() + ->build(); + + $extension->load([$config], $container); + + $attributes = $container->getAutoconfiguredAttributes(); + $this->assertInstanceOf(Closure::class, $attributes[$class]); + + $definition = new ChildDefinition(''); + $attributes[$class]($definition); + + $this->assertSame([['source' => sprintf('with #[%s] attribute', $class)]], $definition->getTag('container.excluded')); + $this->assertTrue($definition->isAbstract()); + } + public function testAsEntityListenerAttribute() { if (! interface_exists(EntityManagerInterface::class)) {