diff --git a/config/messenger.xml b/config/messenger.xml index aefa4017..1ca9faa9 100644 --- a/config/messenger.xml +++ b/config/messenger.xml @@ -52,11 +52,11 @@ - + - + diff --git a/config/orm.xml b/config/orm.xml index 90d3de97..b99cd858 100644 --- a/config/orm.xml +++ b/config/orm.xml @@ -148,11 +148,11 @@ - + - + @@ -160,7 +160,7 @@ - + diff --git a/docs/configuration.rst b/docs/configuration.rst index a6719cd1..dc60769e 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -740,7 +740,7 @@ configuration for the ORM and there are several configuration options that you can control. The following configuration options exist for a mapping: ``type`` - One of ``annotation``, ``xml``, ``yml``, ``php`` or ``staticphp``. + One of ``attribute``, ``xml``, ``yml``, ``php`` or ``staticphp``. This specifies which type of metadata type your mapping uses. ``dir`` diff --git a/docs/custom-id-generators.rst b/docs/custom-id-generators.rst index 4c6141ef..11de3d76 100644 --- a/docs/custom-id-generators.rst +++ b/docs/custom-id-generators.rst @@ -7,7 +7,7 @@ and implement the custom logic in the ``generate(EntityManager $em, $entity)`` method. Before Doctrine bundle 2.3, custom ID generators were always created without any constructor arguments. -Starting with Doctrine bundle 2.3, the ``CustomIdGenerator`` annotation can be +Starting with Doctrine bundle 2.3, the ``CustomIdGenerator`` attribute can be used to reference any services tagged with the ``doctrine.id_generator`` tag. If you enable autoconfiguration (which is the default most of the time), Symfony will add this tag for you automatically if you implement your own id-generators. @@ -28,12 +28,10 @@ are provided: ``doctrine.ulid_generator`` to generate ULIDs, and */ class User { - /** - * @Id - * @Column(type="uuid") - * @ORM\GeneratedValue(strategy="CUSTOM") - * @ORM\CustomIdGenerator("doctrine.uuid_generator") - */ + #[ORM\Id] + #[ORM\Column(type: 'uuid')] + #[ORM\GeneratedValue(strategy: 'CUSTOM')] + #[ORM\CustomIdGenerator('doctrine.uuid_generator')] private $id; // .... diff --git a/docs/entity-listeners.rst b/docs/entity-listeners.rst index e08c7b34..35c4483e 100644 --- a/docs/entity-listeners.rst +++ b/docs/entity-listeners.rst @@ -2,7 +2,7 @@ Entity Listeners ================ Entity listeners that are services must be registered with the entity listener -resolver. On top of the annotation in the entity class, you have to tag the +resolver. On top of the annotation/attribute in the entity class, you have to tag the service with ``doctrine.orm.entity_listener`` for it to be automatically added to the resolver. Use the (optional) ``entity_manager`` attribute to specify which entity manager it should be registered with. diff --git a/src/Command/DropDatabaseDoctrineCommand.php b/src/Command/DropDatabaseDoctrineCommand.php index 8720d315..dc85b293 100644 --- a/src/Command/DropDatabaseDoctrineCommand.php +++ b/src/Command/DropDatabaseDoctrineCommand.php @@ -105,7 +105,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int try { if ($shouldDropDatabase) { - /** @psalm-suppress TypeDoesNotContainType Bogus error, Doctrine\DBAL\Schema\AbstractSchemaManager does contain Doctrine\DBAL\Schema\SQLiteSchemaManager */ if ($schemaManager instanceof SQLiteSchemaManager) { // dropDatabase() is deprecated for Sqlite $connection->close(); diff --git a/src/DependencyInjection/Compiler/MiddlewaresPass.php b/src/DependencyInjection/Compiler/MiddlewaresPass.php index be361991..734c5b93 100644 --- a/src/DependencyInjection/Compiler/MiddlewaresPass.php +++ b/src/DependencyInjection/Compiler/MiddlewaresPass.php @@ -6,6 +6,7 @@ use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; use function array_key_exists; use function array_keys; @@ -44,20 +45,21 @@ public function process(ContainerBuilder $container): void } foreach (array_keys($container->getParameter('doctrine.connections')) as $name) { - $middlewareDefs = []; + $middlewareRefs = []; $i = 0; foreach ($middlewareAbstractDefs as $id => $abstractDef) { if (isset($middlewareConnections[$id]) && ! array_key_exists($name, $middlewareConnections[$id])) { continue; } - $middlewareDefs[$id] = [ - $childDef = $container->setDefinition( - sprintf('%s.%s', $id, $name), - new ChildDefinition($id), - ), - ++$i, - ]; + $childDef = $container->setDefinition( + $childId = sprintf('%s.%s', $id, $name), + (new ChildDefinition($id)) + ->setTags($abstractDef->getTags())->clearTag('doctrine.middleware') + ->setAutoconfigured($abstractDef->isAutoconfigured()) + ->setAutowired($abstractDef->isAutowired()), + ); + $middlewareRefs[$id] = [new Reference($childId), ++$i]; if (! is_subclass_of($abstractDef->getClass(), ConnectionNameAwareInterface::class)) { continue; @@ -66,21 +68,21 @@ public function process(ContainerBuilder $container): void $childDef->addMethodCall('setConnectionName', [$name]); } - $middlewareDefs = array_map( - static fn ($id, $def) => [ + $middlewareRefs = array_map( + static fn (string $id, array $ref) => [ $middlewareConnections[$id][$name] ?? $middlewarePriorities[$id] ?? 0, - $def[1], - $def[0], + $ref[1], + $ref[0], ], - array_keys($middlewareDefs), - array_values($middlewareDefs), + array_keys($middlewareRefs), + array_values($middlewareRefs), ); - uasort($middlewareDefs, static fn ($a, $b) => $b[0] <=> $a[0] ?: $a[1] <=> $b[1]); - $middlewareDefs = array_map(static fn ($value) => $value[2], $middlewareDefs); + uasort($middlewareRefs, static fn (array $a, array $b): int => $b[0] <=> $a[0] ?: $a[1] <=> $b[1]); + $middlewareRefs = array_map(static fn (array $value): Reference => $value[2], $middlewareRefs); $container ->getDefinition(sprintf('doctrine.dbal.%s_connection.configuration', $name)) - ->addMethodCall('setMiddlewares', [$middlewareDefs]); + ->addMethodCall('setMiddlewares', [$middlewareRefs]); } } } diff --git a/tests/DependencyInjection/Compiler/MiddlewarePassTest.php b/tests/DependencyInjection/Compiler/MiddlewarePassTest.php index acb64f93..61b8bd9c 100644 --- a/tests/DependencyInjection/Compiler/MiddlewarePassTest.php +++ b/tests/DependencyInjection/Compiler/MiddlewarePassTest.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\Reference; use function array_map; use function class_exists; @@ -306,6 +307,28 @@ public function testAddMiddlewareOrderingWithInheritedPriorityPerConnection(): v $this->assertMiddlewareOrdering($container, 'conn2', $expectedMiddlewares); } + public function testInjectedMiddlewaresPreserveParentDefinition(): void + { + $container = $this->createContainer(static function (ContainerBuilder $container): void { + $container + ->register('middleware', PHP7Middleware::class) + ->setPublic(true) + ->setAutowired(true) + ->setAutoconfigured(true) + ->addTag('doctrine.middleware')->addTag('custom.tag'); + $container + ->setAlias('conf_conn', 'doctrine.dbal.conn1_connection.configuration') + ->setPublic(true); // Avoid removal and inlining + }); + $this->assertMiddlewareInjected($container, 'conn', PHP7Middleware::class); + $this->assertNotNull($definition = $container->getDefinition('middleware.conn1')); + $this->assertCount(1, $middlewares = $this->getMiddlewaresForConn($container, 'conn', PHP7Middleware::class)); + $this->assertSame(true, $definition->isAutowired()); + $this->assertSame(true, $definition->isAutoconfigured()); + $this->assertSame(['custom.tag' => [[]]], $definition->getTags()); + $this->assertSame($middlewares[0], $definition); + } + /** @requires PHP 8 */ public function testAddMiddlewareOrderingWithAttributeForAutoconfiguration(): void { @@ -466,6 +489,10 @@ private function getMiddlewaresForConn(ContainerBuilder $container, string $conn } foreach ($call[1][0] as $middlewareDef) { + if ($middlewareDef instanceof Reference) { + $middlewareDef = $container->getDefinition($middlewareDef->__toString()); + } + if (isset($middlewareClass) && $middlewareDef->getClass() !== $middlewareClass) { continue; }