Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ecc9a92

Browse files
committed
[Messenger] added a SenderLocator decoupled from ContainerInterface
1 parent f2f4cd8 commit ecc9a92

File tree

9 files changed

+213
-91
lines changed

9 files changed

+213
-91
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<defaults public="false" />
99

1010
<!-- Asynchronous -->
11-
<service id="messenger.asynchronous.routing.sender_locator" class="Symfony\Component\Messenger\Asynchronous\Routing\SenderLocator">
11+
<service id="messenger.asynchronous.routing.sender_locator" class="Symfony\Component\Messenger\Asynchronous\Routing\ContainerSenderLocator">
1212
<argument type="service" id="messenger.sender_locator" />
1313
<argument type="collection" /> <!-- Message to sender ID mapping -->
1414
</service>

src/Symfony/Component/Messenger/Asynchronous/Middleware/SendMessageMiddleware.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace Symfony\Component\Messenger\Asynchronous\Middleware;
1313

14-
use Symfony\Component\Messenger\Asynchronous\Routing\SenderLocator;
14+
use Symfony\Component\Messenger\Asynchronous\Routing\AbstractSenderLocator;
1515
use Symfony\Component\Messenger\Asynchronous\Routing\SenderLocatorInterface;
1616
use Symfony\Component\Messenger\Asynchronous\Transport\ReceivedMessage;
1717
use Symfony\Component\Messenger\Envelope;
@@ -60,6 +60,6 @@ public function handle($envelope, callable $next)
6060

6161
private function mustSendAndHandle($message): bool
6262
{
63-
return (bool) SenderLocator::getValueFromMessageRouting($this->messagesToSendAndHandleMapping, $message);
63+
return (bool) AbstractSenderLocator::getValueFromMessageRouting($this->messagesToSendAndHandleMapping, $message);
6464
}
6565
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Component\Messenger\Asynchronous\Routing;
13+
14+
/**
15+
* @author Samuel Roze <[email protected]>
16+
*/
17+
abstract class AbstractSenderLocator implements SenderLocatorInterface
18+
{
19+
public static function getValueFromMessageRouting(array $mapping, $message)
20+
{
21+
if (isset($mapping[\get_class($message)])) {
22+
return $mapping[\get_class($message)];
23+
}
24+
if ($parentsMapping = array_intersect_key($mapping, class_parents($message))) {
25+
return current($parentsMapping);
26+
}
27+
if ($interfaceMapping = array_intersect_key($mapping, class_implements($message))) {
28+
return current($interfaceMapping);
29+
}
30+
if (isset($mapping['*'])) {
31+
return $mapping['*'];
32+
}
33+
34+
return null;
35+
}
36+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Component\Messenger\Asynchronous\Routing;
13+
14+
use Psr\Container\ContainerInterface;
15+
use Symfony\Component\Messenger\Transport\SenderInterface;
16+
17+
/**
18+
* @author Samuel Roze <[email protected]>
19+
*/
20+
class ContainerSenderLocator extends AbstractSenderLocator
21+
{
22+
private $senderServiceLocator;
23+
private $messageToSenderIdMapping;
24+
25+
public function __construct(ContainerInterface $senderServiceLocator, array $messageToSenderIdMapping)
26+
{
27+
$this->senderServiceLocator = $senderServiceLocator;
28+
$this->messageToSenderIdMapping = $messageToSenderIdMapping;
29+
}
30+
31+
/**
32+
* {@inheritdoc}
33+
*/
34+
public function getSenderForMessage($message): ?SenderInterface
35+
{
36+
$senderId = self::getValueFromMessageRouting($this->messageToSenderIdMapping, $message);
37+
38+
return $senderId ? $this->senderServiceLocator->get($senderId) : null;
39+
}
40+
}

src/Symfony/Component/Messenger/Asynchronous/Routing/SenderLocator.php

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,56 +11,35 @@
1111

1212
namespace Symfony\Component\Messenger\Asynchronous\Routing;
1313

14-
use Psr\Container\ContainerInterface;
1514
use Symfony\Component\Messenger\Transport\SenderInterface;
15+
use Symfony\Component\Messenger\Exception\RuntimeException;
1616

1717
/**
18-
* @author Samuel Roze <samuel.roze@gmail.com>
18+
* @author Fabien Potencier <fabien@symfony.com>
1919
*/
20-
class SenderLocator implements SenderLocatorInterface
20+
class SenderLocator extends AbstractSenderLocator
2121
{
22-
private $senderServiceLocator;
23-
private $messageToSenderIdMapping;
22+
private $messageToSenderMapping;
2423

25-
public function __construct(ContainerInterface $senderServiceLocator, array $messageToSenderIdMapping)
24+
public function __construct(array $messageToSenderMapping)
2625
{
27-
$this->senderServiceLocator = $senderServiceLocator;
28-
$this->messageToSenderIdMapping = $messageToSenderIdMapping;
26+
$this->messageToSenderMapping = $messageToSenderMapping;
2927
}
3028

3129
/**
3230
* {@inheritdoc}
3331
*/
3432
public function getSenderForMessage($message): ?SenderInterface
3533
{
36-
$senderId = $this->getSenderId($message);
37-
38-
return $senderId ? $this->senderServiceLocator->get($senderId) : null;
39-
}
40-
41-
private function getSenderId($message): ?string
42-
{
43-
return self::getValueFromMessageRouting($this->messageToSenderIdMapping, $message);
44-
}
45-
46-
/**
47-
* @internal
48-
*/
49-
public static function getValueFromMessageRouting(array $mapping, $message)
50-
{
51-
if (isset($mapping[\get_class($message)])) {
52-
return $mapping[\get_class($message)];
34+
$sender = self::getValueFromMessageRouting($this->messageToSenderMapping, $message);
35+
if (null === $sender) {
36+
return null;
5337
}
54-
if ($parentsMapping = array_intersect_key($mapping, class_parents($message))) {
55-
return current($parentsMapping);
56-
}
57-
if ($interfaceMapping = array_intersect_key($mapping, class_implements($message))) {
58-
return current($interfaceMapping);
59-
}
60-
if (isset($mapping['*'])) {
61-
return $mapping['*'];
38+
39+
if (!$sender instanceof SenderInterface) {
40+
throw new RuntimeException(sprintf('The sender instance provided for message "%s" should be of type "%s" but got "%s".', \get_class($message), SenderInterface::class, is_object($sender) ? get_class($sender) : gettype($sender)));
6241
}
6342

64-
return null;
43+
return $sender;
6544
}
6645
}

src/Symfony/Component/Messenger/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ CHANGELOG
44
4.2.0
55
-----
66

7+
* [BC BREAK] `SenderLocator` has been renamed to `ContainerSenderLocator`
8+
Be careful as there is still a `SenderLocator` class, but it does not rely on a `ContainerInterface` to find senders.
9+
Instead, it accepts the sender instance itself instead of its identifier in the container.
710
* [BC BREAK] `MessageSubscriberInterface::getHandledMessages()` return value has changed. The value of an array item
811
needs to be an associative array or the method name.
912
* `ValidationMiddleware::handle()` and `SendMessageMiddleware::handle()` now require an `Envelope` object
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Component\Messenger\Exception;
13+
14+
/**
15+
* @author Fabien Potencier <[email protected]>
16+
*/
17+
class RuntimeException extends \RuntimeException implements ExceptionInterface
18+
{
19+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Component\Messenger\Tests\Asynchronous\Routing;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Container;
16+
use Symfony\Component\Messenger\Asynchronous\Routing\ContainerSenderLocator;
17+
use Symfony\Component\Messenger\Tests\Fixtures\ChildDummyMessage;
18+
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
19+
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageInterface;
20+
use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage;
21+
use Symfony\Component\Messenger\Transport\SenderInterface;
22+
23+
class ContainerSenderLocatorTest extends TestCase
24+
{
25+
public function testItReturnsTheSenderBasedOnTheMessageClass()
26+
{
27+
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
28+
$container = new Container();
29+
$container->set('my_amqp_sender', $sender);
30+
31+
$locator = new ContainerSenderLocator($container, array(
32+
DummyMessage::class => 'my_amqp_sender',
33+
));
34+
35+
$this->assertSame($sender, $locator->getSenderForMessage(new DummyMessage('Hello')));
36+
$this->assertNull($locator->getSenderForMessage(new SecondMessage()));
37+
}
38+
39+
public function testItReturnsTheSenderBasedOnTheMessageParentClass()
40+
{
41+
$container = new Container();
42+
43+
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
44+
$container->set('my_amqp_sender', $sender);
45+
46+
$apiSender = $this->getMockBuilder(SenderInterface::class)->getMock();
47+
$container->set('my_api_sender', $apiSender);
48+
49+
$locator = new ContainerSenderLocator($container, array(
50+
DummyMessageInterface::class => 'my_api_sender',
51+
DummyMessage::class => 'my_amqp_sender',
52+
));
53+
54+
$this->assertSame($sender, $locator->getSenderForMessage(new ChildDummyMessage('Hello')));
55+
$this->assertNull($locator->getSenderForMessage(new SecondMessage()));
56+
}
57+
58+
public function testItReturnsTheSenderBasedOnTheMessageInterface()
59+
{
60+
$container = new Container();
61+
62+
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
63+
$container->set('my_amqp_sender', $sender);
64+
65+
$locator = new ContainerSenderLocator($container, array(
66+
DummyMessageInterface::class => 'my_amqp_sender',
67+
));
68+
69+
$this->assertSame($sender, $locator->getSenderForMessage(new DummyMessage('Hello')));
70+
$this->assertNull($locator->getSenderForMessage(new SecondMessage()));
71+
}
72+
73+
public function testItSupportsAWildcardInsteadOfTheMessageClass()
74+
{
75+
$container = new Container();
76+
77+
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
78+
$container->set('my_amqp_sender', $sender);
79+
80+
$apiSender = $this->getMockBuilder(SenderInterface::class)->getMock();
81+
$container->set('my_api_sender', $apiSender);
82+
83+
$locator = new ContainerSenderLocator($container, array(
84+
DummyMessage::class => 'my_amqp_sender',
85+
'*' => 'my_api_sender',
86+
));
87+
88+
$this->assertSame($sender, $locator->getSenderForMessage(new DummyMessage('Hello')));
89+
$this->assertSame($apiSender, $locator->getSenderForMessage(new SecondMessage()));
90+
}
91+
}

src/Symfony/Component/Messenger/Tests/Asynchronous/Routing/SenderLocatorTest.php

Lines changed: 8 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
namespace Symfony\Component\Messenger\Tests\Asynchronous\Routing;
1313

1414
use PHPUnit\Framework\TestCase;
15-
use Symfony\Component\DependencyInjection\Container;
1615
use Symfony\Component\Messenger\Asynchronous\Routing\SenderLocator;
16+
use Symfony\Component\Messenger\Exception\RuntimeException;
1717
use Symfony\Component\Messenger\Tests\Fixtures\ChildDummyMessage;
1818
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
1919
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageInterface;
@@ -25,67 +25,21 @@ class SenderLocatorTest extends TestCase
2525
public function testItReturnsTheSenderBasedOnTheMessageClass()
2626
{
2727
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
28-
$container = new Container();
29-
$container->set('my_amqp_sender', $sender);
30-
31-
$locator = new SenderLocator($container, array(
32-
DummyMessage::class => 'my_amqp_sender',
33-
));
34-
35-
$this->assertSame($sender, $locator->getSenderForMessage(new DummyMessage('Hello')));
36-
$this->assertNull($locator->getSenderForMessage(new SecondMessage()));
37-
}
38-
39-
public function testItReturnsTheSenderBasedOnTheMessageParentClass()
40-
{
41-
$container = new Container();
42-
43-
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
44-
$container->set('my_amqp_sender', $sender);
45-
46-
$apiSender = $this->getMockBuilder(SenderInterface::class)->getMock();
47-
$container->set('my_api_sender', $apiSender);
48-
49-
$locator = new SenderLocator($container, array(
50-
DummyMessageInterface::class => 'my_api_sender',
51-
DummyMessage::class => 'my_amqp_sender',
52-
));
53-
54-
$this->assertSame($sender, $locator->getSenderForMessage(new ChildDummyMessage('Hello')));
55-
$this->assertNull($locator->getSenderForMessage(new SecondMessage()));
56-
}
57-
58-
public function testItReturnsTheSenderBasedOnTheMessageInterface()
59-
{
60-
$container = new Container();
61-
62-
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
63-
$container->set('my_amqp_sender', $sender);
64-
65-
$locator = new SenderLocator($container, array(
66-
DummyMessageInterface::class => 'my_amqp_sender',
28+
$locator = new SenderLocator(array(
29+
DummyMessage::class => $sender,
6730
));
6831

6932
$this->assertSame($sender, $locator->getSenderForMessage(new DummyMessage('Hello')));
7033
$this->assertNull($locator->getSenderForMessage(new SecondMessage()));
7134
}
7235

73-
public function testItSupportsAWildcardInsteadOfTheMessageClass()
36+
public function testItThrowsExceptionIfConfigurationIsWrong()
7437
{
75-
$container = new Container();
76-
77-
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
78-
$container->set('my_amqp_sender', $sender);
79-
80-
$apiSender = $this->getMockBuilder(SenderInterface::class)->getMock();
81-
$container->set('my_api_sender', $apiSender);
82-
83-
$locator = new SenderLocator($container, array(
84-
DummyMessage::class => 'my_amqp_sender',
85-
'*' => 'my_api_sender',
38+
$locator = new SenderLocator(array(
39+
DummyMessage::class => 'amqp',
8640
));
8741

88-
$this->assertSame($sender, $locator->getSenderForMessage(new DummyMessage('Hello')));
89-
$this->assertSame($apiSender, $locator->getSenderForMessage(new SecondMessage()));
42+
$this->expectException(RuntimeException::class);
43+
$locator->getSenderForMessage(new DummyMessage('Hello'));
9044
}
9145
}

0 commit comments

Comments
 (0)