diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 772c8fe1ffeb7..aac1d4a9fd42a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -1466,9 +1466,75 @@ function ($a) { }) ->end() ->fixXmlConfig('option') + ->validate() + ->ifTrue(static fn (array $transportConf) => \count(array_intersect(['serializer', 'incoming_message_serializer', 'outgoing_message_serializer'], array_keys($transportConf))) > 1) + ->thenInvalid('Only one of "serializer", "incoming_message_serializer" and "outgoing_message_serializer" could be used.') + ->end() ->children() ->scalarNode('dsn')->end() - ->scalarNode('serializer')->defaultNull()->info('Service id of a custom serializer to use.')->end() + ->arrayNode('serializer') + ->info('Transport serializer configuration for messages produced and handled by this application.') + ->beforeNormalization() + ->ifString() + ->then(static fn (string $serviceId) => ['service_id' => $serviceId]) + ->end() + ->children() + ->scalarNode('service_id')->info('Service id of a custom transport serializer to use (incompatible with "format", "context" and "serializer" options).')->defaultNull()->end() + ->scalarNode('format')->info('Serialization format for this transport\'s serializer (will use Symfony serializer).')->end() + ->arrayNode('context') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->defaultValue([]) + ->info('Context serialization array for this transport\'s serializer (will use Symfony serializer).') + ->prototype('variable')->end() + ->end() + ->scalarNode('serializer')->info('Service id of a custom Symfony serializer to use.')->end() + ->end() + ->validate() + ->ifTrue(static fn (array $serializerConf) => !(isset($serializerConf['service_id']) xor (isset($serializerConf['format']) || [] !== $serializerConf['context'] || isset($serializerConf['serializer'])))) + ->thenInvalid('Either "service_id" OR at least one of "format" or "context" or "serializer" should be provided.') + ->end() + ->end() + ->arrayNode('incoming_message_serializer') + ->info('Transport serializer configuration for messages coming from other applications (uses Symfony serializer).') + ->children() + ->scalarNode('messageClass') + ->info('The class in which the message should be deserialized (incompatible with "messageClassResolver" option).') + ->validate() + ->ifTrue(static fn ($class) => $class && !class_exists($class)) + ->thenInvalid('The "messageClass" should be a valid class.') + ->end() + ->end() + ->scalarNode('messageClassResolver')->info('Service id of a message class resolver to use (incompatible with "messageClass" option).')->end() + ->scalarNode('format')->info('Serialization format for this transport\'s serializer.')->end() + ->arrayNode('context') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->defaultValue([]) + ->info('Context serialization array for this transport\'s serializer.') + ->prototype('variable')->end() + ->end() + ->scalarNode('serializer')->info('Service id of a custom Symfony serializer to use.')->end() + ->end() + ->validate() + ->ifTrue(static fn (array $incomingMessageConf) => !(isset($incomingMessageConf['messageClass']) xor isset($incomingMessageConf['messageClassResolver']))) + ->thenInvalid('A message class OR a message class resolver should be provided.') + ->end() + ->end() + ->arrayNode('outgoing_message_serializer') + ->info('Transport serializer configuration for sending messages to other applications (uses Symfony serializer).') + ->children() + ->scalarNode('format')->info('Serialization format for this transport\'s serializer.')->end() + ->arrayNode('context') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->defaultValue([]) + ->info('Context serialization array for this transport\'s serializer.') + ->prototype('variable')->end() + ->end() + ->scalarNode('serializer')->info('Service id of a custom Symfony serializer to use.')->end() + ->end() + ->end() ->arrayNode('options') ->normalizeKeys(false) ->defaultValue([]) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 358ec36f10bea..01a59bf609f88 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -120,6 +120,9 @@ use Symfony\Component\Messenger\MessageBus; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Middleware\RouterContextMiddleware; +use Symfony\Component\Messenger\Transport\Serialization\IncomingMessageSerializer; +use Symfony\Component\Messenger\Transport\Serialization\OutgoingMessageSerializer; +use Symfony\Component\Messenger\Transport\Serialization\Serializer; use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface; use Symfony\Component\Messenger\Transport\TransportFactoryInterface; use Symfony\Component\Messenger\Transport\TransportInterface; @@ -2086,7 +2089,47 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder $transportRetryReferences = []; $transportRateLimiterReferences = []; foreach ($config['transports'] as $name => $transport) { - $serializerId = $transport['serializer'] ?? 'messenger.default_serializer'; + if (isset($transport['serializer'])) { + $basicSerializerConf = $transport['serializer']; + + $serializerId = $basicSerializerConf['service_id'] ?? "messenger.transport.{$name}.serializer"; + + if (($basicSerializerConf['serializer'] ?? null) || ($basicSerializerConf['format'] ?? null) || [] !== $basicSerializerConf['context']) { + $serializerDefinition = (new Definition(Serializer::class)) + ->setArguments([ + new Reference($basicSerializerConf['serializer'] ?? 'serializer'), + $basicSerializerConf['format'] ?? $config['serializer']['symfony_serializer']['format'], + $basicSerializerConf['context'] ?: $config['serializer']['symfony_serializer']['context'], + ]); + + $container->setDefinition($serializerId, $serializerDefinition); + } + } elseif (isset($transport['incoming_message_serializer'])) { + $incomingSerializerConf = $transport['incoming_message_serializer']; + + $serializerDefinition = (new Definition(IncomingMessageSerializer::class)) + ->setArguments([ + $incomingSerializerConf['messageClass'] ?? new Reference($incomingSerializerConf['messageClassResolver']), + new Reference($incomingSerializerConf['serializer'] ?? 'serializer'), + $incomingSerializerConf['format'] ?? $config['serializer']['symfony_serializer']['format'], + $incomingSerializerConf['context'] ?: $config['serializer']['symfony_serializer']['context'], + ]); + + $container->setDefinition($serializerId = "messenger.transport.{$name}.serializer", $serializerDefinition); + } elseif (isset($transport['outgoing_message_serializer'])) { + $outgoingSerializerConf = $transport['outgoing_message_serializer']; + + $serializerDefinition = (new Definition(OutgoingMessageSerializer::class)) + ->setArguments([ + new Reference($outgoingSerializerConf['serializer'] ?? 'serializer'), + $outgoingSerializerConf['format'] ?? $config['serializer']['symfony_serializer']['format'], + $outgoingSerializerConf['context'] ?: $config['serializer']['symfony_serializer']['context'], + ]); + + $container->setDefinition($serializerId = "messenger.transport.{$name}.serializer", $serializerDefinition); + } + + $serializerId ??= 'messenger.default_serializer'; $transportDefinition = (new Definition(TransportInterface::class)) ->setFactory([new Reference('messenger.transport_factory'), 'createTransport']) ->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)]) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer.php new file mode 100644 index 0000000000000..22fd14d394216 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer.php @@ -0,0 +1,64 @@ +loadFromExtension('framework', [ + 'http_method_override' => false, + 'serializer' => true, + 'messenger' => [ + 'serializer' => [ + 'symfony_serializer' => [ + 'format' => 'xml', + 'context' => ['default' => 'context'], + ] + ], + 'transports' => [ + 'default_serializer' => ['dsn' => 'null://'], + 'custom_serializer_short_notation' => [ + 'dsn' => 'null://', + 'serializer' => 'messenger.transport.native_php_serializer', + ], + 'custom_serializer_long_notation' => [ + 'dsn' => 'null://', + 'serializer' => [ + 'service_id' => 'messenger.transport.native_php_serializer', + ], + ], + 'symfony_serializer_with_context' => [ + 'dsn' => 'null://', + 'serializer' => [ + 'format' => 'json', + 'context' => ['some' => 'context'], + 'serializer' => 'my_fancy_serializer', + ], + ], + 'incoming_message_transport' => [ + 'dsn' => 'null://', + 'incoming_message_serializer' => [ + 'messageClass' => BarMessage::class, + 'format' => 'json', + 'context' => ['some' => 'context'], + 'serializer' => 'my_fancy_serializer', + ], + ], + 'incoming_message_transport_with_default_serializer' => [ + 'dsn' => 'null://', + 'incoming_message_serializer' => [ + 'messageClassResolver' => 'some_message_class_resolver_id', + ], + ], + 'outgoing_message_transport' => [ + 'dsn' => 'null://', + 'outgoing_message_serializer' => [ + 'format' => 'json', + 'context' => ['some' => 'context'], + 'serializer' => 'my_fancy_serializer', + ], + ], + 'outgoing_message_transport_with_default_serializer' => [ + 'dsn' => 'null://', + 'outgoing_message_serializer' => [], + ], + ], + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_1.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_1.php new file mode 100644 index 0000000000000..869db0f98f26b --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_1.php @@ -0,0 +1,15 @@ +loadFromExtension('framework', [ + 'http_method_override' => false, + 'serializer' => true, + 'messenger' => [ + 'transports' => [ + 'invalid_transport' => [ + 'dsn' => 'null://', + 'serializer' => 'messenger.transport.native_php_serializer', + 'outgoing_message_serializer' => [] + ] + ], + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_2.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_2.php new file mode 100644 index 0000000000000..b51b50a351c8a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_2.php @@ -0,0 +1,17 @@ +loadFromExtension('framework', [ + 'http_method_override' => false, + 'serializer' => true, + 'messenger' => [ + 'transports' => [ + 'invalid_transport' => [ + 'dsn' => 'null://', + 'serializer' => [ + 'service_id' => 'messenger.transport.native_php_serializer', + 'format' => 'json' + ], + ] + ], + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_3.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_3.php new file mode 100644 index 0000000000000..b4a6a7e16de02 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_3.php @@ -0,0 +1,14 @@ +loadFromExtension('framework', [ + 'http_method_override' => false, + 'serializer' => true, + 'messenger' => [ + 'transports' => [ + 'invalid_transport' => [ + 'dsn' => 'null://', + 'serializer' => [], + ] + ], + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_4.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_4.php new file mode 100644 index 0000000000000..96e5e4d07f531 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_4.php @@ -0,0 +1,19 @@ +loadFromExtension('framework', [ + 'http_method_override' => false, + 'serializer' => true, + 'messenger' => [ + 'transports' => [ + 'invalid_transport' => [ + 'dsn' => 'null://', + 'incoming_message_serializer' => [ + 'messageClass' => BarMessage::class, + 'messageClassResolver' => 'foo', + ], + ] + ], + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_5.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_5.php new file mode 100644 index 0000000000000..f46fc375be338 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport_serializer_invalid_5.php @@ -0,0 +1,16 @@ +loadFromExtension('framework', [ + 'http_method_override' => false, + 'serializer' => true, + 'messenger' => [ + 'transports' => [ + 'invalid_transport' => [ + 'dsn' => 'null://', + 'incoming_message_serializer' => [ + 'messageClass' => 'foo', + ], + ] + ], + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer.xml new file mode 100644 index 0000000000000..cf583ec809485 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + context + + + + + + + + + + + + + + + + context + + + + + + + + context + + + + + + + + + + + + context + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_1.xml new file mode 100644 index 0000000000000..dfd04dc43fef7 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_1.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_2.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_2.xml new file mode 100644 index 0000000000000..f758f30b1a88c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_2.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_3.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_3.xml new file mode 100644 index 0000000000000..4e66c3487f03c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_3.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_4.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_4.xml new file mode 100644 index 0000000000000..def75bbcd251b --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_4.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_5.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_5.xml new file mode 100644 index 0000000000000..0975b13b3bfa7 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport_serializer_invalid_5.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer.yml new file mode 100644 index 0000000000000..eda1c7f12c4ec --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer.yml @@ -0,0 +1,44 @@ +framework: + http_method_override: false + serializer: true + messenger: + serializer: + symfony_serializer: + format: xml + context: {default: context} + transports: + default_serializer: + dsn: 'null://' + custom_serializer_short_notation: + dsn: 'null://' + serializer: 'messenger.transport.native_php_serializer' + custom_serializer_long_notation: + dsn: 'null://' + serializer: + service_id: 'messenger.transport.native_php_serializer' + symfony_serializer_with_context: + dsn: 'null://' + serializer: + format: 'json' + context: {some: context} + serializer: 'my_fancy_serializer' + incoming_message_transport: + dsn: 'null://' + incoming_message_serializer: + messageClass: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\BarMessage + format: 'json' + context: {some: context} + serializer: 'my_fancy_serializer' + incoming_message_transport_with_default_serializer: + dsn: 'null://' + incoming_message_serializer: + messageClassResolver: 'some_message_class_resolver_id' + outgoing_message_transport: + dsn: 'null://' + outgoing_message_serializer: + format: 'json' + context: {some: context} + serializer: 'my_fancy_serializer' + outgoing_message_transport_with_default_serializer: + dsn: 'null://' + outgoing_message_serializer: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_1.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_1.yml new file mode 100644 index 0000000000000..1d88974672b6f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_1.yml @@ -0,0 +1,9 @@ +framework: + http_method_override: false + serializer: true + messenger: + transports: + invalid_transport: + dsn: 'null://' + serializer: 'messenger.transport.native_php_serializer' + outgoing_message_serializer: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_2.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_2.yml new file mode 100644 index 0000000000000..2086945145672 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_2.yml @@ -0,0 +1,10 @@ +framework: + http_method_override: false + serializer: true + messenger: + transports: + invalid_transport: + dsn: 'null://' + serializer: + service_id: 'messenger.transport.native_php_serializer' + format: json diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_3.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_3.yml new file mode 100644 index 0000000000000..1c42ed1e16704 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_3.yml @@ -0,0 +1,8 @@ +framework: + http_method_override: false + serializer: true + messenger: + transports: + invalid_transport: + dsn: 'null://' + serializer: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_4.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_4.yml new file mode 100644 index 0000000000000..5096657148ff8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_4.yml @@ -0,0 +1,10 @@ +framework: + http_method_override: false + serializer: true + messenger: + transports: + invalid_transport: + dsn: 'null://' + incoming_message_serializer: + messageClass: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\BarMessage + messageClassResolver: foo diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_5.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_5.yml new file mode 100644 index 0000000000000..44363a712bfde --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport_serializer_invalid_5.yml @@ -0,0 +1,9 @@ +framework: + http_method_override: false + serializer: true + messenger: + transports: + invalid_transport: + dsn: 'null://' + incoming_message_serializer: + messageClass: foo diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index e3416357c162b..d224ab7f18bc2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -18,6 +18,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\BarMessage; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Bundle\FullStack; @@ -57,6 +58,9 @@ use Symfony\Component\HttpClient\ScopingHttpClient; use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface; +use Symfony\Component\Messenger\Transport\Serialization\IncomingMessageSerializer; +use Symfony\Component\Messenger\Transport\Serialization\OutgoingMessageSerializer; +use Symfony\Component\Messenger\Transport\Serialization\Serializer as MessengerTransportSerializer; use Symfony\Component\Messenger\Transport\TransportFactory; use Symfony\Component\Notifier\ChatterInterface; use Symfony\Component\Notifier\TexterInterface; @@ -1083,6 +1087,107 @@ public function testMessengerWithDisabledResetOnMessage() $this->createContainerFromFile('messenger_with_disabled_reset_on_message'); } + public function testMessengerTransportSerializerConfigurations() + { + $container = $this->createContainerFromFile('messenger_transport_serializer'); + + $transportDefinition = $container->getDefinition('messenger.transport.default_serializer'); + $this->assertEquals(new Reference('messenger.default_serializer'), $transportDefinition->getArguments()[2]); + + $transportDefinition = $container->getDefinition('messenger.transport.custom_serializer_short_notation'); + $this->assertEquals(new Reference('messenger.transport.native_php_serializer'), $transportDefinition->getArguments()[2]); + + $transportDefinition = $container->getDefinition('messenger.transport.custom_serializer_long_notation'); + $this->assertEquals(new Reference('messenger.transport.native_php_serializer'), $transportDefinition->getArguments()[2]); + + $transportDefinition = $container->getDefinition('messenger.transport.symfony_serializer_with_context'); + $this->assertEquals(new Reference($serializerId = 'messenger.transport.symfony_serializer_with_context.serializer'), $transportDefinition->getArguments()[2]); + $serializerDefinition = $container->getDefinition($serializerId); + self::assertSame(MessengerTransportSerializer::class, $serializerDefinition->getClass()); + self::assertEquals( + [ + new Reference('my_fancy_serializer'), + 'json', + ['some' => 'context'], + ], + $serializerDefinition->getArguments() + ); + + $transportDefinition = $container->getDefinition('messenger.transport.incoming_message_transport'); + $this->assertEquals(new Reference($serializerId = 'messenger.transport.incoming_message_transport.serializer'), $transportDefinition->getArguments()[2]); + $serializerDefinition = $container->getDefinition($serializerId); + self::assertSame(IncomingMessageSerializer::class, $serializerDefinition->getClass()); + self::assertEquals( + [ + BarMessage::class, + new Reference('my_fancy_serializer'), + 'json', + ['some' => 'context'], + ], + $serializerDefinition->getArguments() + ); + + $transportDefinition = $container->getDefinition('messenger.transport.incoming_message_transport_with_default_serializer'); + $this->assertEquals(new Reference($serializerId = 'messenger.transport.incoming_message_transport_with_default_serializer.serializer'), $transportDefinition->getArguments()[2]); + $serializerDefinition = $container->getDefinition($serializerId); + self::assertSame(IncomingMessageSerializer::class, $serializerDefinition->getClass()); + self::assertEquals( + [ + new Reference('some_message_class_resolver_id'), + new Reference('serializer'), + 'xml', + ['default' => 'context'], + ], + $serializerDefinition->getArguments() + ); + + $transportDefinition = $container->getDefinition('messenger.transport.outgoing_message_transport'); + $this->assertEquals(new Reference($serializerId = 'messenger.transport.outgoing_message_transport.serializer'), $transportDefinition->getArguments()[2]); + $serializerDefinition = $container->getDefinition($serializerId); + self::assertSame(OutgoingMessageSerializer::class, $serializerDefinition->getClass()); + self::assertEquals( + [ + new Reference('my_fancy_serializer'), + 'json', + ['some' => 'context'], + ], + $serializerDefinition->getArguments() + ); + + $transportDefinition = $container->getDefinition('messenger.transport.outgoing_message_transport_with_default_serializer'); + $this->assertEquals(new Reference($serializerId = 'messenger.transport.outgoing_message_transport_with_default_serializer.serializer'), $transportDefinition->getArguments()[2]); + $serializerDefinition = $container->getDefinition($serializerId); + self::assertSame(OutgoingMessageSerializer::class, $serializerDefinition->getClass()); + self::assertEquals( + [ + new Reference('serializer'), + 'xml', + ['default' => 'context'], + ], + $serializerDefinition->getArguments() + ); + } + + /** + * @dataProvider invalidMessengerTransportSerializerConfigurationsProvider + */ + public function testInvalidMessengerTransportSerializerConfigurations(string $configFile, string $errorMessage) + { + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage($errorMessage); + + $this->createContainerFromFile($configFile); + } + + public function invalidMessengerTransportSerializerConfigurationsProvider(): iterable + { + yield ['messenger_transport_serializer_invalid_1', 'Only one of "serializer", "incoming_message_serializer" and "outgoing_message_serializer" could be used']; + yield ['messenger_transport_serializer_invalid_2', 'Either "service_id" OR at least one of "format" or "context" or "serializer" should be provided.']; + yield ['messenger_transport_serializer_invalid_3', 'Either "service_id" OR at least one of "format" or "context" or "serializer" should be provided.']; + yield ['messenger_transport_serializer_invalid_4', 'A message class OR a message class resolver should be provided.']; + yield ['messenger_transport_serializer_invalid_5', 'The "messageClass" should be a valid class.']; + } + public function testTranslator() { $container = $this->createContainerFromFile('full'); diff --git a/src/Symfony/Component/Messenger/Transport/Serialization/IncomingMessageClassResolverInterface.php b/src/Symfony/Component/Messenger/Transport/Serialization/IncomingMessageClassResolverInterface.php new file mode 100644 index 0000000000000..7ef0db2d1ce0d --- /dev/null +++ b/src/Symfony/Component/Messenger/Transport/Serialization/IncomingMessageClassResolverInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Transport\Serialization; + +interface IncomingMessageClassResolverInterface +{ + /** + * @return class-string + */ + public function __invoke(array $encodedEnvelope): string; +} diff --git a/src/Symfony/Component/Messenger/Transport/Serialization/IncomingMessageSerializer.php b/src/Symfony/Component/Messenger/Transport/Serialization/IncomingMessageSerializer.php new file mode 100644 index 0000000000000..069c88559ea70 --- /dev/null +++ b/src/Symfony/Component/Messenger/Transport/Serialization/IncomingMessageSerializer.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Transport\Serialization; + +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Serializer\SerializerInterface as SymfonySerializerInterface; + +final class IncomingMessageSerializer implements SerializerInterface +{ + private Serializer $decorated; + + public function __construct(private readonly IncomingMessageClassResolverInterface|string $messageClass, SymfonySerializerInterface $serializer, string $format, array $context) + { + $this->decorated = new Serializer($serializer, $format, $context); + } + + public function decode(array $encodedEnvelope): Envelope + { + $encodedEnvelope['headers']['type'] ??= $this->resolveType($encodedEnvelope); + + return $this->decorated->decode($encodedEnvelope); + } + + public function encode(Envelope $envelope): array + { + return $this->decorated->encode($envelope); + } + + private function resolveType(array $encodedEnvelope): string + { + return \is_string($this->messageClass) ? $this->messageClass : ($this->messageClass)($encodedEnvelope); + } +} diff --git a/src/Symfony/Component/Messenger/Transport/Serialization/OutgoingMessageSerializer.php b/src/Symfony/Component/Messenger/Transport/Serialization/OutgoingMessageSerializer.php new file mode 100644 index 0000000000000..7b01e593a18bb --- /dev/null +++ b/src/Symfony/Component/Messenger/Transport/Serialization/OutgoingMessageSerializer.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Transport\Serialization; + +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Serializer\SerializerInterface as SymfonySerializerInterface; + +final class OutgoingMessageSerializer implements SerializerInterface +{ + private Serializer $decorated; + + public function __construct(SymfonySerializerInterface $serializer, string $format, array $context) + { + $this->decorated = new Serializer($serializer, $format, $context); + } + + public function decode(array $encodedEnvelope): Envelope + { + throw new \LogicException(sprintf('Cannot use "%s" to decode message.', __CLASS__)); + } + + public function encode(Envelope $envelope): array + { + $encode = $this->decorated->encode(Envelope::wrap($envelope->getMessage())); + + unset($encode['headers']['type']); + + return $encode; + } +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy