Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 333ca17

Browse filesBrowse files
committed
[Validator] Added StrictTypes as class constraint with not nullable typed properties
1 parent e493e9d commit 333ca17
Copy full SHA for 333ca17

File tree

5 files changed

+134
-0
lines changed
Filter options

5 files changed

+134
-0
lines changed

‎src/Symfony/Component/Validator/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
5.1.0
55
-----
66

7+
* added a `StrictTypes` constraint to ease validating non nullable typed properties
78
* added a `Cascade` constraint to ease validating typed nested objects
89
* added the `Hostname` constraint and validator
910
* added the `alpha3` option to the `Country` and `Language` constraints
+41Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.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 Symfony\Component\Validator\Constraints;
13+
14+
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
16+
17+
/**
18+
* @Annotation
19+
* @Target({"CLASS"})
20+
*
21+
* @author Jules Pietri <jules@heahprod.com>
22+
*/
23+
class StrictTypes extends Constraint
24+
{
25+
public function __construct($options = null)
26+
{
27+
if (\is_array($options) && \array_key_exists('groups', $options)) {
28+
throw new ConstraintDefinitionException(sprintf('The option "groups" is not supported by the constraint "%s".', __CLASS__));
29+
}
30+
31+
parent::__construct($options);
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
public function getTargets()
38+
{
39+
return self::CLASS_CONSTRAINT;
40+
}
41+
}

‎src/Symfony/Component/Validator/Mapping/ClassMetadata.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Mapping/ClassMetadata.php
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
use Symfony\Component\Validator\Constraint;
1515
use Symfony\Component\Validator\Constraints\Cascade;
1616
use Symfony\Component\Validator\Constraints\GroupSequence;
17+
use Symfony\Component\Validator\Constraints\NotNull;
18+
use Symfony\Component\Validator\Constraints\StrictTypes;
1719
use Symfony\Component\Validator\Constraints\Traverse;
20+
use Symfony\Component\Validator\Constraints\Type;
1821
use Symfony\Component\Validator\Constraints\Valid;
1922
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
2023
use Symfony\Component\Validator\Exception\GroupDefinitionException;
@@ -220,6 +223,21 @@ public function addConstraint(Constraint $constraint)
220223
return $this;
221224
}
222225

226+
if ($constraint instanceof StrictTypes) {
227+
if (\PHP_VERSION_ID < 70400) {
228+
throw new ConstraintDefinitionException(sprintf('The constraint "%s" requires PHP 7.4.', StrictTypes::class));
229+
}
230+
231+
foreach ($this->getReflectionClass()->getProperties() as $property) {
232+
if ($property->hasType() && !$property->getType()->allowsNull()) {
233+
$this->addPropertyConstraint($property->getName(), new NotNull());
234+
}
235+
}
236+
237+
// The constraint is not added
238+
return $this;
239+
}
240+
223241
$constraint->addImplicitGroupName($this->getDefaultGroup());
224242

225243
parent::addConstraint($constraint);

‎src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Validator\Constraint;
1616
use Symfony\Component\Validator\Constraints\Cascade;
17+
use Symfony\Component\Validator\Constraints\StrictTypes;
1718
use Symfony\Component\Validator\Constraints\Valid;
1819
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
1920
use Symfony\Component\Validator\Mapping\CascadingStrategy;
@@ -346,4 +347,34 @@ public function testCascadeConstraint()
346347
'children',
347348
], $metadata->getConstrainedProperties());
348349
}
350+
351+
/**
352+
* @requires PHP < 7.4
353+
*/
354+
public function testStrictTypesConstraintIsNotAvailable()
355+
{
356+
$metadata = new ClassMetadata(CascadingEntity::class);
357+
358+
$this->expectException(ConstraintDefinitionException::class);
359+
$this->expectExceptionMessage('The constraint "Symfony\Component\Validator\Constraints\StrictTypes" requires PHP 7.4.');
360+
361+
$metadata->addConstraint(new StrictTypes());
362+
}
363+
364+
/**
365+
* @requires PHP 7.4
366+
*/
367+
public function testStrictTypesConstraint()
368+
{
369+
$metadata = new ClassMetadata(CascadingEntity::class);
370+
371+
$metadata->addConstraint(new StrictTypes());
372+
373+
$this->assertCount(3, $metadata->properties);
374+
$this->assertSame([
375+
'scalar',
376+
'requiredChild',
377+
'children',
378+
], $metadata->getConstrainedProperties());
379+
}
349380
}

‎src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php
+43Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\Validator\Constraints\Length;
2121
use Symfony\Component\Validator\Constraints\NotBlank;
2222
use Symfony\Component\Validator\Constraints\NotNull;
23+
use Symfony\Component\Validator\Constraints\StrictTypes;
2324
use Symfony\Component\Validator\Constraints\Type;
2425
use Symfony\Component\Validator\Constraints\Valid;
2526
use Symfony\Component\Validator\ConstraintValidatorFactory;
@@ -276,4 +277,46 @@ public function testValidateWithExplicitCascade()
276277

277278
CascadingEntity::$staticChild = null;
278279
}
280+
281+
/**
282+
* @requires PHP 7.4
283+
*/
284+
public function testValidateWithExplicitCascadeUninitialized()
285+
{
286+
$this->metadataFactory->addMetadata((new ClassMetadata(CascadingEntity::class))
287+
->addConstraint(new Cascade())
288+
);
289+
$this->metadataFactory->addMetadata((new ClassMetadata(CascadedChild::class))
290+
->addPropertyConstraint('name', new NotNull())
291+
);
292+
293+
$entity = new CascadingEntity();
294+
295+
$violations = $this->validator->validate($entity);
296+
297+
$this->assertCount(0, $violations);
298+
}
299+
300+
/**
301+
* @requires PHP 7.4
302+
*/
303+
public function testValidateWithExplicitStrictTypesUninitialized()
304+
{
305+
$this->metadataFactory->addMetadata((new ClassMetadata(CascadingEntity::class))
306+
->addConstraint(new StrictTypes())
307+
);
308+
309+
$entity = new CascadingEntity();
310+
311+
$violations = $this->validator->validate($entity);
312+
313+
$this->assertCount(3, $violations);
314+
315+
$this->assertInstanceOf(NotNull::class, $violations->get(0)->getConstraint());
316+
$this->assertInstanceOf(NotNull::class, $violations->get(1)->getConstraint());
317+
$this->assertInstanceOf(NotNull::class, $violations->get(2)->getConstraint());
318+
$this->assertSame('scalar', $violations->get(0)->getPropertyPath());
319+
$this->assertSame('requiredChild', $violations->get(1)->getPropertyPath());
320+
$this->assertSame('children', $violations->get(2)->getPropertyPath());
321+
}
279322
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.