diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 146be090225d5..154ae76def0bc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -1005,10 +1005,14 @@ function ($a) { ->arrayNode('middlewares') ->addDefaultsIfNotSet() ->children() - ->arrayNode('doctrine_transaction') - ->canBeEnabled() - ->children() - ->scalarNode('entity_manager_name')->info('The name of the entity manager to use')->defaultNull()->end() + ->arrayNode('doctrine_transaction') + ->canBeEnabled() + ->children() + ->scalarNode('entity_manager_name')->info('The name of the entity manager to use')->defaultNull()->end() + ->end() + ->end() + ->arrayNode('validation') + ->{!class_exists(FullStack::class) && class_exists(Validation::class) ? 'canBeDisabled' : 'canBeEnabled'}() ->end() ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index ff7dbeaa5d60b..248ad11eaa890 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1459,6 +1459,14 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder } else { $container->removeDefinition('messenger.middleware.doctrine_transaction'); } + + if ($config['middlewares']['validation']['enabled']) { + if (!$container->has('validator')) { + throw new LogicException('The Validation middleware is only available when the Validator component is installed and enabled. Try running "composer require symfony/validator".'); + } + } else { + $container->removeDefinition('messenger.middleware.validator'); + } } private function registerCacheConfiguration(array $config, ContainerBuilder $container) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml index cbba149b2fb1f..580e2b8f4ae2b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml @@ -25,6 +25,12 @@ + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index ab205bd267256..fdf9ec5b0702c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -371,6 +371,7 @@ + @@ -378,4 +379,8 @@ + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 6fc0ebd1cf8c2..1d96df88a631b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -258,6 +258,9 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor 'enabled' => false, 'entity_manager_name' => null, ), + 'validation' => array( + 'enabled' => false, + ), ), ), ); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_validation.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_validation.php new file mode 100644 index 0000000000000..9776e0b5b2abc --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_validation.php @@ -0,0 +1,11 @@ +loadFromExtension('framework', array( + 'messenger' => array( + 'middlewares' => array( + 'validation' => array( + 'enabled' => false, + ), + ), + ), +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_validation.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_validation.xml new file mode 100644 index 0000000000000..66c104d385965 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_validation.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_validation.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_validation.yml new file mode 100644 index 0000000000000..276182d2bb3c8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_validation.yml @@ -0,0 +1,5 @@ +framework: + messenger: + middlewares: + validation: + enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 2176afdbcf6f7..2ba8907135b0a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -45,6 +45,7 @@ use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; use Symfony\Component\Translation\DependencyInjection\TranslatorPass; use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; +use Symfony\Component\Validator\Validation; use Symfony\Component\Workflow; abstract class FrameworkExtensionTest extends TestCase @@ -532,6 +533,16 @@ public function testMessengerDoctrine() $this->assertEquals('foobar', $def->getArgument(1)); } + public function testMessengerValidationDisabled() + { + if (!class_exists(Validation::class)) { + self::markTestSkipped('Skipping tests since Validator component is not installed'); + } + + $container = $this->createContainerFromFile('messenger_validation'); + $this->assertFalse($container->hasDefinition('messenger.middleware.validator')); + } + public function testTranslator() { $container = $this->createContainerFromFile('full'); diff --git a/src/Symfony/Component/Messenger/Exception/ValidationFailedException.php b/src/Symfony/Component/Messenger/Exception/ValidationFailedException.php new file mode 100644 index 0000000000000..0e06ceaa05ac1 --- /dev/null +++ b/src/Symfony/Component/Messenger/Exception/ValidationFailedException.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Exception; + +use Symfony\Component\Validator\ConstraintViolationListInterface; + +/** + * @author Tobias Nyholm + */ +class ValidationFailedException extends \RuntimeException implements ExceptionInterface +{ + private $violations; + private $violatingMessage; + + /** + * @param object $violatingMessage + */ + public function __construct($violatingMessage, ConstraintViolationListInterface $violations) + { + $this->violatingMessage = $violatingMessage; + $this->violations = $violations; + + parent::__construct(sprintf('Message of type "%s" failed validation.', get_class($this->violatingMessage))); + } + + public function getViolatingMessage() + { + return $this->violatingMessage; + } + + public function getViolations(): ConstraintViolationListInterface + { + return $this->violations; + } +} diff --git a/src/Symfony/Component/Messenger/Middleware/ValidationMiddleware.php b/src/Symfony/Component/Messenger/Middleware/ValidationMiddleware.php new file mode 100644 index 0000000000000..38264a17571ee --- /dev/null +++ b/src/Symfony/Component/Messenger/Middleware/ValidationMiddleware.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\Middleware; + +use Symfony\Component\Messenger\Exception\ValidationFailedException; +use Symfony\Component\Messenger\MiddlewareInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; + +/** + * @author Tobias Nyholm + */ +class ValidationMiddleware implements MiddlewareInterface +{ + private $validator; + + public function __construct(ValidatorInterface $validator) + { + $this->validator = $validator; + } + + public function handle($message, callable $next) + { + $violations = $this->validator->validate($message); + if (count($violations)) { + throw new ValidationFailedException($message, $violations); + } + + return $next($message); + } +}