These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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 FOS\RestBundle\Controller\Annotations\ParamInterface; |
||
15 | use FOS\RestBundle\Exception\InvalidParameterException; |
||
16 | use FOS\RestBundle\Util\ResolverTrait; |
||
17 | use FOS\RestBundle\Validator\Constraints\ResolvableConstraintInterface; |
||
18 | use Symfony\Component\DependencyInjection\ContainerInterface; |
||
19 | use Symfony\Component\HttpFoundation\Request; |
||
20 | use Symfony\Component\HttpFoundation\RequestStack; |
||
21 | use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
||
22 | use Symfony\Component\Validator\Constraint; |
||
23 | use Symfony\Component\Validator\ConstraintViolationList; |
||
24 | use Symfony\Component\Validator\Validator\ValidatorInterface; |
||
25 | use Symfony\Component\Validator\Exception\ValidatorException; |
||
26 | use Symfony\Component\Validator\ConstraintViolation; |
||
27 | |||
28 | /** |
||
29 | * Helper to validate parameters of the active request. |
||
30 | * |
||
31 | * @author Alexander <[email protected]> |
||
32 | * @author Lukas Kahwe Smith <[email protected]> |
||
33 | * @author Jordi Boggiano <[email protected]> |
||
34 | * @author Boris Guéry <[email protected]> |
||
35 | */ |
||
36 | class ParamFetcher implements ParamFetcherInterface |
||
37 | { |
||
38 | use ResolverTrait; |
||
39 | |||
40 | private $container; |
||
41 | private $parameterBag; |
||
42 | private $requestStack; |
||
43 | private $validator; |
||
44 | |||
45 | /** |
||
46 | * Initializes fetcher. |
||
47 | * |
||
48 | * @param ContainerInterface $container |
||
49 | * @param ParamReaderInterface $paramReader |
||
50 | * @param RequestStack $requestStack |
||
51 | * @param ValidatorInterface $validator |
||
52 | */ |
||
53 | 27 | public function __construct(ContainerInterface $container, ParamReaderInterface $paramReader, RequestStack $requestStack, ValidatorInterface $validator = null) |
|
54 | { |
||
55 | 27 | if (null === $validator) { |
|
56 | 27 | @trigger_error(sprintf('Using no validator is deprecated since FOSRestBundle 2.6. The `$validator` constructor argument of the `%s` will become mandatory in 3.0.', __CLASS__), E_USER_DEPRECATED); |
|
0 ignored issues
–
show
|
|||
57 | 27 | } |
|
58 | |||
59 | 27 | $this->container = $container; |
|
60 | 27 | $this->requestStack = $requestStack; |
|
61 | $this->validator = $validator; |
||
62 | |||
63 | $this->parameterBag = new ParameterBag($paramReader); |
||
64 | } |
||
65 | 15 | ||
66 | /** |
||
67 | 15 | * {@inheritdoc} |
|
68 | 15 | */ |
|
69 | public function setController($controller) |
||
70 | { |
||
71 | $this->parameterBag->setController($this->getRequest(), $controller); |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Add additional params to the ParamFetcher during runtime. |
||
76 | * |
||
77 | 1 | * Note that adding a param that has the same name as an existing param will override that param. |
|
78 | * |
||
79 | 1 | * @param ParamInterface $param |
|
80 | 1 | */ |
|
81 | public function addParam(ParamInterface $param) |
||
82 | { |
||
83 | $this->parameterBag->addParam($this->getRequest(), $param); |
||
84 | } |
||
85 | 15 | ||
86 | /** |
||
87 | 15 | * @return ParamInterface[] |
|
88 | */ |
||
89 | public function getParams() |
||
90 | { |
||
91 | return $this->parameterBag->getParams($this->getRequest()); |
||
92 | } |
||
93 | 12 | ||
94 | /** |
||
95 | 12 | * {@inheritdoc} |
|
96 | */ |
||
97 | 12 | public function get($name, $strict = null) |
|
98 | 1 | { |
|
99 | $params = $this->getParams(); |
||
100 | |||
101 | if (!array_key_exists($name, $params)) { |
||
102 | 11 | throw new \InvalidArgumentException(sprintf("No @ParamInterface configuration for parameter '%s'.", $name)); |
|
103 | 11 | } |
|
104 | 11 | ||
105 | 11 | /** @var ParamInterface $param */ |
|
106 | $param = $params[$name]; |
||
107 | 11 | $default = $param->getDefault(); |
|
108 | $default = $this->resolveValue($this->container, $default); |
||
109 | 11 | $strict = (null !== $strict ? $strict : $param->isStrict()); |
|
110 | |||
111 | $paramValue = $param->getValue($this->getRequest(), $default); |
||
112 | |||
113 | return $this->cleanParamWithRequirements($param, $paramValue, $strict, $default); |
||
114 | } |
||
115 | |||
116 | /** |
||
117 | * @param ParamInterface $param |
||
118 | * @param mixed $paramValue |
||
119 | * @param bool $strict |
||
120 | * @param mixed $default |
||
121 | * |
||
122 | * @throws BadRequestHttpException |
||
123 | * @throws \RuntimeException |
||
124 | * |
||
125 | 16 | * @return mixed |
|
126 | * |
||
127 | 16 | * @internal |
|
128 | 16 | */ |
|
129 | 4 | protected function cleanParamWithRequirements(ParamInterface $param, $paramValue, $strict, $default) |
|
130 | { |
||
131 | $this->checkNotIncompatibleParams($param); |
||
132 | 14 | if (null !== $default && $default === $paramValue) { |
|
133 | 14 | return $paramValue; |
|
134 | 14 | } |
|
135 | 1 | ||
136 | $constraints = $param->getConstraints(); |
||
137 | 13 | $this->resolveConstraints($constraints); |
|
138 | 1 | if (empty($constraints)) { |
|
139 | return $paramValue; |
||
140 | 1 | } |
|
141 | if (null === $this->validator) { |
||
142 | throw new \RuntimeException( |
||
143 | 'The ParamFetcher requirements feature requires the symfony/validator component.' |
||
144 | 12 | ); |
|
145 | 12 | } |
|
146 | |||
147 | try { |
||
148 | $errors = $this->validator->validate($paramValue, $constraints); |
||
149 | } catch (ValidatorException $e) { |
||
150 | $violation = new ConstraintViolation( |
||
151 | $e->getMessage(), |
||
152 | $e->getMessage(), |
||
153 | array(), |
||
154 | $paramValue, |
||
155 | '', |
||
156 | null, |
||
157 | null, |
||
158 | $e->getCode() |
||
159 | 12 | ); |
|
160 | 6 | $errors = new ConstraintViolationList(array($violation)); |
|
161 | 2 | } |
|
162 | |||
163 | if (0 < count($errors)) { |
||
164 | 4 | if ($strict) { |
|
165 | throw InvalidParameterException::withViolations($param, $errors); |
||
166 | } |
||
167 | 8 | ||
168 | return null === $default ? '' : $default; |
||
169 | } |
||
170 | |||
171 | return $paramValue; |
||
172 | } |
||
173 | 9 | ||
174 | /** |
||
175 | 9 | * {@inheritdoc} |
|
176 | */ |
||
177 | 5 | public function all($strict = null) |
|
178 | 5 | { |
|
179 | 5 | $configuredParams = $this->getParams(); |
|
180 | 5 | ||
181 | $params = []; |
||
182 | 5 | foreach ($configuredParams as $name => $param) { |
|
183 | $params[$name] = $this->get($name, $strict); |
||
184 | } |
||
185 | |||
186 | return $params; |
||
187 | } |
||
188 | |||
189 | /** |
||
190 | * Check if current param is not in conflict with other parameters |
||
191 | * according to the "incompatibles" field. |
||
192 | * |
||
193 | * @param ParamInterface $param the configuration for the param fetcher |
||
194 | * |
||
195 | * @throws InvalidArgumentException |
||
196 | 11 | * @throws BadRequestHttpException |
|
197 | * |
||
198 | 11 | * @internal |
|
199 | 11 | */ |
|
200 | 2 | protected function checkNotIncompatibleParams(ParamInterface $param) |
|
201 | 1 | { |
|
202 | if (null === $param->getValue($this->getRequest(), null)) { |
||
203 | 1 | return; |
|
204 | } |
||
205 | 1 | ||
206 | 1 | $params = $this->getParams(); |
|
207 | 1 | foreach ($param->getIncompatibilities() as $incompatibleParamName) { |
|
208 | 1 | if (!array_key_exists($incompatibleParamName, $params)) { |
|
209 | 1 | throw new \InvalidArgumentException(sprintf("No @ParamInterface configuration for parameter '%s'.", $incompatibleParamName)); |
|
210 | 1 | } |
|
211 | $incompatibleParam = $params[$incompatibleParamName]; |
||
212 | 1 | ||
213 | if (null !== $incompatibleParam->getValue($this->getRequest(), null)) { |
||
214 | 10 | $exceptionMessage = sprintf( |
|
215 | 9 | "'%s' param is incompatible with %s param.", |
|
216 | $param->getName(), |
||
217 | $incompatibleParam->getName() |
||
218 | ); |
||
219 | |||
220 | 14 | throw new BadRequestHttpException($exceptionMessage); |
|
221 | } |
||
222 | 14 | } |
|
223 | 13 | } |
|
224 | 4 | ||
225 | 4 | /** |
|
226 | 14 | * @param Constraint[] $constraints |
|
227 | 14 | */ |
|
228 | private function resolveConstraints(array $constraints) |
||
229 | { |
||
230 | foreach ($constraints as $constraint) { |
||
231 | if ($constraint instanceof ResolvableConstraintInterface) { |
||
232 | $constraint->resolve($this->container); |
||
233 | } |
||
234 | 18 | } |
|
235 | } |
||
236 | 18 | ||
237 | 18 | /** |
|
238 | * @throws \RuntimeException |
||
239 | * |
||
240 | * @return Request |
||
241 | 18 | */ |
|
242 | View Code Duplication | private function getRequest() |
|
243 | { |
||
244 | $request = $this->requestStack->getCurrentRequest(); |
||
245 | if (null === $request) { |
||
246 | throw new \RuntimeException('There is no current request.'); |
||
247 | } |
||
248 | |||
249 | return $request; |
||
250 | } |
||
251 | } |
||
252 |
If you suppress an error, we recommend checking for the error condition explicitly: