Skip to content

Commit 44c1c1d

Browse files
committed
[Validator] Allow creating constraints with required arguments
1 parent 68fa5a5 commit 44c1c1d

File tree

9 files changed

+111
-0
lines changed

9 files changed

+111
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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\Attribute;
13+
14+
#[\Attribute(\Attribute::TARGET_CLASS)]
15+
final class NamedArgumentConstraintConstructor
16+
{
17+
}

src/Symfony/Component/Validator/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Deprecate `Constraint::$errorNames`, use `Constraint::ERROR_NAMES` instead
88
* Deprecate constraint `ExpressionLanguageSyntax`, use `ExpressionSyntax` instead
99
* Add method `__toString()` to `ConstraintViolationInterface` & `ConstraintViolationListInterface`
10+
* Allow creating constraints with required arguments
1011

1112
6.0
1213
---

src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Validator\Mapping\Loader;
1313

14+
use Symfony\Component\Validator\Attribute\NamedArgumentConstraintConstructor;
1415
use Symfony\Component\Validator\Constraint;
1516
use Symfony\Component\Validator\Exception\MappingException;
1617

@@ -78,6 +79,10 @@ protected function newConstraint(string $name, mixed $options = null): Constrain
7879
$className = self::DEFAULT_NAMESPACE.$name;
7980
}
8081

82+
if ((new \ReflectionClass($className))->getAttributes(NamedArgumentConstraintConstructor::class) !== [] && \is_array($options)) {
83+
return new $className(...$options);
84+
}
85+
8186
return new $className($options);
8287
}
8388
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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\Tests\Fixtures;
13+
14+
use Symfony\Component\Validator\Attribute\NamedArgumentConstraintConstructor;
15+
use Symfony\Component\Validator\Constraint;
16+
17+
#[\Attribute]
18+
#[NamedArgumentConstraintConstructor]
19+
final class ConstraintWithRequiredArgument extends Constraint
20+
{
21+
public string $requiredArg;
22+
23+
public function __construct(string $requiredArg, array $groups = null, mixed $payload = null)
24+
{
25+
parent::__construct([], $groups, $payload);
26+
27+
$this->requiredArg = $requiredArg;
28+
}
29+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Symfony\Component\Validator\Tests\Fixtures;
4+
5+
class Entity_81
6+
{
7+
public $title;
8+
}

src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
use Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity;
2929
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
3030
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
31+
use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithRequiredArgument;
32+
use Symfony\Component\Validator\Tests\Fixtures\Entity_81;
3133

3234
class XmlFileLoaderTest extends TestCase
3335
{
@@ -98,6 +100,19 @@ public function testLoadClassMetadataWithNonStrings()
98100
$this->assertFalse($constraints[0]->match);
99101
}
100102

103+
public function testLoadClassMetadataWithRequiredArguments()
104+
{
105+
$loader = new XmlFileLoader(__DIR__.'/constraint-mapping-required-arg.xml');
106+
$metadata = new ClassMetadata(Entity_81::class);
107+
108+
$loader->loadClassMetadata($metadata);
109+
110+
$expected = new ClassMetadata(Entity_81::class);
111+
$expected->addPropertyConstraint('title', new ConstraintWithRequiredArgument('X'));
112+
113+
$this->assertEquals($expected, $metadata);
114+
}
115+
101116
public function testLoadGroupSequenceProvider()
102117
{
103118
$loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');

src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
use Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity;
2626
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
2727
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
28+
use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithRequiredArgument;
29+
use Symfony\Component\Validator\Tests\Fixtures\Entity_81;
2830

2931
class YamlFileLoaderTest extends TestCase
3032
{
@@ -138,6 +140,19 @@ public function testLoadClassMetadataWithConstants()
138140
$this->assertEquals($expected, $metadata);
139141
}
140142

143+
public function testLoadClassMetadataWithRequiredArguments()
144+
{
145+
$loader = new YamlFileLoader(__DIR__.'/constraint-mapping-required-arg.yml');
146+
$metadata = new ClassMetadata(Entity_81::class);
147+
148+
$loader->loadClassMetadata($metadata);
149+
150+
$expected = new ClassMetadata(Entity_81::class);
151+
$expected->addPropertyConstraint('title', new ConstraintWithRequiredArgument('X'));
152+
153+
$this->assertEquals($expected, $metadata);
154+
}
155+
141156
public function testLoadGroupSequenceProvider()
142157
{
143158
$loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" ?>
2+
3+
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
6+
7+
<class name="Symfony\Component\Validator\Tests\Fixtures\Entity_81">
8+
9+
<property name="title">
10+
<constraint name="Symfony\Component\Validator\Tests\Fixtures\ConstraintWithRequiredArgument">
11+
<option name="requiredArg">X</option>
12+
</constraint>
13+
</property>
14+
</class>
15+
16+
</constraint-mapping>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Symfony\Component\Validator\Tests\Fixtures\Entity_81:
2+
properties:
3+
title:
4+
- Symfony\Component\Validator\Tests\Fixtures\ConstraintWithRequiredArgument:
5+
requiredArg: 'X'

0 commit comments

Comments
 (0)