Skip to content

Commit f7892fa

Browse files
committed
Merge pull request #633 from xabbuh/issue-622
configure RequestBodyParamConverter implementation based on the SensioFr...
2 parents d469bff + ccf3140 commit f7892fa

8 files changed

+671
-235
lines changed

DependencyInjection/FOSRestExtension.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,24 @@ public function load(array $configs, ContainerBuilder $container)
199199

200200
if (!empty($config['body_converter'])) {
201201
if (!empty($config['body_converter']['enabled'])) {
202+
$parameter = new \ReflectionParameter(
203+
array(
204+
'Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface',
205+
'supports',
206+
),
207+
'configuration'
208+
);
209+
if ('Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter' == $parameter->getClass()->getName()) {
210+
$container->setParameter(
211+
'fos_rest.converter.request_body.class',
212+
'FOS\RestBundle\Request\RequestBodyParamConverter'
213+
);
214+
} else {
215+
$container->setParameter(
216+
'fos_rest.converter.request_body.class',
217+
'FOS\RestBundle\Request\RequestBodyParamConverter20'
218+
);
219+
}
202220
$loader->load('request_body_param_converter.xml');
203221
}
204222
if (!empty($config['body_converter']['validate'])) {
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the FOSRestBundle package.
5+
*
6+
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace FOS\RestBundle\Request;
13+
14+
use Symfony\Component\HttpFoundation\Request;
15+
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
16+
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
17+
use Symfony\Component\OptionsResolver\OptionsResolver;
18+
use Symfony\Component\Serializer\Exception\Exception as SymfonySerializerException;
19+
use Symfony\Component\Validator\ValidatorInterface;
20+
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
21+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
22+
use JMS\Serializer\Exception\UnsupportedFormatException;
23+
use JMS\Serializer\Exception\Exception as JMSSerializerException;
24+
use JMS\Serializer\DeserializationContext;
25+
use JMS\Serializer\SerializerInterface;
26+
27+
/**
28+
* @author Tyler Stroud <[email protected]>
29+
*/
30+
abstract class AbstractRequestBodyParamConverter implements ParamConverterInterface
31+
{
32+
/**
33+
* @var object
34+
*/
35+
protected $serializer;
36+
37+
/**
38+
* @var array
39+
*/
40+
protected $context = array();
41+
42+
/**
43+
* @var null|ValidatorInterface
44+
*/
45+
protected $validator;
46+
47+
/**
48+
* @var null|string The name of the argument on which the ConstraintViolationList will be set
49+
*/
50+
protected $validationErrorsArgument;
51+
52+
/**
53+
* @param object $serializer
54+
* @param array|null $groups An array of groups to be used in the serialization context
55+
* @param string|null $version A version string to be used in the serialization context
56+
* @param object $serializer
57+
* @param ValidatorInterface $validator
58+
* @param string|null $validationErrorsArgument
59+
*
60+
* @throws \InvalidArgumentException
61+
*/
62+
public function __construct(
63+
$serializer,
64+
$groups = null,
65+
$version = null,
66+
ValidatorInterface $validator = null,
67+
$validationErrorsArgument = null
68+
) {
69+
$this->serializer = $serializer;
70+
71+
if (!empty($groups)) {
72+
$this->context['groups'] = (array) $groups;
73+
}
74+
if (!empty($version)) {
75+
$this->context['version'] = $version;
76+
}
77+
78+
if (null !== $validator && null === $validationErrorsArgument) {
79+
throw new \InvalidArgumentException('"$validationErrorsArgument" cannot be null when using the validator');
80+
}
81+
$this->validator = $validator;
82+
$this->validationErrorsArgument = $validationErrorsArgument;
83+
}
84+
85+
/**
86+
* Stores the object in the request.
87+
*
88+
* @param Request $request The request
89+
* @param ParamConverter $configuration Contains the name, class and options of the object
90+
*
91+
* @return boolean True if the object has been successfully set, else false
92+
*
93+
* @throws UnsupportedMediaTypeHttpException
94+
* @throws BadRequestHttpException
95+
*/
96+
protected function execute(Request $request, ParamConverter $configuration)
97+
{
98+
$options = (array) $configuration->getOptions();
99+
100+
if (isset($options['deserializationContext']) && is_array($options['deserializationContext'])) {
101+
$context = array_merge($this->context, $options['deserializationContext']);
102+
} else {
103+
$context = $this->context;
104+
}
105+
106+
if ($this->serializer instanceof SerializerInterface) {
107+
$context = $this->configureDeserializationContext($this->getDeserializationContext(), $context);
108+
}
109+
110+
try {
111+
$object = $this->serializer->deserialize(
112+
$request->getContent(),
113+
$configuration->getClass(),
114+
$request->getContentType(),
115+
$context
116+
);
117+
} catch (UnsupportedFormatException $e) {
118+
throw new UnsupportedMediaTypeHttpException($e->getMessage());
119+
} catch (JMSSerializerException $e) {
120+
throw new BadRequestHttpException($e->getMessage());
121+
} catch (SymfonySerializerException $e) {
122+
throw new BadRequestHttpException($e->getMessage());
123+
}
124+
125+
$request->attributes->set($configuration->getName(), $object);
126+
127+
if (null !== $this->validator) {
128+
$validatorOptions = $this->getValidatorOptions($options);
129+
$request->attributes->set(
130+
$this->validationErrorsArgument,
131+
$this->validator->validate(
132+
$object,
133+
$validatorOptions['groups'],
134+
$validatorOptions['traverse'],
135+
$validatorOptions['deep']
136+
)
137+
);
138+
}
139+
140+
return true;
141+
}
142+
143+
/**
144+
* @return DeserializationContext
145+
*/
146+
protected function getDeserializationContext()
147+
{
148+
return DeserializationContext::create();
149+
}
150+
151+
/**
152+
* @param DeserializationContext $context
153+
* @param array $options
154+
*
155+
* @return DeserializationContext
156+
*/
157+
protected function configureDeserializationContext(DeserializationContext $context, array $options)
158+
{
159+
if (isset($options['groups'])) {
160+
$context->setGroups($options['groups']);
161+
}
162+
if (isset($options['version'])) {
163+
$context->setVersion($options['version']);
164+
}
165+
166+
return $context;
167+
}
168+
169+
/**
170+
* @param array $options
171+
*
172+
* @return array
173+
*/
174+
protected function getValidatorOptions(array $options)
175+
{
176+
$resolver = new OptionsResolver();
177+
$resolver->setDefaults(array(
178+
'groups' => null,
179+
'traverse' => false,
180+
'deep' => false,
181+
));
182+
183+
return $resolver->resolve(isset($options['validator']) ? $options['validator'] : array());
184+
}
185+
}

Request/RequestBodyParamConverter.php

Lines changed: 5 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -12,175 +12,26 @@
1212
namespace FOS\RestBundle\Request;
1313

1414
use Symfony\Component\HttpFoundation\Request;
15-
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
16-
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
17-
use Symfony\Component\OptionsResolver\OptionsResolver;
18-
use Symfony\Component\Serializer\Exception\Exception as SymfonySerializerException;
19-
use Symfony\Component\Serializer\SerializerInterface as SymfonySerializerInterface;
20-
use Symfony\Component\Validator\ValidatorInterface;
21-
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
22-
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
23-
use JMS\Serializer\Exception\UnsupportedFormatException;
24-
use JMS\Serializer\Exception\Exception as JMSSerializerException;
25-
use JMS\Serializer\DeserializationContext;
26-
use JMS\Serializer\SerializerInterface;
15+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
2716

2817
/**
2918
* @author Tyler Stroud <[email protected]>
3019
*/
31-
class RequestBodyParamConverter implements ParamConverterInterface
20+
class RequestBodyParamConverter extends AbstractRequestBodyParamConverter
3221
{
33-
/**
34-
* @var object
35-
*/
36-
protected $serializer;
37-
38-
/**
39-
* @var array
40-
*/
41-
protected $context = array();
42-
43-
/**
44-
* @var null|ValidatorInterface
45-
*/
46-
protected $validator;
47-
48-
/**
49-
* @var null|string The name of the argument on which the ConstraintViolationList will be set
50-
*/
51-
protected $validationErrorsArgument;
52-
53-
/**
54-
* @param object $serializer
55-
* @param array|null $groups An array of groups to be used in the serialization context
56-
* @param string|null $version A version string to be used in the serialization context
57-
* @param object $serializer
58-
* @param ValidatorInterface $validator
59-
* @param string|null $validationErrorsArgument
60-
*
61-
* @throws \InvalidArgumentException
62-
*/
63-
public function __construct(
64-
$serializer,
65-
$groups = null,
66-
$version = null,
67-
ValidatorInterface $validator = null,
68-
$validationErrorsArgument = null
69-
) {
70-
$this->serializer = $serializer;
71-
72-
if (!empty($groups)) {
73-
$this->context['groups'] = (array) $groups;
74-
}
75-
if (!empty($version)) {
76-
$this->context['version'] = $version;
77-
}
78-
79-
if (null !== $validator && null === $validationErrorsArgument) {
80-
throw new \InvalidArgumentException('"$validationErrorsArgument" cannot be null when using the validator');
81-
}
82-
$this->validator = $validator;
83-
$this->validationErrorsArgument = $validationErrorsArgument;
84-
}
85-
8622
/**
8723
* {@inheritDoc}
8824
*/
89-
public function apply(Request $request, ConfigurationInterface $configuration)
25+
public function apply(Request $request, ParamConverter $configuration)
9026
{
91-
$options = (array) $configuration->getOptions();
92-
93-
if (isset($options['deserializationContext']) && is_array($options['deserializationContext'])) {
94-
$context = array_merge($this->context, $options['deserializationContext']);
95-
} else {
96-
$context = $this->context;
97-
}
98-
99-
if ($this->serializer instanceof SerializerInterface) {
100-
$context = $this->configureDeserializationContext($this->getDeserializationContext(), $context);
101-
}
102-
103-
try {
104-
$object = $this->serializer->deserialize(
105-
$request->getContent(),
106-
$configuration->getClass(),
107-
$request->getContentType(),
108-
$context
109-
);
110-
} catch (UnsupportedFormatException $e) {
111-
throw new UnsupportedMediaTypeHttpException($e->getMessage());
112-
} catch (JMSSerializerException $e) {
113-
throw new BadRequestHttpException($e->getMessage());
114-
} catch (SymfonySerializerException $e) {
115-
throw new BadRequestHttpException($e->getMessage());
116-
}
117-
118-
$request->attributes->set($configuration->getName(), $object);
119-
120-
if (null !== $this->validator) {
121-
$validatorOptions = $this->getValidatorOptions($options);
122-
$request->attributes->set(
123-
$this->validationErrorsArgument,
124-
$this->validator->validate(
125-
$object,
126-
$validatorOptions['groups'],
127-
$validatorOptions['traverse'],
128-
$validatorOptions['deep']
129-
)
130-
);
131-
}
132-
133-
return true;
27+
return $this->execute($request, $configuration);
13428
}
13529

13630
/**
13731
* {@inheritDoc}
13832
*/
139-
public function supports(ConfigurationInterface $configuration)
33+
public function supports(ParamConverter $configuration)
14034
{
14135
return null !== $configuration->getClass();
14236
}
143-
144-
/**
145-
* @return DeserializationContext
146-
*/
147-
protected function getDeserializationContext()
148-
{
149-
return DeserializationContext::create();
150-
}
151-
152-
/**
153-
* @param DeserializationContext $context
154-
* @param array $options
155-
*
156-
* @return DeserializationContext
157-
*/
158-
protected function configureDeserializationContext(DeserializationContext $context, array $options)
159-
{
160-
if (isset($options['groups'])) {
161-
$context->setGroups($options['groups']);
162-
}
163-
if (isset($options['version'])) {
164-
$context->setVersion($options['version']);
165-
}
166-
167-
return $context;
168-
}
169-
170-
/**
171-
* @param array $options
172-
*
173-
* @return array
174-
*/
175-
protected function getValidatorOptions(array $options)
176-
{
177-
$resolver = new OptionsResolver();
178-
$resolver->setDefaults(array(
179-
'groups' => null,
180-
'traverse' => false,
181-
'deep' => false,
182-
));
183-
184-
return $resolver->resolve(isset($options['validator']) ? $options['validator'] : array());
185-
}
18637
}

0 commit comments

Comments
 (0)