Skip to content

Commit 140112a

Browse files
ogizanagisroze
authored andcommitted
[Messenger] Middleware factories support in config
1 parent ba8b68e commit 140112a

File tree

2 files changed

+72
-12
lines changed

2 files changed

+72
-12
lines changed

DependencyInjection/MessengerPass.php

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -221,24 +221,37 @@ private function registerBusToCollector(ContainerBuilder $container, string $bus
221221
$container->getDefinition('messenger.data_collector')->addMethodCall('registerBus', array($busId, new Reference($tracedBusId)));
222222
}
223223

224-
private function registerBusMiddleware(ContainerBuilder $container, string $busId, array $middleware)
224+
private function registerBusMiddleware(ContainerBuilder $container, string $busId, array $middlewareCollection)
225225
{
226-
$container->getDefinition($busId)->replaceArgument(0, array_map(function (string $name) use ($container, $busId) {
227-
if (!$container->has($messengerMiddlewareId = 'messenger.middleware.'.$name)) {
228-
$messengerMiddlewareId = $name;
226+
$middlewareReferences = array();
227+
foreach ($middlewareCollection as $middlewareItem) {
228+
$id = $middlewareItem['id'];
229+
$arguments = $middlewareItem['arguments'] ?? array();
230+
if (!$container->has($messengerMiddlewareId = 'messenger.middleware.'.$id)) {
231+
$messengerMiddlewareId = $id;
229232
}
230233

231234
if (!$container->has($messengerMiddlewareId)) {
232-
throw new RuntimeException(sprintf('Invalid middleware "%s": define such service to be able to use it.', $name));
235+
throw new RuntimeException(sprintf('Invalid middleware "%s": define such service to be able to use it.', $id));
233236
}
234237

235-
if ($container->getDefinition($messengerMiddlewareId)->isAbstract()) {
238+
if (($definition = $container->findDefinition($messengerMiddlewareId))->isAbstract()) {
236239
$childDefinition = new ChildDefinition($messengerMiddlewareId);
240+
$count = \count($definition->getArguments());
241+
foreach (array_values($arguments ?? array()) as $key => $argument) {
242+
// Parent definition can provide default arguments.
243+
// Replace each explicitly or add if not set:
244+
$key < $count ? $childDefinition->replaceArgument($key, $argument) : $childDefinition->addArgument($argument);
245+
}
237246

238-
$container->setDefinition($messengerMiddlewareId = $busId.'.middleware.'.$name, $childDefinition);
247+
$container->setDefinition($messengerMiddlewareId = $busId.'.middleware.'.$id, $childDefinition);
248+
} elseif ($arguments) {
249+
throw new RuntimeException(sprintf('Invalid middleware factory "%s": a middleware factory must be an abstract definition.', $id));
239250
}
240251

241-
return new Reference($messengerMiddlewareId);
242-
}, $middleware));
252+
$middlewareReferences[] = new Reference($messengerMiddlewareId);
253+
}
254+
255+
$container->getDefinition($busId)->replaceArgument(0, $middlewareReferences);
243256
}
244257
}

Tests/DependencyInjection/MessengerPassTest.php

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
16+
use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass;
1617
use Symfony\Component\DependencyInjection\ContainerBuilder;
1718
use Symfony\Component\DependencyInjection\Reference;
1819
use Symfony\Component\DependencyInjection\ServiceLocator;
@@ -312,14 +313,42 @@ public function testRegistersMiddlewareFromServices()
312313
$container = $this->getContainerBuilder();
313314
$container->register($fooBusId = 'messenger.bus.foo', MessageBusInterface::class)->setArgument(0, array())->addTag('messenger.bus');
314315
$container->register('messenger.middleware.allow_no_handler', AllowNoHandlerMiddleware::class)->setAbstract(true);
316+
$container->register('middleware_with_factory', UselessMiddleware::class)->addArgument('some_default')->setAbstract(true);
317+
$container->register('middleware_with_factory_using_default', UselessMiddleware::class)->addArgument('some_default')->setAbstract(true);
315318
$container->register(UselessMiddleware::class, UselessMiddleware::class);
316319

317-
$container->setParameter($middlewareParameter = $fooBusId.'.middleware', array(UselessMiddleware::class, 'allow_no_handler'));
320+
$container->setParameter($middlewareParameter = $fooBusId.'.middleware', array(
321+
array('id' => UselessMiddleware::class),
322+
array('id' => 'middleware_with_factory', 'arguments' => array('foo', 'bar')),
323+
array('id' => 'middleware_with_factory_using_default'),
324+
array('id' => 'allow_no_handler'),
325+
));
318326

319327
(new MessengerPass())->process($container);
328+
(new ResolveChildDefinitionsPass())->process($container);
320329

321330
$this->assertTrue($container->hasDefinition($childMiddlewareId = $fooBusId.'.middleware.allow_no_handler'));
322-
$this->assertEquals(array(new Reference(UselessMiddleware::class), new Reference($childMiddlewareId)), $container->getDefinition($fooBusId)->getArgument(0));
331+
332+
$this->assertTrue($container->hasDefinition($factoryChildMiddlewareId = $fooBusId.'.middleware.middleware_with_factory'));
333+
$this->assertEquals(
334+
array('foo', 'bar'),
335+
$container->getDefinition($factoryChildMiddlewareId)->getArguments(),
336+
'parent default argument is overridden, and next ones appended'
337+
);
338+
339+
$this->assertTrue($container->hasDefinition($factoryWithDefaultChildMiddlewareId = $fooBusId.'.middleware.middleware_with_factory_using_default'));
340+
$this->assertEquals(
341+
array('some_default'),
342+
$container->getDefinition($factoryWithDefaultChildMiddlewareId)->getArguments(),
343+
'parent default argument is used'
344+
);
345+
346+
$this->assertEquals(array(
347+
new Reference(UselessMiddleware::class),
348+
new Reference($factoryChildMiddlewareId),
349+
new Reference($factoryWithDefaultChildMiddlewareId),
350+
new Reference($childMiddlewareId),
351+
), $container->getDefinition($fooBusId)->getArgument(0));
323352
$this->assertFalse($container->hasParameter($middlewareParameter));
324353
}
325354

@@ -331,7 +360,25 @@ public function testCannotRegistersAnUndefinedMiddleware()
331360
{
332361
$container = $this->getContainerBuilder();
333362
$container->register($fooBusId = 'messenger.bus.foo', MessageBusInterface::class)->setArgument(0, array())->addTag('messenger.bus');
334-
$container->setParameter($middlewareParameter = $fooBusId.'.middleware', array('not_defined_middleware'));
363+
$container->setParameter($middlewareParameter = $fooBusId.'.middleware', array(
364+
array('id' => 'not_defined_middleware', 'arguments' => array()),
365+
));
366+
367+
(new MessengerPass())->process($container);
368+
}
369+
370+
/**
371+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
372+
* @expectedExceptionMessage Invalid middleware factory "not_an_abstract_definition": a middleware factory must be an abstract definition.
373+
*/
374+
public function testMiddlewareFactoryDefinitionMustBeAbstract()
375+
{
376+
$container = $this->getContainerBuilder();
377+
$container->register('not_an_abstract_definition', UselessMiddleware::class);
378+
$container->register($fooBusId = 'messenger.bus.foo', MessageBusInterface::class)->setArgument(0, array())->addTag('messenger.bus', array('name' => 'foo'));
379+
$container->setParameter($middlewareParameter = $fooBusId.'.middleware', array(
380+
array('id' => 'not_an_abstract_definition', 'arguments' => array('foo')),
381+
));
335382

336383
(new MessengerPass())->process($container);
337384
}

0 commit comments

Comments
 (0)