Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f5ef421

Browse filesBrowse files
ogizanagisroze
authored andcommitted
[Messenger] Middleware factories support in config
1 parent 3cc4a70 commit f5ef421
Copy full SHA for f5ef421

File tree

13 files changed

+222
-24
lines changed
Filter options

13 files changed

+222
-24
lines changed
+37Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Messenger;
13+
14+
use Symfony\Bridge\Doctrine\ManagerRegistry;
15+
16+
/**
17+
* Create a Doctrine ORM transaction middleware to be used in a message bus from an entity manager name.
18+
*
19+
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
20+
*
21+
* @experimental in 4.1
22+
* @final
23+
*/
24+
class DoctrineTransactionMiddlewareFactory
25+
{
26+
private $managerRegistry;
27+
28+
public function __construct(ManagerRegistry $managerRegistry)
29+
{
30+
$this->managerRegistry = $managerRegistry;
31+
}
32+
33+
public function createMiddleware(string $managerName): DoctrineTransactionMiddleware
34+
{
35+
return new DoctrineTransactionMiddleware($this->managerRegistry, $managerName);
36+
}
37+
}

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+30-1Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,36 @@ function ($a) {
10611061
})
10621062
->end()
10631063
->defaultValue(array())
1064-
->prototype('scalar')->end()
1064+
->prototype('array')
1065+
->beforeNormalization()
1066+
->always()
1067+
->then(function ($middleware): array {
1068+
if (!\is_array($middleware)) {
1069+
return array('id' => $middleware);
1070+
}
1071+
if (isset($middleware['id'])) {
1072+
return $middleware;
1073+
}
1074+
if (\count($middleware) > 1) {
1075+
throw new \InvalidArgumentException(sprintf('There is an error at path "framework.messenger" in one of the buses middleware definitions: expected a single entry for a middleware item config, with factory id as key and arguments as value. Got "%s".', json_encode($middleware)));
1076+
}
1077+
1078+
return array(
1079+
'id' => key($middleware),
1080+
'arguments' => current($middleware),
1081+
);
1082+
})
1083+
->end()
1084+
->fixXmlConfig('argument')
1085+
->children()
1086+
->scalarNode('id')->isRequired()->cannotBeEmpty()->end()
1087+
->arrayNode('arguments')
1088+
->normalizeKeys(false)
1089+
->defaultValue(array())
1090+
->prototype('variable')
1091+
->end()
1092+
->end()
1093+
->end()
10651094
->end()
10661095
->end()
10671096
->end()

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+8-3Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,12 +1471,17 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder
14711471
$config['default_bus'] = key($config['buses']);
14721472
}
14731473

1474-
$defaultMiddleware = array('before' => array('logging'), 'after' => array('route_messages', 'call_message_handler'));
1474+
$defaultMiddleware = array(
1475+
'before' => array(array('id' => 'logging')),
1476+
'after' => array(array('id' => 'route_messages'), array('id' => 'call_message_handler')),
1477+
);
14751478
foreach ($config['buses'] as $busId => $bus) {
14761479
$middleware = $bus['default_middleware'] ? array_merge($defaultMiddleware['before'], $bus['middleware'], $defaultMiddleware['after']) : $bus['middleware'];
14771480

1478-
if (!$validationConfig['enabled'] && \in_array('messenger.middleware.validation', $middleware, true)) {
1479-
throw new LogicException('The Validation middleware is only available when the Validator component is installed and enabled. Try running "composer require symfony/validator".');
1481+
foreach ($middleware as $middlewareItem) {
1482+
if (!$validationConfig['enabled'] && 'messenger.middleware.validation' === $middlewareItem['id']) {
1483+
throw new LogicException('The Validation middleware is only available when the Validator component is installed and enabled. Try running "composer require symfony/validator".');
1484+
}
14801485
}
14811486

14821487
$container->setParameter($busId.'.middleware', $middleware);

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+8-1Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,16 @@
391391

392392
<xsd:complexType name="messenger_bus">
393393
<xsd:sequence>
394-
<xsd:element name="middleware" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
394+
<xsd:element name="middleware" type="messenger_middleware" minOccurs="0" maxOccurs="unbounded" />
395395
</xsd:sequence>
396396
<xsd:attribute name="name" type="xsd:string" use="required"/>
397397
<xsd:attribute name="default-middleware" type="xsd:boolean"/>
398398
</xsd:complexType>
399+
400+
<xsd:complexType name="messenger_middleware">
401+
<xsd:sequence>
402+
<xsd:element name="argument" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded" />
403+
</xsd:sequence>
404+
<xsd:attribute name="id" type="xsd:string" use="required"/>
405+
</xsd:complexType>
399406
</xsd:schema>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
$container->loadFromExtension('framework', array(
4+
'messenger' => array(
5+
'buses' => array(
6+
'command_bus' => array(
7+
'middleware' => array(
8+
array(
9+
'foo' => array('qux'),
10+
'bar' => array('baz'),
11+
),
12+
),
13+
),
14+
),
15+
),
16+
));

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_buses.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_buses.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
'messenger.bus.commands' => null,
88
'messenger.bus.events' => array(
99
'middleware' => array(
10+
array('with_factory' => array('foo', true, array('bar' => 'baz'))),
1011
'allow_no_handler',
1112
),
1213
),

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_buses.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_buses.xml
+11-4Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,19 @@
99
<framework:messenger default-bus="messenger.bus.commands">
1010
<framework:bus name="messenger.bus.commands" />
1111
<framework:bus name="messenger.bus.events">
12-
<framework:middleware>allow_no_handler</framework:middleware>
12+
<framework:middleware id="with_factory">
13+
<framework:argument>foo</framework:argument>
14+
<framework:argument>true</framework:argument>
15+
<framework:argument>
16+
<framework:bar>baz</framework:bar>
17+
</framework:argument>
18+
</framework:middleware>
19+
<framework:middleware id="allow_no_handler" />
1320
</framework:bus>
1421
<framework:bus name="messenger.bus.queries" default-middleware="false">
15-
<framework:middleware>route_messages</framework:middleware>
16-
<framework:middleware>allow_no_handler</framework:middleware>
17-
<framework:middleware>call_message_handler</framework:middleware>
22+
<framework:middleware id="route_messages" />
23+
<framework:middleware id="allow_no_handler" />
24+
<framework:middleware id="call_message_handler" />
1825
</framework:bus>
1926
</framework:messenger>
2027
</framework:config>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
framework:
2+
messenger:
3+
buses:
4+
command_bus:
5+
middleware:
6+
- foo: ['qux']
7+
bar: ['baz']

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_buses.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_buses.yml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ framework:
55
messenger.bus.commands: ~
66
messenger.bus.events:
77
middleware:
8+
- with_factory: [foo, true, { bar: baz }]
89
- "allow_no_handler"
910
messenger.bus.queries:
1011
default_middleware: false

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+26-3Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -604,18 +604,41 @@ public function testMessengerWithMultipleBuses()
604604

605605
$this->assertTrue($container->has('messenger.bus.commands'));
606606
$this->assertSame(array(), $container->getDefinition('messenger.bus.commands')->getArgument(0));
607-
$this->assertEquals(array('logging', 'route_messages', 'call_message_handler'), $container->getParameter('messenger.bus.commands.middleware'));
607+
$this->assertEquals(array(
608+
array('id' => 'logging'),
609+
array('id' => 'route_messages'),
610+
array('id' => 'call_message_handler'),
611+
), $container->getParameter('messenger.bus.commands.middleware'));
608612
$this->assertTrue($container->has('messenger.bus.events'));
609613
$this->assertSame(array(), $container->getDefinition('messenger.bus.events')->getArgument(0));
610-
$this->assertEquals(array('logging', 'allow_no_handler', 'route_messages', 'call_message_handler'), $container->getParameter('messenger.bus.events.middleware'));
614+
$this->assertEquals(array(
615+
array('id' => 'logging'),
616+
array('id' => 'with_factory', 'arguments' => array('foo', true, array('bar' => 'baz'))),
617+
array('id' => 'allow_no_handler', 'arguments' => array()),
618+
array('id' => 'route_messages'),
619+
array('id' => 'call_message_handler'),
620+
), $container->getParameter('messenger.bus.events.middleware'));
611621
$this->assertTrue($container->has('messenger.bus.queries'));
612622
$this->assertSame(array(), $container->getDefinition('messenger.bus.queries')->getArgument(0));
613-
$this->assertEquals(array('route_messages', 'allow_no_handler', 'call_message_handler'), $container->getParameter('messenger.bus.queries.middleware'));
623+
$this->assertEquals(array(
624+
array('id' => 'route_messages', 'arguments' => array()),
625+
array('id' => 'allow_no_handler', 'arguments' => array()),
626+
array('id' => 'call_message_handler', 'arguments' => array()),
627+
), $container->getParameter('messenger.bus.queries.middleware'));
614628

615629
$this->assertTrue($container->hasAlias('message_bus'));
616630
$this->assertSame('messenger.bus.commands', (string) $container->getAlias('message_bus'));
617631
}
618632

633+
/**
634+
* @expectedException \InvalidArgumentException
635+
* @expectedExceptionMessage There is an error at path "framework.messenger" in one of the buses middleware definitions: expected a single entry for a middleware item config, with factory id as key and arguments as value. Got "{"foo":["qux"],"bar":["baz"]}"
636+
*/
637+
public function testMessengerMiddlewareFactoryErroneousFormat()
638+
{
639+
$this->createContainerFromFile('messenger_middleware_factory_erroneous_format');
640+
}
641+
619642
public function testTranslator()
620643
{
621644
$container = $this->createContainerFromFile('full');

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,9 @@ public function testAssetsHelperIsRemovedWhenPhpTemplatingEngineIsEnabledAndAsse
2727
{
2828
$this->markTestSkipped('The assets key cannot be set to false using the XML configuration format.');
2929
}
30+
31+
public function testMessengerMiddlewareFactoryErroneousFormat()
32+
{
33+
$this->markTestSkipped('XML configuration will not allow eeroneous format.');
34+
}
3035
}

‎src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php
+22-9Lines 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
}

‎src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php
+50-3Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.