From 88262a5d8bddfba707ba417f34a7bc2a9add168d Mon Sep 17 00:00:00 2001 From: Ener-Getick Date: Mon, 5 Oct 2015 18:42:18 +0200 Subject: [PATCH] Add parameters validation support --- Controller/ApiController.php | 10 ++- DependencyInjection/Configuration.php | 11 ++++ DependencyInjection/EXSystApiExtension.php | 10 +++ EventListener/ParameterValidationListener.php | 65 +++++++++++++++++++ Resources/config/parameter_validation.yml | 14 ++++ .../ParameterValidationController.php | 32 +++++++++ .../TestBundle/Resources/config/routing.yml | 4 ++ Tests/Functional/ParameterValidationTest.php | 47 ++++++++++++++ .../app/ParameterValidation/bundles.php | 16 +++++ .../app/ParameterValidation/config.yml | 12 ++++ 10 files changed, 218 insertions(+), 3 deletions(-) create mode 100644 EventListener/ParameterValidationListener.php create mode 100644 Resources/config/parameter_validation.yml create mode 100644 Tests/Functional/Bundle/TestBundle/Controller/ParameterValidationController.php create mode 100644 Tests/Functional/ParameterValidationTest.php create mode 100644 Tests/Functional/app/ParameterValidation/bundles.php create mode 100644 Tests/Functional/app/ParameterValidation/config.yml diff --git a/Controller/ApiController.php b/Controller/ApiController.php index 165ba1d..4883cdc 100644 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -26,7 +26,7 @@ abstract class ApiController extends Controller * * @return string */ - protected function serializeView($value, $context, $format = null) + protected function serializeView($value, $context = null, $format = null) { if ($format === null) { $format = $this->getParameter('exsyst_api.serializer.default_format'); @@ -34,7 +34,11 @@ protected function serializeView($value, $context, $format = null) $serializer = $this->get('exsyst_api.serializer'); - return $serializer->serialize($value, $format, $context); + if ($context === null) { + return $serializer->serialize($value, $format); + } else { + return $serializer->serialize($value, $format, $context); + } } /** @@ -44,7 +48,7 @@ protected function serializeView($value, $context, $format = null) * * @return Response */ - protected function serialize($value, $context, $format = null, Response $response = null) + protected function serialize($value, $context = null, $format = null, Response $response = null) { $request = $this->get('request_stack')->getCurrentRequest(); if ($format === null) { diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 7a6a748..fd0ba37 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -64,6 +64,17 @@ public function getConfigTreeBuilder() ->end() ->end() ->end() + ->arrayNode('parameter') + ->addDefaultsIfNotSet() + ->children() + ->arrayNode('validation') + ->canBeEnabled() + ->children() + ->scalarNode('attributeName')->defaultValue('validationErrors')->end() + ->end() + ->end() + ->end() + ->end() ->end(); return $treeBuilder; diff --git a/DependencyInjection/EXSystApiExtension.php b/DependencyInjection/EXSystApiExtension.php index 280bea1..52aec07 100644 --- a/DependencyInjection/EXSystApiExtension.php +++ b/DependencyInjection/EXSystApiExtension.php @@ -40,6 +40,7 @@ public function load(array $configs, ContainerBuilder $container) $this->loadSerialization($config, $loader, $container); $this->loadRouting($config, $loader, $container); $this->loadVersioning($config, $loader, $container); + $this->loadParameterValidation($config, $loader, $container); } private function loadSerialization(array $config, YamlFileLoader $loader, ContainerBuilder $container) @@ -95,6 +96,15 @@ private function loadVersioning(array $config, YamlFileLoader $loader, Container } } + private function loadParameterValidation(array $config, YamlFileLoader $loader, ContainerBuilder $container) + { + if ($config['parameter']['validation']['enabled']) { + $loader->load('parameter_validation.yml'); + + $container->getDefinition('exsyst_api.parameter.validation_listener')->replaceArgument(2, $config['parameter']['validation']['attributeName']); + } + } + public function getAlias() { return 'exsyst_api'; diff --git a/EventListener/ParameterValidationListener.php b/EventListener/ParameterValidationListener.php new file mode 100644 index 0000000..a4e8f59 --- /dev/null +++ b/EventListener/ParameterValidationListener.php @@ -0,0 +1,65 @@ + + */ +class ParameterValidationListener +{ + /** + * @var ParameterReader + */ + private $parameterReader; + /** + * @var ParameterValidator + */ + private $parameterValidator; + + /** + * Constructor. + * + * @param ParameterReader $parameterReader + * @param ParameterValidator $parameterValidator + * @param string $attributeName + */ + public function __construct(ParameterReader $parameterReader, ParameterValidator $parameterValidator, $attributeName) + { + $this->parameterReader = $parameterReader; + $this->parameterValidator = $parameterValidator; + $this->attributeName = $attributeName; + } + + /** + * @param FilterControllerEvent $event + */ + public function onKernelController(FilterControllerEvent $event) + { + $request = $event->getRequest(); + + $controller = $event->getController(); + if (is_callable($controller) && method_exists($controller, '__invoke')) { + $controller = [$controller, '__invoke']; + } + + $parameters = $this->parameterReader->read( + new \ReflectionMethod($controller[0], $controller[1]) + ); + $errors = $this->parameterValidator->validateParameters($parameters); + + $request->attributes->set($this->attributeName, $errors); + } +} diff --git a/Resources/config/parameter_validation.yml b/Resources/config/parameter_validation.yml new file mode 100644 index 0000000..c05f181 --- /dev/null +++ b/Resources/config/parameter_validation.yml @@ -0,0 +1,14 @@ +services: + exsyst_api.parameter.reader: + class: EXSyst\Component\Api\Parameter\ParameterReader + arguments: [ @annotation_reader ] + + exsyst_api.parameter.validator: + class: EXSyst\Component\Api\Parameter\ParameterValidator + arguments: [ @request_stack, @validator ] + + exsyst_api.parameter.validation_listener: + class: EXSyst\Bundle\ApiBundle\EventListener\ParameterValidationListener + arguments: [ @exsyst_api.parameter.reader, @exsyst_api.parameter.validator, ~ ] + tags: + - { name: kernel.event_listener, event: kernel.controller, method: onKernelController, priority: 5 } diff --git a/Tests/Functional/Bundle/TestBundle/Controller/ParameterValidationController.php b/Tests/Functional/Bundle/TestBundle/Controller/ParameterValidationController.php new file mode 100644 index 0000000..47945a5 --- /dev/null +++ b/Tests/Functional/Bundle/TestBundle/Controller/ParameterValidationController.php @@ -0,0 +1,32 @@ +serialize($errors); + } +} diff --git a/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml b/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml index bfb169d..4240e72 100644 --- a/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml +++ b/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml @@ -21,3 +21,7 @@ version_uri: version_other: path: /version defaults: { _controller: TestBundle:Version:version } + +parameter_validation: + path: /parameter-validation + defaults: { _controller: TestBundle:ParameterValidation:validate } diff --git a/Tests/Functional/ParameterValidationTest.php b/Tests/Functional/ParameterValidationTest.php new file mode 100644 index 0000000..4fe7c1d --- /dev/null +++ b/Tests/Functional/ParameterValidationTest.php @@ -0,0 +1,47 @@ + + */ +class ParameterValidationTest extends WebTestCase +{ + public function setUp() + { + $this->client = $this->createClient(['test_case' => 'ParameterValidation', 'root_config' => 'config.yml']); + } + + public function testDefaultValidation() + { + $this->client->request('GET', '/parameter-validation'); + $response = $this->client->getResponse(); + $this->assertEquals( + '{"foo":"","bar":"bar:\n Parameter \"bar\" must be defined.\n"}', + $response->getContent() + ); + } + + public function testValidParameters() + { + $this->client->request( + 'POST', + '/parameter-validation?bar=null', + ['foo' => 'bar@example.com'] + ); + $response = $this->client->getResponse(); + $this->assertEquals( + '{"foo":"","bar":""}', + $response->getContent() + ); + } +} diff --git a/Tests/Functional/app/ParameterValidation/bundles.php b/Tests/Functional/app/ParameterValidation/bundles.php new file mode 100644 index 0000000..7cd33e6 --- /dev/null +++ b/Tests/Functional/app/ParameterValidation/bundles.php @@ -0,0 +1,16 @@ +