/Request/RequestBodyParamConverter.php
PHP | 155 lines | 112 code | 23 blank | 20 comment | 14 complexity | 6a7e573e9a1585ed6d7c46d37e260bc9 MD5 | raw file
- <?php
- /*
- * This file is part of the FOSRestBundle package.
- *
- * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace FOS\RestBundle\Request;
- use FOS\RestBundle\Context\Context;
- use FOS\RestBundle\Serializer\Serializer;
- use JMS\Serializer\Exception\Exception as JMSSerializerException;
- use JMS\Serializer\Exception\UnsupportedFormatException;
- use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
- use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
- use Symfony\Component\HttpFoundation\Request;
- use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
- use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
- use Symfony\Component\OptionsResolver\OptionsResolver;
- use Symfony\Component\Serializer\Exception\ExceptionInterface as SymfonySerializerException;
- use Symfony\Component\Validator\Validator\ValidatorInterface;
- /**
- * @author Tyler Stroud <tyler@tylerstroud.com>
- */
- final class RequestBodyParamConverter implements ParamConverterInterface
- {
- private $serializer;
- private $context = [];
- private $validator;
- private $validationErrorsArgument;
- /**
- * @param string[]|null $groups
- */
- public function __construct(
- Serializer $serializer,
- ?array $groups = null,
- ?string $version = null,
- ValidatorInterface $validator = null,
- ?string $validationErrorsArgument = null
- ) {
- $this->serializer = $serializer;
- if (!empty($groups)) {
- $this->context['groups'] = (array) $groups;
- }
- if (!empty($version)) {
- $this->context['version'] = $version;
- }
- if (null !== $validator && null === $validationErrorsArgument) {
- throw new \InvalidArgumentException('"$validationErrorsArgument" cannot be null when using the validator');
- }
- $this->validator = $validator;
- $this->validationErrorsArgument = $validationErrorsArgument;
- }
- /**
- * {@inheritdoc}
- */
- public function apply(Request $request, ParamConverter $configuration): bool
- {
- $options = (array) $configuration->getOptions();
- if (isset($options['deserializationContext']) && is_array($options['deserializationContext'])) {
- $arrayContext = array_merge($this->context, $options['deserializationContext']);
- } else {
- $arrayContext = $this->context;
- }
- $this->configureContext($context = new Context(), $arrayContext);
- try {
- $object = $this->serializer->deserialize(
- $request->getContent(),
- $configuration->getClass(),
- $request->getContentType(),
- $context
- );
- } catch (UnsupportedFormatException $e) {
- return $this->throwException(new UnsupportedMediaTypeHttpException($e->getMessage(), $e), $configuration);
- } catch (JMSSerializerException $e) {
- return $this->throwException(new BadRequestHttpException($e->getMessage(), $e), $configuration);
- } catch (SymfonySerializerException $e) {
- return $this->throwException(new BadRequestHttpException($e->getMessage(), $e), $configuration);
- }
- $request->attributes->set($configuration->getName(), $object);
- if (null !== $this->validator && (!isset($options['validate']) || $options['validate'])) {
- $validatorOptions = $this->getValidatorOptions($options);
- $errors = $this->validator->validate($object, null, $validatorOptions['groups']);
- $request->attributes->set(
- $this->validationErrorsArgument,
- $errors
- );
- }
- return true;
- }
- /**
- * {@inheritdoc}
- */
- public function supports(ParamConverter $configuration): bool
- {
- return null !== $configuration->getClass() && 'fos_rest.request_body' === $configuration->getConverter();
- }
- private function configureContext(Context $context, array $options): void
- {
- foreach ($options as $key => $value) {
- if ('groups' === $key) {
- $context->addGroups($options['groups']);
- } elseif ('version' === $key) {
- $context->setVersion($options['version']);
- } elseif ('enableMaxDepth' === $key) {
- $context->enableMaxDepth($options['enableMaxDepth']);
- } elseif ('serializeNull' === $key) {
- $context->setSerializeNull($options['serializeNull']);
- } else {
- $context->setAttribute($key, $value);
- }
- }
- }
- private function throwException(\Exception $exception, ParamConverter $configuration): bool
- {
- if ($configuration->isOptional()) {
- return false;
- }
- throw $exception;
- }
- private function getValidatorOptions(array $options): array
- {
- $resolver = new OptionsResolver();
- $resolver->setDefaults([
- 'groups' => null,
- 'traverse' => false,
- 'deep' => false,
- ]);
- return $resolver->resolve(isset($options['validator']) ? $options['validator'] : []);
- }
- }