From 8b86e7d03c9daddf87d8fa9b56955c9fcb5e6a56 Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Tue, 11 May 2021 22:16:57 +0300 Subject: [PATCH 01/14] [Messenger] Add Senders attribute to configure message to sender mapping --- .../Component/Messenger/Attribute/Senders.php | 22 ++++++++ .../Fixtures/DummyMessageWithAttribute.php | 21 ++++++++ .../Transport/Sender/SendersLocatorTest.php | 13 +++++ .../Transport/Sender/SendersLocator.php | 51 +++++++++++++++---- 4 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 src/Symfony/Component/Messenger/Attribute/Senders.php create mode 100644 src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php diff --git a/src/Symfony/Component/Messenger/Attribute/Senders.php b/src/Symfony/Component/Messenger/Attribute/Senders.php new file mode 100644 index 0000000000000..56b2e34c8eab5 --- /dev/null +++ b/src/Symfony/Component/Messenger/Attribute/Senders.php @@ -0,0 +1,22 @@ + + */ +#[\Attribute(\Attribute::TARGET_CLASS)] +class Senders +{ + public array $senders; + + /** + * @param string[] $senders + */ + public function __construct(string ...$senders) + { + $this->senders = $senders; + } +} diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php new file mode 100644 index 0000000000000..5fdfb87b5d300 --- /dev/null +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php @@ -0,0 +1,21 @@ +message = $message; + } + + public function getMessage(): string + { + return $this->message; + } +} diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php index db4cb0efa0782..1c16b412a2367 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php @@ -15,12 +15,25 @@ use Psr\Container\ContainerInterface; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; +use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageWithAttribute; use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage; use Symfony\Component\Messenger\Transport\Sender\SenderInterface; use Symfony\Component\Messenger\Transport\Sender\SendersLocator; class SendersLocatorTest extends TestCase { + public function testAttributeMapping() + { + $sender = $this->createMock(SenderInterface::class); + $sendersLocator = $this->createContainer([ + 'my_sender' => $sender, + ]); + $locator = new SendersLocator([], $sendersLocator); + + $this->assertSame(['my_sender' => $sender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttribute('a'))))); + $this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new DummyMessage('a'))))); + } + public function testItReturnsTheSenderBasedOnTheMessageClass() { $sender = $this->createMock(SenderInterface::class); diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index cda20008c8768..b9ff43223a7b9 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Messenger\Transport\Sender; use Psr\Container\ContainerInterface; +use Symfony\Component\Messenger\Attribute\Senders; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\RuntimeException; use Symfony\Component\Messenger\Handler\HandlersLocator; @@ -41,20 +42,50 @@ public function __construct(array $sendersMap, ContainerInterface $sendersLocato */ public function getSenders(Envelope $envelope): iterable { - $seen = []; + $senderAliases = $this->getSendersFromAttributes($envelope); foreach (HandlersLocator::listTypes($envelope) as $type) { foreach ($this->sendersMap[$type] ?? [] as $senderAlias) { - if (!\in_array($senderAlias, $seen, true)) { - if (!$this->sendersLocator->has($senderAlias)) { - throw new RuntimeException(sprintf('Invalid senders configuration: sender "%s" is not in the senders locator.', $senderAlias)); - } - - $seen[] = $senderAlias; - $sender = $this->sendersLocator->get($senderAlias); - yield $senderAlias => $sender; - } + $senderAliases[] = $senderAlias; } } + + $senderAliases = array_unique($senderAliases); + + foreach ($senderAliases as $senderAlias) { + if (!$this->sendersLocator->has($senderAlias)) { + throw new RuntimeException(sprintf('Invalid senders configuration: sender "%s" is not in the senders locator.', $senderAlias)); + } + + $sender = $this->sendersLocator->get($senderAlias); + yield $senderAlias => $sender; + } + } + + /** + * @param Envelope $envelope + * + * @return string[] + */ + private function getSendersFromAttributes(Envelope $envelope): array + { + $messageClass = get_class($envelope->getMessage()); + + try { + $reflectionClass = new \ReflectionClass($messageClass); + } catch (\ReflectionException $e) { + return []; + } + + $attributes = $reflectionClass->getAttributes(Senders::class); + + $senders = []; + foreach ($attributes as $attribute) { + /** @var Senders $attributeInstance */ + $attributeInstance = $attribute->newInstance(); + $senders = array_merge($senders, $attributeInstance->senders); + } + + return $senders; } } From 575487417575338cd4b25f0ce936902ac423ce54 Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Tue, 11 May 2021 22:33:55 +0300 Subject: [PATCH 02/14] [Messenger] Enable attribute reading only for PHP 8 --- .../Messenger/Tests/Transport/Sender/SendersLocatorTest.php | 3 +++ .../Component/Messenger/Transport/Sender/SendersLocator.php | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php index 1c16b412a2367..95a3fac922ce7 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php @@ -22,6 +22,9 @@ class SendersLocatorTest extends TestCase { + /** + * @requires PHP 8 + */ public function testAttributeMapping() { $sender = $this->createMock(SenderInterface::class); diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index b9ff43223a7b9..fec80a76aae18 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -42,7 +42,11 @@ public function __construct(array $sendersMap, ContainerInterface $sendersLocato */ public function getSenders(Envelope $envelope): iterable { - $senderAliases = $this->getSendersFromAttributes($envelope); + $senderAliases = []; + + if (\PHP_VERSION_ID >= 80000) { + $senderAliases = $this->getSendersFromAttributes($envelope); + } foreach (HandlersLocator::listTypes($envelope) as $type) { foreach ($this->sendersMap[$type] ?? [] as $senderAlias) { From 2d4938ca0dc93b5206dc4d3a039ae8a5f5b5861a Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Tue, 11 May 2021 22:48:43 +0300 Subject: [PATCH 03/14] [Messenger] Add entry to changelog --- src/Symfony/Component/Messenger/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md index 98193ec5c02c4..c73e055cad144 100644 --- a/src/Symfony/Component/Messenger/CHANGELOG.md +++ b/src/Symfony/Component/Messenger/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * Add `SerializedMessageStamp` to avoid serializing a message when a retry occurs. * Automatically resolve handled message type when method different from `__invoke` is used as handler. + * Add `Senders` attribute to configure message to sender mapping 6.0 --- From dec6ddc9e45354e7ce3b4b2d298bc97b1a9c7e4c Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Tue, 11 May 2021 22:56:42 +0300 Subject: [PATCH 04/14] [Messenger] Add license header and fix code style --- src/Symfony/Component/Messenger/Attribute/Senders.php | 9 +++++++++ .../Messenger/Transport/Sender/SendersLocator.php | 4 +--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Messenger/Attribute/Senders.php b/src/Symfony/Component/Messenger/Attribute/Senders.php index 56b2e34c8eab5..07e5585c5b6a7 100644 --- a/src/Symfony/Component/Messenger/Attribute/Senders.php +++ b/src/Symfony/Component/Messenger/Attribute/Senders.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + declare(strict_types=1); namespace Symfony\Component\Messenger\Attribute; diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index fec80a76aae18..cd60ec9d3b2fe 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -67,13 +67,11 @@ public function getSenders(Envelope $envelope): iterable } /** - * @param Envelope $envelope - * * @return string[] */ private function getSendersFromAttributes(Envelope $envelope): array { - $messageClass = get_class($envelope->getMessage()); + $messageClass = \get_class($envelope->getMessage()); try { $reflectionClass = new \ReflectionClass($messageClass); From 8f4ae6cc51474b4557300ba41a81fe0d1a7066b9 Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Wed, 12 May 2021 00:05:39 +0300 Subject: [PATCH 05/14] [Messenger] Remove strict types --- src/Symfony/Component/Messenger/Attribute/Senders.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Symfony/Component/Messenger/Attribute/Senders.php b/src/Symfony/Component/Messenger/Attribute/Senders.php index 07e5585c5b6a7..84ae90f9588dd 100644 --- a/src/Symfony/Component/Messenger/Attribute/Senders.php +++ b/src/Symfony/Component/Messenger/Attribute/Senders.php @@ -9,8 +9,6 @@ * file that was distributed with this source code. */ -declare(strict_types=1); - namespace Symfony\Component\Messenger\Attribute; /** From 606e7d06359ed95d149b23a990cb8a05215f07c7 Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Wed, 12 May 2021 22:17:56 +0300 Subject: [PATCH 06/14] [Messenger] Fix code review comments Overwrite config routing Read from parent interfaces and classes Add tests --- .../Attribute/{Senders.php => Transport.php} | 13 +++--- .../DummyMessageInterfaceWithAttribute.php | 10 +++++ .../Fixtures/DummyMessageWithAttribute.php | 4 +- .../DummyMessageWithAttributeAndInterface.php | 21 +++++++++ .../Transport/Sender/SendersLocatorTest.php | 20 ++++++++- .../Transport/Sender/SendersLocator.php | 45 +++++++++++-------- 6 files changed, 83 insertions(+), 30 deletions(-) rename src/Symfony/Component/Messenger/Attribute/{Senders.php => Transport.php} (63%) create mode 100644 src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageInterfaceWithAttribute.php create mode 100644 src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttributeAndInterface.php diff --git a/src/Symfony/Component/Messenger/Attribute/Senders.php b/src/Symfony/Component/Messenger/Attribute/Transport.php similarity index 63% rename from src/Symfony/Component/Messenger/Attribute/Senders.php rename to src/Symfony/Component/Messenger/Attribute/Transport.php index 84ae90f9588dd..3d5998975c5f0 100644 --- a/src/Symfony/Component/Messenger/Attribute/Senders.php +++ b/src/Symfony/Component/Messenger/Attribute/Transport.php @@ -14,16 +14,13 @@ /** * @author Maxim Dovydenok */ -#[\Attribute(\Attribute::TARGET_CLASS)] -class Senders +#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] +class Transport { - public array $senders; + public string $name; - /** - * @param string[] $senders - */ - public function __construct(string ...$senders) + public function __construct(string $name) { - $this->senders = $senders; + $this->name = $name; } } diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageInterfaceWithAttribute.php b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageInterfaceWithAttribute.php new file mode 100644 index 0000000000000..70600c60045a4 --- /dev/null +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageInterfaceWithAttribute.php @@ -0,0 +1,10 @@ +message = $message; + } + + public function getMessage(): string + { + return $this->message; + } +} diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php index 95a3fac922ce7..9787bfbe01139 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php @@ -16,6 +16,7 @@ use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageWithAttribute; +use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageWithAttributeAndInterface; use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage; use Symfony\Component\Messenger\Transport\Sender\SenderInterface; use Symfony\Component\Messenger\Transport\Sender\SendersLocator; @@ -30,11 +31,28 @@ public function testAttributeMapping() $sender = $this->createMock(SenderInterface::class); $sendersLocator = $this->createContainer([ 'my_sender' => $sender, + 'my_common_sender' => $sender, + 'my_merged_sender' => $sender, ]); $locator = new SendersLocator([], $sendersLocator); + $locatorWithRouting = new SendersLocator([ + DummyMessageWithAttribute::class => ['my_merged_sender'], + ], $sendersLocator); - $this->assertSame(['my_sender' => $sender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttribute('a'))))); $this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new DummyMessage('a'))))); + $this->assertSame( + ['my_sender' => $sender], + iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttribute('a')))) + ); + $this->assertSame( + ['my_sender' => $sender, 'my_common_sender' => $sender], + iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttributeAndInterface('a')))) + ); + + $this->assertSame( + ['my_sender' => $sender], + iterator_to_array($locatorWithRouting->getSenders(new Envelope(new DummyMessageWithAttribute('a')))) + ); } public function testItReturnsTheSenderBasedOnTheMessageClass() diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index cd60ec9d3b2fe..d55abfd88d17b 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Messenger\Transport\Sender; use Psr\Container\ContainerInterface; -use Symfony\Component\Messenger\Attribute\Senders; +use Symfony\Component\Messenger\Attribute\Transport; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\RuntimeException; use Symfony\Component\Messenger\Handler\HandlersLocator; @@ -44,16 +44,20 @@ public function getSenders(Envelope $envelope): iterable { $senderAliases = []; - if (\PHP_VERSION_ID >= 80000) { - $senderAliases = $this->getSendersFromAttributes($envelope); - } - foreach (HandlersLocator::listTypes($envelope) as $type) { foreach ($this->sendersMap[$type] ?? [] as $senderAlias) { $senderAliases[] = $senderAlias; } } + if (\PHP_VERSION_ID >= 80000) { + $senderAliasesFromAttributes = $this->getSendersFromAttributes($envelope); + + if (!empty($senderAliasesFromAttributes)) { + $senderAliases = $senderAliasesFromAttributes; + } + } + $senderAliases = array_unique($senderAliases); foreach ($senderAliases as $senderAlias) { @@ -71,21 +75,24 @@ public function getSenders(Envelope $envelope): iterable */ private function getSendersFromAttributes(Envelope $envelope): array { - $messageClass = \get_class($envelope->getMessage()); - - try { - $reflectionClass = new \ReflectionClass($messageClass); - } catch (\ReflectionException $e) { - return []; - } - - $attributes = $reflectionClass->getAttributes(Senders::class); - $senders = []; - foreach ($attributes as $attribute) { - /** @var Senders $attributeInstance */ - $attributeInstance = $attribute->newInstance(); - $senders = array_merge($senders, $attributeInstance->senders); + + foreach (HandlersLocator::listTypes($envelope) as $type) { + if (class_exists($type) || interface_exists($type)) { + try { + $reflectionClass = new \ReflectionClass($type); + } catch (\ReflectionException $e) { + continue; + } + + $attributes = $reflectionClass->getAttributes(Transport::class); + + foreach ($attributes as $attribute) { + /** @var Transport $attributeInstance */ + $attributeInstance = $attribute->newInstance(); + $senders[] = $attributeInstance->name; + } + } } return $senders; From c8daecdb0c1d6d737fb026fe2e00b4c736b37a25 Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Wed, 12 May 2021 22:22:13 +0300 Subject: [PATCH 07/14] [Messenger] Added test for multiple attributes --- .../Messenger/Tests/Fixtures/DummyMessageWithAttribute.php | 1 + .../Messenger/Tests/Transport/Sender/SendersLocatorTest.php | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php index 17e67baf9fc08..b977219519b8a 100644 --- a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php @@ -5,6 +5,7 @@ use Symfony\Component\Messenger\Attribute\Transport; #[Transport('my_sender')] +#[Transport('my_second_sender')] class DummyMessageWithAttribute implements DummyMessageInterface { private $message; diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php index 9787bfbe01139..e2050f5b68b20 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php @@ -31,6 +31,7 @@ public function testAttributeMapping() $sender = $this->createMock(SenderInterface::class); $sendersLocator = $this->createContainer([ 'my_sender' => $sender, + 'my_second_sender' => $sender, 'my_common_sender' => $sender, 'my_merged_sender' => $sender, ]); @@ -41,7 +42,7 @@ public function testAttributeMapping() $this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new DummyMessage('a'))))); $this->assertSame( - ['my_sender' => $sender], + ['my_sender' => $sender, 'my_second_sender' => $sender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttribute('a')))) ); $this->assertSame( @@ -50,7 +51,7 @@ public function testAttributeMapping() ); $this->assertSame( - ['my_sender' => $sender], + ['my_sender' => $sender, 'my_second_sender' => $sender], iterator_to_array($locatorWithRouting->getSenders(new Envelope(new DummyMessageWithAttribute('a')))) ); } From 54784eea218a8670cb010a2488a335fe7e867cbb Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Thu, 13 May 2021 14:01:47 +0300 Subject: [PATCH 08/14] [Messenger] Overwrite attributes if framework's config is specified --- .../Tests/Transport/Sender/SendersLocatorTest.php | 10 +++++----- .../Messenger/Transport/Sender/SendersLocator.php | 8 ++------ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php index e2050f5b68b20..b9853d66c4dc1 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php @@ -35,11 +35,8 @@ public function testAttributeMapping() 'my_common_sender' => $sender, 'my_merged_sender' => $sender, ]); - $locator = new SendersLocator([], $sendersLocator); - $locatorWithRouting = new SendersLocator([ - DummyMessageWithAttribute::class => ['my_merged_sender'], - ], $sendersLocator); + $locator = new SendersLocator([], $sendersLocator); $this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new DummyMessage('a'))))); $this->assertSame( ['my_sender' => $sender, 'my_second_sender' => $sender], @@ -50,8 +47,11 @@ public function testAttributeMapping() iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttributeAndInterface('a')))) ); + $locatorWithRouting = new SendersLocator([ + DummyMessageWithAttribute::class => ['my_merged_sender'], + ], $sendersLocator); $this->assertSame( - ['my_sender' => $sender, 'my_second_sender' => $sender], + ['my_merged_sender' => $sender], iterator_to_array($locatorWithRouting->getSenders(new Envelope(new DummyMessageWithAttribute('a')))) ); } diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index d55abfd88d17b..7c35fb7e1df4b 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -50,12 +50,8 @@ public function getSenders(Envelope $envelope): iterable } } - if (\PHP_VERSION_ID >= 80000) { - $senderAliasesFromAttributes = $this->getSendersFromAttributes($envelope); - - if (!empty($senderAliasesFromAttributes)) { - $senderAliases = $senderAliasesFromAttributes; - } + if (\PHP_VERSION_ID >= 80000 && empty($senderAliases)) { + $senderAliases = $this->getSendersFromAttributes($envelope); } $senderAliases = array_unique($senderAliases); From 9ada6e66ddefe5c09998703110e1915b80a9e2a8 Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Thu, 13 May 2021 14:56:18 +0300 Subject: [PATCH 09/14] [Messenger] Add tests and rename senders --- .../DummyMessageInterfaceWithAttribute.php | 2 +- .../Fixtures/DummyMessageWithAttribute.php | 4 ++-- .../DummyMessageWithAttributeAndInterface.php | 2 +- .../Transport/Sender/SendersLocatorTest.php | 24 ++++++++++++------- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageInterfaceWithAttribute.php b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageInterfaceWithAttribute.php index 70600c60045a4..0f9a78b34072a 100644 --- a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageInterfaceWithAttribute.php +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageInterfaceWithAttribute.php @@ -4,7 +4,7 @@ use Symfony\Component\Messenger\Attribute\Transport; -#[Transport('my_common_sender')] +#[Transport('interface_attribute_sender')] interface DummyMessageInterfaceWithAttribute { } diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php index b977219519b8a..9d120890a0dd1 100644 --- a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php @@ -4,8 +4,8 @@ use Symfony\Component\Messenger\Attribute\Transport; -#[Transport('my_sender')] -#[Transport('my_second_sender')] +#[Transport('message_attribute_sender')] +#[Transport('message_attribute_sender_2')] class DummyMessageWithAttribute implements DummyMessageInterface { private $message; diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttributeAndInterface.php b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttributeAndInterface.php index 919849854fb71..cb447a6a9b4a4 100644 --- a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttributeAndInterface.php +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttributeAndInterface.php @@ -4,7 +4,7 @@ use Symfony\Component\Messenger\Attribute\Transport; -#[Transport('my_sender')] +#[Transport('message_attribute_sender')] class DummyMessageWithAttributeAndInterface implements DummyMessageInterfaceWithAttribute { private $message; diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php index b9853d66c4dc1..c42f073b83105 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php @@ -15,6 +15,7 @@ use Psr\Container\ContainerInterface; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; +use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageInterfaceWithAttribute; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageWithAttribute; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageWithAttributeAndInterface; use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage; @@ -30,30 +31,37 @@ public function testAttributeMapping() { $sender = $this->createMock(SenderInterface::class); $sendersLocator = $this->createContainer([ - 'my_sender' => $sender, - 'my_second_sender' => $sender, - 'my_common_sender' => $sender, - 'my_merged_sender' => $sender, + 'message_attribute_sender' => $sender, + 'message_attribute_sender_2' => $sender, + 'interface_attribute_sender' => $sender, + 'message_config_sender' => $sender, + 'interface_config_sender' => $sender, ]); $locator = new SendersLocator([], $sendersLocator); $this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new DummyMessage('a'))))); $this->assertSame( - ['my_sender' => $sender, 'my_second_sender' => $sender], + ['message_attribute_sender' => $sender, 'message_attribute_sender_2' => $sender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttribute('a')))) ); $this->assertSame( - ['my_sender' => $sender, 'my_common_sender' => $sender], + ['message_attribute_sender' => $sender, 'interface_attribute_sender' => $sender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttributeAndInterface('a')))) ); $locatorWithRouting = new SendersLocator([ - DummyMessageWithAttribute::class => ['my_merged_sender'], + DummyMessageWithAttribute::class => ['message_config_sender'], + DummyMessageWithAttributeAndInterface::class => ['message_config_sender'], + DummyMessageInterfaceWithAttribute::class => ['interface_config_sender'], ], $sendersLocator); $this->assertSame( - ['my_merged_sender' => $sender], + ['message_config_sender' => $sender], iterator_to_array($locatorWithRouting->getSenders(new Envelope(new DummyMessageWithAttribute('a')))) ); + $this->assertSame( + ['message_config_sender' => $sender, 'interface_config_sender' => $sender], + iterator_to_array($locatorWithRouting->getSenders(new Envelope(new DummyMessageWithAttributeAndInterface('a')))) + ); } public function testItReturnsTheSenderBasedOnTheMessageClass() From 908e5f096f1f0201af838b89256e80456837c644 Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Thu, 13 May 2021 15:18:28 +0300 Subject: [PATCH 10/14] [Messenger] Change overwriting behavior, overwrite per type --- .../Transport/Sender/SendersLocatorTest.php | 30 ++++++++++-- .../Transport/Sender/SendersLocator.php | 47 ++++++++++--------- 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php index c42f073b83105..97ed250787e29 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php @@ -36,6 +36,7 @@ public function testAttributeMapping() 'interface_attribute_sender' => $sender, 'message_config_sender' => $sender, 'interface_config_sender' => $sender, + 'all_config_sender' => $sender, ]); $locator = new SendersLocator([], $sendersLocator); @@ -49,18 +50,37 @@ public function testAttributeMapping() iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttributeAndInterface('a')))) ); - $locatorWithRouting = new SendersLocator([ + $locatorWithFullRouting = new SendersLocator([ DummyMessageWithAttribute::class => ['message_config_sender'], DummyMessageWithAttributeAndInterface::class => ['message_config_sender'], DummyMessageInterfaceWithAttribute::class => ['interface_config_sender'], + '*' => ['all_config_sender'], ], $sendersLocator); $this->assertSame( - ['message_config_sender' => $sender], - iterator_to_array($locatorWithRouting->getSenders(new Envelope(new DummyMessageWithAttribute('a')))) + ['message_config_sender' => $sender, 'all_config_sender' => $sender], + iterator_to_array($locatorWithFullRouting->getSenders(new Envelope(new DummyMessageWithAttribute('a')))) ); $this->assertSame( - ['message_config_sender' => $sender, 'interface_config_sender' => $sender], - iterator_to_array($locatorWithRouting->getSenders(new Envelope(new DummyMessageWithAttributeAndInterface('a')))) + ['message_config_sender' => $sender, 'interface_config_sender' => $sender, 'all_config_sender' => $sender], + iterator_to_array($locatorWithFullRouting->getSenders(new Envelope(new DummyMessageWithAttributeAndInterface('a')))) + ); + + $locatorWithClassRouting = new SendersLocator([ + DummyMessageWithAttributeAndInterface::class => ['message_config_sender'], + '*' => ['all_config_sender'], + ], $sendersLocator); + $this->assertSame( + ['message_config_sender' => $sender, 'interface_attribute_sender' => $sender, 'all_config_sender' => $sender], + iterator_to_array($locatorWithClassRouting->getSenders(new Envelope(new DummyMessageWithAttributeAndInterface('a')))) + ); + + $locatorWithInterfaceRouting = new SendersLocator([ + DummyMessageInterfaceWithAttribute::class => ['interface_config_sender'], + '*' => ['all_config_sender'], + ], $sendersLocator); + $this->assertSame( + ['message_attribute_sender' => $sender, 'interface_config_sender' => $sender, 'all_config_sender' => $sender], + iterator_to_array($locatorWithInterfaceRouting->getSenders(new Envelope(new DummyMessageWithAttributeAndInterface('a')))) ); } diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index 7c35fb7e1df4b..ebe41ccbc8a76 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -45,13 +45,17 @@ public function getSenders(Envelope $envelope): iterable $senderAliases = []; foreach (HandlersLocator::listTypes($envelope) as $type) { + $typeSenderAliases = []; + foreach ($this->sendersMap[$type] ?? [] as $senderAlias) { - $senderAliases[] = $senderAlias; + $typeSenderAliases[] = $senderAlias; } - } - if (\PHP_VERSION_ID >= 80000 && empty($senderAliases)) { - $senderAliases = $this->getSendersFromAttributes($envelope); + if (\PHP_VERSION_ID >= 80000 && empty($typeSenderAliases)) { + $typeSenderAliases = $this->getSendersFromAttributes($type); + } + + array_push($senderAliases, ...$typeSenderAliases); } $senderAliases = array_unique($senderAliases); @@ -69,28 +73,25 @@ public function getSenders(Envelope $envelope): iterable /** * @return string[] */ - private function getSendersFromAttributes(Envelope $envelope): array + private function getSendersFromAttributes(string $type): array { - $senders = []; + if (!class_exists($type) && !interface_exists($type)) { + return []; + } - foreach (HandlersLocator::listTypes($envelope) as $type) { - if (class_exists($type) || interface_exists($type)) { - try { - $reflectionClass = new \ReflectionClass($type); - } catch (\ReflectionException $e) { - continue; - } - - $attributes = $reflectionClass->getAttributes(Transport::class); - - foreach ($attributes as $attribute) { - /** @var Transport $attributeInstance */ - $attributeInstance = $attribute->newInstance(); - $senders[] = $attributeInstance->name; - } - } + try { + $reflectionClass = new \ReflectionClass($type); + } catch (\ReflectionException $e) { + return []; } - return $senders; + $attributes = $reflectionClass->getAttributes(Transport::class); + + return array_map(function (\ReflectionAttribute $attribute): string { + /** @var Transport $attributeInstance */ + $attributeInstance = $attribute->newInstance(); + + return $attributeInstance->name; + }, $attributes); } } From af5646c626a094ab1dcf535d78d30fc967e75772 Mon Sep 17 00:00:00 2001 From: Maxim Dovydenok Date: Thu, 13 May 2021 15:31:33 +0300 Subject: [PATCH 11/14] [Messenger] Fix tests on 7.2 --- .../Component/Messenger/Transport/Sender/SendersLocator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index ebe41ccbc8a76..f819f6573c382 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -55,7 +55,7 @@ public function getSenders(Envelope $envelope): iterable $typeSenderAliases = $this->getSendersFromAttributes($type); } - array_push($senderAliases, ...$typeSenderAliases); + $senderAliases = array_merge($senderAliases, $typeSenderAliases); } $senderAliases = array_unique($senderAliases); From 016db385a9e259441a75d17ca029f007c70320fc Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Thu, 17 Mar 2022 14:56:00 -0400 Subject: [PATCH 12/14] cleanup --- src/Symfony/Component/Messenger/Attribute/Transport.php | 5 +---- src/Symfony/Component/Messenger/CHANGELOG.md | 2 +- .../Messenger/Tests/Transport/Sender/SendersLocatorTest.php | 3 --- .../Component/Messenger/Transport/Sender/SendersLocator.php | 2 +- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Messenger/Attribute/Transport.php b/src/Symfony/Component/Messenger/Attribute/Transport.php index 3d5998975c5f0..a5da179ec44e3 100644 --- a/src/Symfony/Component/Messenger/Attribute/Transport.php +++ b/src/Symfony/Component/Messenger/Attribute/Transport.php @@ -17,10 +17,7 @@ #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] class Transport { - public string $name; - - public function __construct(string $name) + public function __construct(public readonly string $name) { - $this->name = $name; } } diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md index c73e055cad144..3409acc041e13 100644 --- a/src/Symfony/Component/Messenger/CHANGELOG.md +++ b/src/Symfony/Component/Messenger/CHANGELOG.md @@ -6,7 +6,7 @@ CHANGELOG * Add `SerializedMessageStamp` to avoid serializing a message when a retry occurs. * Automatically resolve handled message type when method different from `__invoke` is used as handler. - * Add `Senders` attribute to configure message to sender mapping + * Add `Transport` attribute to configure message to sender mapping 6.0 --- diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php index 97ed250787e29..f3ee2ab3a71ed 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php @@ -24,9 +24,6 @@ class SendersLocatorTest extends TestCase { - /** - * @requires PHP 8 - */ public function testAttributeMapping() { $sender = $this->createMock(SenderInterface::class); diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index f819f6573c382..2057293e5f6ed 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -51,7 +51,7 @@ public function getSenders(Envelope $envelope): iterable $typeSenderAliases[] = $senderAlias; } - if (\PHP_VERSION_ID >= 80000 && empty($typeSenderAliases)) { + if (empty($typeSenderAliases)) { $typeSenderAliases = $this->getSendersFromAttributes($type); } From 36386880d31c03678290de5ffc30012901cf06ca Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Fri, 18 Mar 2022 11:20:13 -0400 Subject: [PATCH 13/14] fix per review --- .../Component/Messenger/Transport/Sender/SendersLocator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index 2057293e5f6ed..e5c882d810579 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -51,7 +51,7 @@ public function getSenders(Envelope $envelope): iterable $typeSenderAliases[] = $senderAlias; } - if (empty($typeSenderAliases)) { + if (!$typeSenderAliases) { $typeSenderAliases = $this->getSendersFromAttributes($type); } From 9068719812b10caa41ea410b8332d5e859866569 Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Fri, 18 Mar 2022 11:25:49 -0400 Subject: [PATCH 14/14] allow subclasses of `Transport` --- .../Tests/Fixtures/DummyMessageWithAttribute.php | 11 ++++++++++- .../Messenger/Transport/Sender/SendersLocator.php | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php index 9d120890a0dd1..03e93928957c8 100644 --- a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php @@ -5,7 +5,7 @@ use Symfony\Component\Messenger\Attribute\Transport; #[Transport('message_attribute_sender')] -#[Transport('message_attribute_sender_2')] +#[CustomTransport] class DummyMessageWithAttribute implements DummyMessageInterface { private $message; @@ -20,3 +20,12 @@ public function getMessage(): string return $this->message; } } + +#[\Attribute(\Attribute::TARGET_CLASS)] +class CustomTransport extends Transport +{ + public function __construct() + { + parent::__construct('message_attribute_sender_2'); + } +} diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index e5c882d810579..58b9be48a03c0 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -85,7 +85,7 @@ private function getSendersFromAttributes(string $type): array return []; } - $attributes = $reflectionClass->getAttributes(Transport::class); + $attributes = $reflectionClass->getAttributes(Transport::class, \ReflectionAttribute::IS_INSTANCEOF); return array_map(function (\ReflectionAttribute $attribute): string { /** @var Transport $attributeInstance */