This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file is part of the Cubiche package. |
||
4 | * |
||
5 | * Copyright (c) Cubiche |
||
6 | * |
||
7 | * For the full copyright and license information, please view the LICENSE |
||
8 | * file that was distributed with this source code. |
||
9 | */ |
||
10 | |||
11 | namespace Cubiche\Core\Validator; |
||
12 | |||
13 | use Cubiche\Core\Validator\Exception\ValidationException; |
||
14 | use Cubiche\Core\Validator\Mapping\ClassMetadata; |
||
15 | use Cubiche\Core\Validator\Mapping\Driver\StaticDriver; |
||
16 | use Metadata\Driver\DriverChain; |
||
17 | use Metadata\MetadataFactory; |
||
18 | use Metadata\MetadataFactoryInterface; |
||
19 | use Respect\Validation\Exceptions\NestedValidationException; |
||
20 | |||
21 | /** |
||
22 | * Validator class. |
||
23 | * |
||
24 | * @author Ivannis Suárez Jerez <[email protected]> |
||
25 | */ |
||
26 | class Validator implements ValidatorInterface |
||
27 | { |
||
28 | /** |
||
29 | * @var array |
||
30 | */ |
||
31 | protected $constraints = array(); |
||
32 | |||
33 | /** |
||
34 | * @var string |
||
35 | */ |
||
36 | protected $defaultGroup; |
||
37 | |||
38 | /** |
||
39 | * @var MetadataFactoryInterface |
||
40 | */ |
||
41 | protected $metadataFactory; |
||
42 | |||
43 | /** |
||
44 | * @var Validator |
||
45 | */ |
||
46 | private static $instance = null; |
||
47 | |||
48 | /** |
||
49 | * Validator constructor. |
||
50 | * |
||
51 | * @param MetadataFactoryInterface $metadataFactory |
||
52 | * @param string $defaultGroup |
||
53 | */ |
||
54 | private function __construct(MetadataFactoryInterface $metadataFactory, $defaultGroup = Assert::DEFAULT_GROUP) |
||
55 | { |
||
56 | $this->metadataFactory = $metadataFactory; |
||
57 | $this->defaultGroup = $defaultGroup; |
||
58 | } |
||
59 | |||
60 | /** |
||
61 | * @param MetadataFactoryInterface $metadataFactory |
||
62 | */ |
||
63 | public static function setMetadataFactory(MetadataFactoryInterface $metadataFactory) |
||
64 | { |
||
65 | static::create()->metadataFactory = $metadataFactory; |
||
66 | } |
||
67 | |||
68 | /** |
||
69 | * @param $defaultGroup |
||
70 | */ |
||
71 | public static function setDefaultGroup($defaultGroup) |
||
72 | { |
||
73 | static::create()->defaultGroup = $defaultGroup; |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * @return Validator |
||
78 | */ |
||
79 | public static function create() |
||
80 | { |
||
81 | if (static::$instance === null) { |
||
0 ignored issues
–
show
|
|||
82 | static::$instance = new static( |
||
0 ignored issues
–
show
Since
$instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self , or increasing the visibility of $instance to at least protected.
Let’s assume you have a class which uses late-static binding: class YourClass
{
private static $someVariable;
public static function getSomeVariable()
{
return static::$someVariable;
}
}
The code above will run fine in your PHP runtime. However, if you now create a
sub-class and call the class YourSubClass extends YourClass { }
YourSubClass::getSomeVariable(); // Will cause an access error.
In the case above, it makes sense to update class SomeClass
{
private static $someVariable;
public static function getSomeVariable()
{
return self::$someVariable; // self works fine with private.
}
}
![]() |
|||
83 | new MetadataFactory(new DriverChain(array(new StaticDriver()))) |
||
84 | ); |
||
85 | } |
||
86 | |||
87 | return static::$instance; |
||
0 ignored issues
–
show
Since
$instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self , or increasing the visibility of $instance to at least protected.
Let’s assume you have a class which uses late-static binding: class YourClass
{
private static $someVariable;
public static function getSomeVariable()
{
return static::$someVariable;
}
}
The code above will run fine in your PHP runtime. However, if you now create a
sub-class and call the class YourSubClass extends YourClass { }
YourSubClass::getSomeVariable(); // Will cause an access error.
In the case above, it makes sense to update class SomeClass
{
private static $someVariable;
public static function getSomeVariable()
{
return self::$someVariable; // self works fine with private.
}
}
![]() |
|||
88 | } |
||
89 | |||
90 | /** |
||
91 | * @param Assert $assert |
||
92 | * @param string $className |
||
93 | * @param string $group |
||
94 | * |
||
95 | * @return $this |
||
96 | */ |
||
97 | protected function addConstraint(Assert $assert, $className = null, $group = null) |
||
98 | { |
||
99 | $className = $this->normalizeClassName($className); |
||
100 | $group = $this->normalizeGroup($group); |
||
101 | |||
102 | if (!isset($this->constraints[$className])) { |
||
103 | $this->constraints[$className] = array(); |
||
104 | } |
||
105 | |||
106 | if (!isset($this->constraints[$className][$group])) { |
||
107 | $this->constraints[$className][$group] = Assert::create(); |
||
108 | } |
||
109 | |||
110 | $this->constraints[$className][$group]->addRules($assert->getRules()); |
||
111 | |||
112 | return $this; |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * @param string $className |
||
117 | * @param string $group |
||
118 | * |
||
119 | * @return Assert |
||
120 | */ |
||
121 | protected function getConstraintsByGroup($className = null, $group = null) |
||
122 | { |
||
123 | $className = $this->normalizeClassName($className); |
||
124 | $group = $this->normalizeGroup($group); |
||
125 | |||
126 | if (!isset($this->constraints[$className])) { |
||
127 | return Assert::create()->alwaysValid(); |
||
128 | } |
||
129 | |||
130 | if (!isset($this->constraints[$className][$group])) { |
||
131 | return Assert::create()->alwaysValid(); |
||
132 | } |
||
133 | |||
134 | return $this->constraints[$className][$group]; |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * {@inheritdoc} |
||
139 | */ |
||
140 | public static function assert($value, $constraints = null, $group = null) |
||
141 | { |
||
142 | return static::create()->assertConstraints($value, $constraints, $group); |
||
143 | } |
||
144 | |||
145 | /** |
||
146 | * {@inheritdoc} |
||
147 | */ |
||
148 | protected function assertConstraints($value, $constraints = null, $group = null) |
||
149 | { |
||
150 | $group = $this->normalizeGroup($group); |
||
151 | |||
152 | // If explicit constraints are passed, validate the value against |
||
153 | // those constraints |
||
154 | if (null !== $constraints) { |
||
155 | if (!is_array($constraints)) { |
||
156 | $constraints = array($constraints); |
||
157 | } |
||
158 | |||
159 | foreach ($constraints as $constraint) { |
||
160 | $this->addConstraint($constraint, null, $group); |
||
161 | } |
||
162 | |||
163 | $constraints = $this->getConstraintsByGroup(null, $group); |
||
164 | |||
165 | try { |
||
166 | $returnValue = $constraints->assert($value); |
||
167 | } catch (NestedValidationException $e) { |
||
168 | throw new ValidationException( |
||
169 | implode(', ', $e->getMessages()), |
||
170 | $e->getMessages(), |
||
171 | $e->getCode(), |
||
172 | $e->getPrevious() |
||
173 | ); |
||
174 | } |
||
175 | |||
176 | return $returnValue; |
||
177 | } |
||
178 | |||
179 | // If an object is passed without explicit constraints, validate that |
||
180 | // object against the constraints defined for the object's class |
||
181 | if (is_object($value)) { |
||
182 | $this->addObjectConstraints($value); |
||
183 | |||
184 | $constraints = $this->getConstraintsByGroup(get_class($value), $group); |
||
185 | |||
186 | try { |
||
187 | $returnValue = $constraints->assert($value); |
||
188 | } catch (NestedValidationException $e) { |
||
189 | throw new ValidationException( |
||
190 | implode(', ', $e->getMessages()), |
||
191 | $e->getMessages(), |
||
192 | $e->getCode(), |
||
193 | $e->getPrevious() |
||
194 | ); |
||
195 | } |
||
196 | |||
197 | return $returnValue; |
||
198 | } |
||
199 | |||
200 | // If an array is passed without explicit constraints, validate each |
||
201 | // object in the array |
||
202 | if (is_array($value)) { |
||
203 | $this->addArrayConstraints($value); |
||
204 | |||
205 | $returnValue = true; |
||
206 | foreach ($value as $item) { |
||
207 | $constraints = $this->getConstraintsByGroup(is_object($item) ? get_class($item) : null, $group); |
||
208 | |||
209 | try { |
||
210 | $returnValue = $returnValue && $constraints->assert($item); |
||
211 | } catch (NestedValidationException $e) { |
||
212 | throw new ValidationException( |
||
213 | implode(', ', $e->getMessages()), |
||
214 | $e->getMessages(), |
||
215 | $e->getCode(), |
||
216 | $e->getPrevious() |
||
217 | ); |
||
218 | } |
||
219 | } |
||
220 | |||
221 | return $returnValue; |
||
222 | } |
||
223 | |||
224 | throw new \RuntimeException(sprintf( |
||
225 | 'Cannot validate values of type "%s" automatically. Please '. |
||
226 | 'provide a constraint.', |
||
227 | gettype($value) |
||
228 | )); |
||
229 | } |
||
230 | |||
231 | /** |
||
232 | * {@inheritdoc} |
||
233 | */ |
||
234 | public static function validate($value, $constraints = null, $group = null) |
||
235 | { |
||
236 | return static::create()->validateConstraints($value, $constraints, $group); |
||
237 | } |
||
238 | |||
239 | /** |
||
240 | * {@inheritdoc} |
||
241 | */ |
||
242 | protected function validateConstraints($value, $constraints = null, $group = null) |
||
243 | { |
||
244 | $group = $this->normalizeGroup($group); |
||
245 | |||
246 | // If explicit constraints are passed, validate the value against |
||
247 | // those constraints |
||
248 | if (null !== $constraints) { |
||
249 | if (!is_array($constraints)) { |
||
250 | $constraints = array($constraints); |
||
251 | } |
||
252 | |||
253 | foreach ($constraints as $constraint) { |
||
254 | $this->addConstraint($constraint, null, $group); |
||
255 | } |
||
256 | |||
257 | return $this->getConstraintsByGroup(null, $group)->validate($value); |
||
258 | } |
||
259 | |||
260 | // If an object is passed without explicit constraints, validate that |
||
261 | // object against the constraints defined for the object's class |
||
262 | if (is_object($value)) { |
||
263 | $this->addObjectConstraints($value); |
||
264 | |||
265 | return $this->getConstraintsByGroup(get_class($value), $group)->validate($value); |
||
266 | } |
||
267 | |||
268 | // If an array is passed without explicit constraints, validate each |
||
269 | // object in the array |
||
270 | if (is_array($value)) { |
||
271 | $this->addArrayConstraints($value); |
||
272 | |||
273 | $returnValue = true; |
||
274 | foreach ($value as $item) { |
||
275 | $constraints = $this->getConstraintsByGroup(is_object($item) ? get_class($item) : null, $group); |
||
276 | $returnValue = $returnValue && $constraints->validate($item); |
||
277 | } |
||
278 | |||
279 | return $returnValue; |
||
280 | } |
||
281 | |||
282 | throw new \RuntimeException(sprintf( |
||
283 | 'Cannot validate values of type "%s" automatically. Please '. |
||
284 | 'provide a constraint.', |
||
285 | gettype($value) |
||
286 | )); |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * @param object $object |
||
291 | */ |
||
292 | protected function addObjectConstraints($object) |
||
293 | { |
||
294 | $metadata = $this->metadataFactory->getMetadataForClass(get_class($object)); |
||
295 | if ($metadata !== null) { |
||
296 | /** @var ClassMetadata $classMetadata */ |
||
297 | $classMetadata = $metadata->getRootClassMetadata(); |
||
298 | |||
299 | View Code Duplication | foreach ($classMetadata->getPropertiesMetadata() as $propertyMetadata) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
300 | foreach ($propertyMetadata->getConstraints() as $group => $constraints) { |
||
301 | $allOf = Assert::create(); |
||
302 | foreach ($constraints as $constraint) { |
||
303 | $allOf->addRules($constraint->getRules()); |
||
304 | } |
||
305 | |||
306 | $this->addConstraint( |
||
307 | Assert::create()->attribute($propertyMetadata->getPropertyName(), $allOf), |
||
0 ignored issues
–
show
\Cubiche\Core\Validator\...PropertyName(), $allOf) of type object<Respect\Validation\Validator> is not a sub-type of object<Cubiche\Core\Validator\Assert> . It seems like you assume a child class of the class Respect\Validation\Validator to be always present.
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass. Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type. ![]() |
|||
308 | get_class($object), |
||
309 | $group |
||
310 | ); |
||
311 | } |
||
312 | } |
||
313 | |||
314 | View Code Duplication | foreach ($classMetadata->getMethodsMetadata() as $methodMetadata) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
315 | foreach ($methodMetadata->getConstraints() as $group => $constraints) { |
||
316 | $allOf = Assert::create(); |
||
317 | foreach ($constraints as $constraint) { |
||
318 | $allOf->addRules($constraint->getRules()); |
||
319 | } |
||
320 | |||
321 | $this->addConstraint( |
||
322 | Assert::create()->call([$object, $methodMetadata->getMethodName()], $allOf), |
||
0 ignored issues
–
show
The call to
Assert::call() has too many arguments starting with array($object, $methodMetadata->getMethodName()) .
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. In this case you can add the ![]() \Cubiche\Core\Validator\...tMethodName()), $allOf) of type object<Respect\Validation\Validator> is not a sub-type of object<Cubiche\Core\Validator\Assert> . It seems like you assume a child class of the class Respect\Validation\Validator to be always present.
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass. Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type. ![]() |
|||
323 | get_class($object), |
||
324 | $group |
||
325 | ); |
||
326 | } |
||
327 | } |
||
328 | } |
||
329 | } |
||
330 | |||
331 | /** |
||
332 | * @param string $className |
||
333 | * |
||
334 | * @return ClassMetadata|null |
||
335 | */ |
||
336 | public static function getMetadataForClass($className) |
||
337 | { |
||
338 | return self::create()->metadataFactory->getMetadataForClass($className); |
||
339 | } |
||
340 | |||
341 | /** |
||
342 | * @param string $namespace |
||
343 | * @param bool $prepend |
||
344 | */ |
||
345 | public static function registerValidator($namespace, $prepend = false) |
||
346 | { |
||
347 | Assert::registerValidator($namespace, $prepend); |
||
348 | } |
||
349 | |||
350 | /** |
||
351 | * @param mixed $array |
||
352 | */ |
||
353 | protected function addArrayConstraints($array) |
||
354 | { |
||
355 | foreach ($array as $key => $value) { |
||
356 | if (is_array($value)) { |
||
357 | $this->addArrayConstraints($value); |
||
358 | |||
359 | continue; |
||
360 | } |
||
361 | |||
362 | // Scalar and null values in the collection are ignored |
||
363 | if (is_object($value)) { |
||
364 | $this->addObjectConstraints($value); |
||
365 | } else { |
||
366 | throw new \RuntimeException(sprintf( |
||
367 | 'Cannot validate values of type "%s" automatically. Please '. |
||
368 | 'provide a constraint.', |
||
369 | gettype($value) |
||
370 | )); |
||
371 | } |
||
372 | } |
||
373 | } |
||
374 | |||
375 | /** |
||
376 | * Normalizes the given group. |
||
377 | * |
||
378 | * @param string $group |
||
379 | * |
||
380 | * @return string |
||
381 | */ |
||
382 | protected function normalizeGroup($group = null) |
||
383 | { |
||
384 | return $group === null || empty($group) ? $this->defaultGroup : $group; |
||
385 | } |
||
386 | |||
387 | /** |
||
388 | * Normalizes the given className. |
||
389 | * |
||
390 | * @param string $className |
||
391 | * |
||
392 | * @return string |
||
393 | */ |
||
394 | protected function normalizeClassName($className = null) |
||
395 | { |
||
396 | return $className !== null ? $className : self::class; |
||
397 | } |
||
398 | } |
||
399 |
Let’s assume you have a class which uses late-static binding:
The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the
getSomeVariable()
on that sub-class, you will receive a runtime error:In the case above, it makes sense to update
SomeClass
to useself
instead: