Skip to content

Commit 16e1329

Browse files
committed
Use references for connection middlewares
This ensures created child definitions for connection specific middlewares inherit props like tags from parent and their definitions are set in root of the container, so that they are visible for other compiler passes that look for things through stuff like tags
1 parent d84aadb commit 16e1329

File tree

2 files changed

+46
-17
lines changed

2 files changed

+46
-17
lines changed

src/DependencyInjection/Compiler/MiddlewaresPass.php

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Symfony\Component\DependencyInjection\ChildDefinition;
77
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
88
use Symfony\Component\DependencyInjection\ContainerBuilder;
9+
use Symfony\Component\DependencyInjection\Reference;
910

1011
use function array_key_exists;
1112
use function array_keys;
@@ -44,20 +45,21 @@ public function process(ContainerBuilder $container): void
4445
}
4546

4647
foreach (array_keys($container->getParameter('doctrine.connections')) as $name) {
47-
$middlewareDefs = [];
48+
$middlewareRefs = [];
4849
$i = 0;
4950
foreach ($middlewareAbstractDefs as $id => $abstractDef) {
5051
if (isset($middlewareConnections[$id]) && ! array_key_exists($name, $middlewareConnections[$id])) {
5152
continue;
5253
}
5354

54-
$middlewareDefs[$id] = [
55-
$childDef = $container->setDefinition(
56-
sprintf('%s.%s', $id, $name),
57-
new ChildDefinition($id),
58-
),
59-
++$i,
60-
];
55+
$childDef = $container->setDefinition(
56+
$childId = sprintf('%s.%s', $id, $name),
57+
(new ChildDefinition($id))
58+
->setTags($abstractDef->getTags())->clearTag('doctrine.middleware')
59+
->setAutoconfigured($abstractDef->isAutoconfigured())
60+
->setAutowired($abstractDef->isAutowired()),
61+
);
62+
$middlewareRefs[$id] = [new Reference($childId), ++$i];
6163

6264
if (! is_subclass_of($abstractDef->getClass(), ConnectionNameAwareInterface::class)) {
6365
continue;
@@ -66,21 +68,21 @@ public function process(ContainerBuilder $container): void
6668
$childDef->addMethodCall('setConnectionName', [$name]);
6769
}
6870

69-
$middlewareDefs = array_map(
70-
static fn ($id, $def) => [
71+
$middlewareRefs = array_map(
72+
static fn (string $id, array $ref) => [
7173
$middlewareConnections[$id][$name] ?? $middlewarePriorities[$id] ?? 0,
72-
$def[1],
73-
$def[0],
74+
$ref[1],
75+
$ref[0],
7476
],
75-
array_keys($middlewareDefs),
76-
array_values($middlewareDefs),
77+
array_keys($middlewareRefs),
78+
array_values($middlewareRefs),
7779
);
78-
uasort($middlewareDefs, static fn ($a, $b) => $b[0] <=> $a[0] ?: $a[1] <=> $b[1]);
79-
$middlewareDefs = array_map(static fn ($value) => $value[2], $middlewareDefs);
80+
uasort($middlewareRefs, static fn (array $a, array $b): int => $b[0] <=> $a[0] ?: $a[1] <=> $b[1]);
81+
$middlewareRefs = array_map(static fn (array $value): Reference => $value[2], $middlewareRefs);
8082

8183
$container
8284
->getDefinition(sprintf('doctrine.dbal.%s_connection.configuration', $name))
83-
->addMethodCall('setMiddlewares', [$middlewareDefs]);
85+
->addMethodCall('setMiddlewares', [$middlewareRefs]);
8486
}
8587
}
8688
}

tests/DependencyInjection/Compiler/MiddlewarePassTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Symfony\Component\DependencyInjection\ContainerBuilder;
1414
use Symfony\Component\DependencyInjection\Definition;
1515
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
16+
use Symfony\Component\DependencyInjection\Reference;
1617

1718
use function array_map;
1819
use function implode;
@@ -296,6 +297,28 @@ public function testAddMiddlewareOrderingWithInheritedPriorityPerConnection(): v
296297
$this->assertMiddlewareOrdering($container, 'conn2', [PHP7Middleware::class, 'some_middleware_class']);
297298
}
298299

300+
public function testInjectedMiddlewaresPreserveParentDefinition(): void
301+
{
302+
$container = $this->createContainer(static function (ContainerBuilder $container): void {
303+
$container
304+
->register('middleware', PHP7Middleware::class)
305+
->setPublic(true)
306+
->setAutowired(true)
307+
->setAutoconfigured(true)
308+
->addTag('doctrine.middleware')->addTag('custom.tag');
309+
$container
310+
->setAlias('conf_conn', 'doctrine.dbal.conn1_connection.configuration')
311+
->setPublic(true); // Avoid removal and inlining
312+
});
313+
$this->assertMiddlewareInjected($container, 'conn', PHP7Middleware::class);
314+
$this->assertNotNull($definition = $container->getDefinition('middleware.conn1'));
315+
$this->assertCount(1, $middlewares = $this->getMiddlewaresForConn($container, 'conn', PHP7Middleware::class));
316+
$this->assertSame(true, $definition->isAutowired());
317+
$this->assertSame(true, $definition->isAutoconfigured());
318+
$this->assertSame(['custom.tag' => [[]]], $definition->getTags());
319+
$this->assertSame($middlewares[0], $definition);
320+
}
321+
299322
/** @requires PHP 8 */
300323
public function testAddMiddlewareOrderingWithAttributeForAutoconfiguration(): void
301324
{
@@ -443,6 +466,10 @@ private function getMiddlewaresForConn(ContainerBuilder $container, string $conn
443466
}
444467

445468
foreach ($call[1][0] as $middlewareDef) {
469+
if ($middlewareDef instanceof Reference) {
470+
$middlewareDef = $container->getDefinition($middlewareDef->__toString());
471+
}
472+
446473
if (isset($middlewareClass) && $middlewareDef->getClass() !== $middlewareClass) {
447474
continue;
448475
}

0 commit comments

Comments
 (0)