8000 bug #35843 [Validator] Add target guards for Composite nested constra… · symfony/symfony@92eae57 · GitHub
[go: up one dir, main page]

Skip to content

Commit 92eae57

Browse files
committed
bug #35843 [Validator] Add target guards for Composite nested constraints (ogizanagi)
This PR was merged into the 3.4 branch. Discussion ---------- [Validator] Add target guards for Composite nested constraints | Q | A | ------------- | --- | Branch? | 3.4 <!-- see below --> | Bug fix? | yes | New feature? | no <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tickets | Fix #35815 (review) <!-- prefix each issue number with "Fix #", if any --> | License | MIT | Doc PR | N/A Commits ------- a08ddf7 [Validator] Add target guards for Composite nested constraints
2 parents a77901d + a08ddf7 commit 92eae57

File tree

5 files changed

+126
-6
lines changed
  • Mapping
  • Tests/Mapping
  • 5 files changed

    +126
    -6
    lines changed

    src/Symfony/Component/Validator/Constraints/Composite.php

    Lines changed: 11 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -136,6 +136,17 @@ public function addImplicitGroupName($group)
    136136
    */
    137137
    abstract protected function getCompositeOption();
    138138

    139+
    /**
    140+
    * @internal Used by metadata
    141+
    *
    142+
    * @return Constraint[]
    143+
    */
    144+
    public function getNestedContraints()
    145+
    {
    146+
    /* @var Constraint[] $nestedConstraints */
    147+
    return $this->{$this->getCompositeOption()};
    148+
    }
    149+
    139150
    /**
    140151
    * Initializes the nested constraints.
    141152
    *

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

    Lines changed: 15 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -12,6 +12,7 @@
    1212
    namespace Symfony\Component\Validator\Mapping;
    1313

    1414
    use Symfony\Component\Validator\Constraint;
    15+
    use Symfony\Component\Validator\Constraints\Composite;
    1516
    use Symfony\Component\Validator\Constraints\GroupSequence;
    1617
    use Symfony\Component\Validator\Constraints\Traverse;
    1718
    use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
    @@ -178,9 +179,7 @@ public function getDefaultGroup()
    178179
    */
    179180
    public function addConstraint(Constraint $constraint)
    180181
    {
    181-
    if (!\in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets())) {
    182-
    throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on classes.', \get_class($constraint)));
    183-
    }
    182+
    $this->checkConstraint($constraint);
    184183

    185184
    if ($constraint instanceof Traverse) {
    186185
    if ($constraint->traverse) {
    @@ -495,4 +494,17 @@ private function addPropertyMetadata(PropertyMetadataInterface $metadata)
    495494

    496495
    $this->members[$property][] = $metadata;
    497496
    }
    497+
    498+
    private function checkConstraint(Constraint $constraint)
    499+
    {
    500+
    if (!\in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets(), true)) {
    501+
    throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on classes.', \get_class($constraint)));
    502+
    }
    503+
    504+
    if ($constraint instanceof Composite) {
    505+
    foreach ($constraint->getNestedContraints() as $nestedContraint) {
    506+
    $this->checkConstraint($nestedContraint);
    507+
    }
    508+
    }
    509+
    }
    498510
    }

    src/Symfony/Component/Validator/Mapping/MemberMetadata.php

    Lines changed: 15 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -12,6 +12,7 @@
    1212
    namespace Symfony\Component\Validator\Mapping;
    1313

    1414
    use Symfony\Component\Validator\Constraint;
    15+
    use Symfony\Component\Validator\Constraints\Composite;
    1516
    use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
    1617

    1718
    /**
    @@ -71,9 +72,7 @@ public function __construct($class, $name, $property)
    7172
    */
    7273
    public function addConstraint(Constraint $constraint)
    7374
    {
    74-
    if (!\in_array(Constraint::PROPERTY_CONSTRAINT, (array) $constraint->getTargets())) {
    75-
    throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on properties or getters.', \get_class($constraint)));
    76-
    }
    75+
    $this->checkConstraint($constraint);
    7776

    7877
    parent::addConstraint($constraint);
    7978

    @@ -181,4 +180,17 @@ public function getReflectionMember($objectOrClassName)
    181180
    * @return \ReflectionMethod|\ReflectionProperty The reflection instance
    182181
    */
    183182
    abstract protected function newReflectionMember($objectOrClassName);
    183+
    184+
    private function checkConstraint(Constraint $constraint)
    185+
    {
    186+
    if (!\in_array(Constraint::PROPERTY_CONSTRAINT, (array) $constraint->getTargets(), true)) {
    187+
    throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on properties or getters.', \get_class($constraint)));
    188+
    }
    189+
    190+
    if ($constraint instanceof Composite) {
    191+
    foreach ($constraint->getNestedContraints() as $nestedContraint) {
    192+
    $this->checkConstraint($nestedContraint);
    193+
    }
    194+
    }
    195+
    }
    184196
    }

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

    Lines changed: 37 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -13,8 +13,11 @@
    1313

    1414
    use PHPUnit\Framework\TestCase;
    1515
    use Symfony\Component\Validator\Constraint;
    16+
    use Symfony\Component\Validator\Constraints\Composite;
    1617
    use Symfony\Component\Validator\Constraints\Valid;
    18+
    use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
    1719
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    20+
    use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
    1821
    use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
    1922
    use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
    2023
    use Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint;
    @@ -52,6 +55,20 @@ public function testAddConstraintRequiresClassConstraints()
    5255
    $this->metadata->addConstraint(new PropertyConstraint());
    5356
    }
    5457

    58+
    public function testAddCompositeConstraintRejectsNestedPropertyConstraints()
    59+
    {
    60+
    $this->expectException(ConstraintDefinitionException::class);
    61+
    $this->expectExceptionMessage('The constraint "Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint" cannot be put on classes.');
    62+
    63+
    $this->metadata->addConstraint(new ClassCompositeConstraint([new PropertyConstraint()]));
    64+
    }
    65+
    66+
    public function testAddCompositeConstraintAcceptsNestedClassConstraints()
    67+
    {
    68+
    $this->metadata->addConstraint($constraint = new ClassCompositeConstraint([new ClassConstraint()]));
    69+
    $this->assertSame($this->metadata->getConstraints(), [$constraint]);
    70+
    }
    71+
    5572
    public function testAddPropertyConstraints()
    5673
    {
    5774
    $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
    @@ -311,3 +328,23 @@ public function testGetPropertyMetadataReturnsEmptyArrayWithoutConfiguredMetadat
    311328
    $this->assertCount(0, $this->metadata->getPropertyMetadata('foo'), '->getPropertyMetadata() returns an empty collection if no metadata is configured for the given property');
    312329
    }
    313330
    }
    331+
    332+
    class ClassCompositeConstraint extends Composite
    333+
    {
    334+
    public $nested;
    335+
    336+
    public function getDefaultOption()
    337+
    {
    338+
    return $this->getCompositeOption();
    339+
    }
    340+
    341+
    protected function getCompositeOption()
    342+
    {
    343+
    return 'nested';
    344+
    }
    345+
    346+
    public function getTargets()
    347+
    {
    348+
    return [self::CLASS_CONSTRAINT];
    349+
    }
    350+
    }

    src/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php

    Lines changed: 48 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -12,11 +12,16 @@
    1212
    namespace Symfony\Component\Validator\Tests\Mapping;
    1313

    1414
    use PHPUnit\Framework\TestCase;
    15+
    use Symfony\Component\Validator\Constraints\Collection;
    16+
    use Symfony\Component\Validator\Constraints\Composite;
    17+
    use Symfony\Component\Validator\Constraints\Required;
    1518
    use Symfony\Component\Validator\Constraints\Valid;
    19+
    use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
    1620
    use Symfony\Component\Validator\Mapping\MemberMetadata;
    1721
    use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
    1822
    use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
    1923
    use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
    24+
    use Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint;
    2025

    2126
    class MemberMetadataTest extends TestCase
    2227
    {
    @@ -43,6 +48,34 @@ public function testAddConstraintRequiresClassConstraints()
    4348
    $this->metadata->addConstraint(new ClassConstraint());
    4449
    }
    4550

    51+
    public function testAddCompositeConstraintRejectsNestedClassConstraints()
    52+
    {
    53+
    $this->expectException(ConstraintDefinitionException::class);
    54+
    $this->expectExceptionMessage('The constraint "Symfony\Component\Validator\Tests\Fixtures\ClassConstraint" cannot be put on properties or getters.');
    55+
    56+
    $this->metadata->addConstraint(new PropertyCompositeConstraint([new ClassConstraint()]));
    57+
    }
    58+
    59+
    public function testAddCompositeConstraintRejectsDeepNestedClassConstraints()
    60+
    {
    61+
    $this->expectException(ConstraintDefinitionException::class);
    62+
    $this->expectExceptionMessage('The constraint "Symfony\Component\Validator\Tests\Fixtures\ClassConstraint" cannot be put on properties or getters.');
    63+
    64+
    $this->metadata->addConstraint(new Collection(['field1' => new Required([new ClassConstraint()])]));
    65+
    }
    66+
    67+
    public function testAddCompositeConstraintAcceptsNestedPropertyConstraints()
    68+
    {
    69+
    $this->metadata->addConstraint($constraint = new PropertyCompositeConstraint([new PropertyConstraint()]));
    70+
    $this->assertSame($this->metadata->getConstraints(), [$constraint]);
    71+
    }
    72+
    73+
    public function testAddCompositeConstraintAcceptsDeepNestedPropertyConstraints()
    74+
    {
    75+
    $this->metadata->addConstraint($constraint = new Collection(['field1' => new Required([new PropertyConstraint()])]));
    76+
    $this->assertSame($this->metadata->getConstraints(), [$constraint]);
    77+
    }
    78+
    4679
    public function testSerialize()
    4780
    {
    4881
    $this->metadata->addConstraint(new ConstraintA(['property1' => 'A']));
    @@ -82,3 +115,18 @@ protected function newReflectionMember($object)
    82115
    {
    83116
    }
    84117
    }
    118+
    119+
    class PropertyCompositeConstraint extends Composite
    120+
    {
    121+
    public $nested;
    122+
    123+
    public function getDefaultOption()
    124+
    {
    125+
    return $this->getCompositeOption();
    126+
    }
    127+
    128+
    protected function getCompositeOption()
    129+
    {
    130+
    return 'nested';
    131+
    }
    132+
    }

    0 commit comments

    Comments
     (0)
    0