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 2461e51

Browse filesBrowse files
committed
[Messenger][DX] Uses custom method names for handlers
1 parent 6988551 commit 2461e51
Copy full SHA for 2461e51

File tree

3 files changed

+132
-12
lines changed
Filter options

3 files changed

+132
-12
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php
+32-5Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,27 +74,55 @@ public function process(ContainerBuilder $container)
7474

7575
private function registerHandlers(ContainerBuilder $container)
7676
{
77+
$definitions = array();
7778
$handlersByMessage = array();
7879

7980
foreach ($container->findTaggedServiceIds($this->handlerTag, true) as $serviceId => $tags) {
8081
foreach ($tags as $tag) {
81-
$handles = isset($tag['handles']) ? array($tag['handles']) : $this->guessHandledClasses($r = $container->getReflectionClass($container->getDefinition($serviceId)->getClass()), $serviceId);
82+
$r = $container->getReflectionClass($container->getDefinition($serviceId)->getClass());
83+
84+
if (isset($tag['handles'])) {
85+
$handles = isset($tag['method']) ? array($tag['handles'] => $tag['method']) : array($tag['handles']);
86+
} else {
87+
$handles = $this->guessHandledClasses($r, $serviceId);
88+
}
89+
8290
$priority = $tag['priority'] ?? 0;
8391

84-
foreach ($handles as $messageClass) {
92+
foreach ($handles as $messageClass => $method) {
93+
if (\is_int($messageClass)) {
94+
$messageClass = $method;
95+
$method = '__invoke';
96+
}
97+
8598
if (\is_array($messageClass)) {
8699
$messagePriority = $messageClass[1];
87100
$messageClass = $messageClass[0];
88101
} else {
89102
$messagePriority = $priority;
90103
}
91104

92-
if (!class_exists($messageClass)) {
93-
$messageClassLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : sprintf($r->implementsInterface(MessageHandlerInterface::class) ? 'returned by method "%s::getHandledMessages()"' : 'used as argument type in method "%s::__invoke()"', $r->getName());
105+
if (\is_array($method)) {
106+
$messagePriority = $method[1];
107+
$method = $method[0];
108+
}
109+
110+
if (!\class_exists($messageClass)) {
111+
$messageClassLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : $r->implementsInterface(MessageHandlerInterface::class) ? sprintf('returned by method "%s::getHandledMessages()"', $r->getName()) : sprintf('used as argument type in method "%s::%s()"', $r->getName(), $method);
94112

95113
throw new RuntimeException(sprintf('Invalid handler service "%s": message class "%s" %s does not exist.', $serviceId, $messageClass, $messageClassLocation));
96114
}
97115

116+
if (!$r->hasMethod($method)) {
117+
throw new RuntimeException(sprintf('Invalid handler service "%s": method "%s::%s()" does not exist.', $serviceId, $r->getName(), $method));
118+
}
119+
120+
if ('__invoke' !== $method) {
121+
$wrapperDefinition = (new Definition('callable'))->addArgument(array(new Reference($serviceId), $method))->setFactory('Closure::fromCallable');
122+
123+
$definitions[$serviceId = '.messenger.method_on_object_wrapper.'.ContainerBuilder::hash($messageClass.':'.$messagePriority.':'.$serviceId.':'.$method)] = $wrapperDefinition;
124+
}
125+
98126
$handlersByMessage[$messageClass][$messagePriority][] = new Reference($serviceId);
99127
}
100128
}
@@ -105,7 +133,6 @@ private function registerHandlers(ContainerBuilder $container)
105133
$handlersByMessage[$message] = array_merge(...$handlersByMessage[$message]);
106134
}
107135

108-
$definitions = array();
109136
$handlersLocatorMapping = array();
110137
foreach ($handlersByMessage as $message => $handlers) {
111138
if (1 === \count($handlers)) {

‎src/Symfony/Component/Messenger/Handler/MessageSubscriberInterface.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Messenger/Handler/MessageSubscriberInterface.php
+8-3Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,14 @@ interface MessageSubscriberInterface extends MessageHandlerInterface
3434
* [SecondMessage::class, -10],
3535
* ];
3636
*
37-
* The `__invoke` method of the handler will be called as usual with the message to handle.
37+
* It can also specify a method and/or a priority per message:
3838
*
39-
* @return array
39+
* return [
40+
* FirstMessage::class => 'firstMessageMethod',
41+
* SecondMessage::class => ['secondMessageMethod', 20],
42+
* ];
43+
*
44+
* The `__invoke` method of the handler will be called as usual with the message to handle.
4045
*/
41-
public static function getHandledMessages(): array;
46+
public static function getHandledMessages(): iterable;
4247
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php
+92-4Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,53 @@ public function testGetClassesFromTheHandlerSubscriberInterface()
9898
$this->assertEquals(array(new Reference(PrioritizedHandler::class), new Reference(HandlerWithMultipleMessages::class)), $definition->getArgument(0));
9999
}
100100

101+
public function testGetClassesAndMethodsAndPrioritiesFromTheSubscriber()
102+
{
103+
$container = $this->getContainerBuilder();
104+
$container
105+
->register(HandlerMappingMethods::class, HandlerMappingMethods::class)
106+
->addTag('messenger.message_handler')
107+
;
108+
$container
109+
->register(PrioritizedHandler::class, PrioritizedHandler::class)
110+
->addTag('messenger.message_handler')
111+
;
112+
113+
(new MessengerPass())->process($container);
114+
115+
$handlerLocatorDefinition = $container->getDefinition($container->getDefinition('messenger.handler_resolver')->getArgument(0));
116+
$handlerMapping = $handlerLocatorDefinition->getArgument(0);
117+
118+
$this->assertArrayHasKey('handler.'.DummyMessage::class, $handlerMapping);
119+
$this->assertArrayHasKey('handler.'.SecondMessage::class, $handlerMapping);
120+
121+
$dummyHandlerReference = (string) $handlerMapping['handler.'.DummyMessage::class]->getValues()[0];
122+
$dummyHandlerDefinition = $container->getDefinition($dummyHandlerReference);
123+
$this->assertSame('callable', $dummyHandlerDefinition->getClass());
124+
$this->assertEquals(array(new Reference(HandlerMappingMethods::class), 'dummyMethod'), $dummyHandlerDefinition->getArgument(0));
125+
$this->assertSame(array('Closure', 'fromCallable'), $dummyHandlerDefinition->getFactory());
126+
127+
$secondHandlerReference = (string) $handlerMapping['handler.'.SecondMessage::class]->getValues()[0];
128+
$secondHandlerDefinition = $container->getDefinition($secondHandlerReference);
129+
$this->assertSame(ChainHandler::class, $secondHandlerDefinition->getClass());
130+
$this->assertEquals(new Reference(PrioritizedHandler::class), $secondHandlerDefinition->getArgument(0)[1]);
131+
}
132+
133+
/**
134+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
135+
* @expectedExceptionMessage Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\HandlerMappingWithNonExistentMethod": method "Symfony\Component\Messenger\Tests\DependencyInjection\HandlerMappingWithNonExistentMethod::dummyMethod()" does not exist.
136+
*/
137+
public function testThrowsExceptionIfTheHandlerMethodDoesNotExist()
138+
{
139+
$container = $this->getContainerBuilder();
140+
$container
141+
->register(HandlerMappingWithNonExistentMethod::class, HandlerMappingWithNonExistentMethod::class)
142+
->addTag('messenger.message_handler')
143+
;
144+
145+
(new MessengerPass())->process($container);
146+
}
147+
101148
public function testItRegistersReceivers()
102149
{
103150
$container = $this->getContainerBuilder();
@@ -397,7 +444,7 @@ public function __invoke(UndefinedMessage $message)
397444

398445
class UndefinedMessageHandlerViaInterface implements MessageSubscriberInterface
399446
{
400-
public static function getHandledMessages(): array
447+
public static function getHandledMessages(): iterable
401448
{
402449
return array(UndefinedMessage::class);
403450
}
@@ -434,31 +481,72 @@ public function __invoke(string $message)
434481

435482
class HandlerWithMultipleMessages implements MessageSubscriberInterface
436483
{
437-
public static function getHandledMessages(): array
484+
public static function getHandledMessages(): iterable
438485
{
439486
return array(
440487
DummyMessage::class,
441488
SecondMessage::class,
442489
);
443490
}
491+
492+
public function __invoke()
493+
{
494+
}
444495
}
445496

446497
class PrioritizedHandler implements MessageSubscriberInterface
447498
{
448-
public static function getHandledMessages(): array
499+
public static function getHandledMessages(): iterable
449500
{
450501
return array(
451502
array(SecondMessage::class, 10),
452503
);
453504
}
505+
506+
public function __invoke()
507+
{
508+
}
509+
}
510+
511+
class HandlerMappingMethods implements MessageSubscriberInterface
512+
{
513+
public static function getHandledMessages(): iterable
514+
{
515+
return array(
516+
DummyMessage::class => 'dummyMethod',
517+
SecondMessage::class => array('secondMessage', 20),
518+
);
519+
}
520+
521+
public function dummyMethod()
522+
{
523+
}
524+
525+
public function secondMessage()
526+
{
527+
}
528+
}
529+
530+
class HandlerMappingWithNonExistentMethod implements MessageSubscriberInterface
531+
{
532+
public static function getHandledMessages(): iterable
533+
{
534+
return array(
535+
DummyMessage::class => 'dummyMethod',
536+
);
537+
}
454538
}
455539

456540
class HandleNoMessageHandler implements MessageSubscriberInterface
457541
{
458-
public static function getHandledMessages(): array
542+
public static function getHandledMessages(): iterable
459543
{
460544
return array();
461545
}
546+
547+
public function __invoke()
548+
{
549+
}
462550
}
463551

464552
class UselessMiddleware implements MiddlewareInterface

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.