Skip to content

Commit bc1205d

Browse files
committed
[Validator] Allow creating constraints with required arguments
1 parent 1317e39 commit bc1205d

File tree

8 files changed

+105
-1
lines changed

8 files changed

+105
-1
lines changed

src/Symfony/Component/Validator/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
CHANGELOG
22
=========
33

4+
6.1
5+
6+
* Allow creating constraints with required arguments
7+
48
6.0
59
---
610

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ protected function newConstraint(string $name, mixed $options = null): Constrain
7878
$className = self::DEFAULT_NAMESPACE.$name;
7979
}
8080

81-
return new $className($options);
81+
try {
82+
return new $className($options);
83+
} catch (\TypeError $e) {
84+
if (!\is_array($options) || \PHP_VERSION_ID < 80100) {
85+
throw $e;
86+
}
87+
88+
return new $className(...$options);
89+
}
8290
}
8391
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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\Constraint;
15+
16+
#[\Attribute]
17+
final class ConstraintWithRequiredArgument extends Constraint
18+
{
19+
public string $requiredArg;
20+
21+
public function __construct(string $requiredArg, array $groups = null, mixed $payload = null)
22+
{
23+
parent::__construct([], $groups, $payload);
24+
25+
$this->requiredArg = $requiredArg;
26+
}
27+
}
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: 18 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,22 @@ public function testLoadClassMetadataWithNonStrings()
98100
$this->assertFalse($constraints[0]->match);
99101
}
100102

103+
/**
104+
* @requires PHP 8.1
105+
*/
106+
public function testLoadClassMetadataWithRequiredArguments()
107+
{
108+
$loader = new XmlFileLoader(__DIR__.'/constraint-mapping-required-arg.xml');
109+
$metadata = new ClassMetadata(Entity_81::class);
110+
111+
$loader->loadClassMetadata($metadata);
112+
113+
$expected = new ClassMetadata(Entity_81::class);
114+
$expected->addPropertyConstraint('title', new ConstraintWithRequiredArgument('X'));
115+
116+
$this->assertEquals($expected, $metadata);
117+
}
118+
101119
public function testLoadGroupSequenceProvider()
102120
{
103121
$loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');

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

Lines changed: 18 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
{
@@ -139,6 +141,22 @@ public function testLoadClassMetadataWithConstants()
139141
$this->assertEquals($expected, $metadata);
140142
}
141143

144+
/**
145+
* @requires PHP 8.1
146+
*/
147+
public function testLoadClassMetadataWithRequiredArguments()
148+
{
149+
$loader = new YamlFileLoader(__DIR__.'/constraint-mapping-required-arg.yml');
150+
$metadata = new ClassMetadata(Entity_81::class);
151+
152+
$loader->loadClassMetadata($metadata);
153+
154+
$expected = new ClassMetadata(Entity_81::class);
155+
$expected->addPropertyConstraint('title', new ConstraintWithRequiredArgument('X'));
156+
157+
$this->assertEquals($expected, $metadata);
158+
}
159+
142160
public function testLoadGroupSequenceProvider()
143161
{
144162
$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)