Skip to content

Commit

Permalink
deprecate the use of option arrays to configure validation constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
xabbuh committed Apr 26, 2024
1 parent 0f6b3ef commit 0d1d920
Show file tree
Hide file tree
Showing 155 changed files with 2,229 additions and 1,768 deletions.
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Bridge\Doctrine\Validator\Constraints;

use Symfony\Component\Validator\Attribute\HasNamedArguments;
use Symfony\Component\Validator\Constraint;

/**
Expand Down Expand Up @@ -45,6 +46,7 @@ class UniqueEntity extends Constraint
* a fieldName => value associative array according to the fields option configuration
* @param string|null $errorPath Bind the constraint violation to this field instead of the first one in the fields option configuration
*/
#[HasNamedArguments]
public function __construct(
array|string $fields,
?string $message = null,
Expand All @@ -59,6 +61,8 @@ public function __construct(
array $options = [],
) {
if (\is_array($fields) && \is_string(key($fields))) {
trigger_deprecation('symfony/validator', '7.2', 'Passing an array of options to configure the %s constraint is deprecated, use named arguments instead.', static::class);

$options = array_merge($fields, $options);
} elseif (null !== $fields) {
$options['fields'] = $fields;
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php
Expand Up @@ -90,7 +90,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool
}

if (true === (self::getFieldMappingValue($mapping, 'unique') ?? false) && !isset($existingUniqueFields[self::getFieldMappingValue($mapping, 'fieldName')])) {
$metadata->addConstraint(new UniqueEntity(['fields' => self::getFieldMappingValue($mapping, 'fieldName')]));
$metadata->addConstraint(new UniqueEntity(fields: self::getFieldMappingValue($mapping, 'fieldName')));
$loaded = true;
}

Expand All @@ -103,7 +103,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool
$metadata->addPropertyConstraint(self::getFieldMappingValue($mapping, 'declaredField'), new Valid());
$loaded = true;
} elseif (property_exists($className, self::getFieldMappingValue($mapping, 'fieldName')) && (!$doctrineMetadata->isMappedSuperclass || $metadata->getReflectionClass()->getProperty(self::getFieldMappingValue($mapping, 'fieldName'))->isPrivate())) {
$metadata->addPropertyConstraint(self::getFieldMappingValue($mapping, 'fieldName'), new Length(['max' => self::getFieldMappingValue($mapping, 'length')]));
$metadata->addPropertyConstraint(self::getFieldMappingValue($mapping, 'fieldName'), new Length(max: self::getFieldMappingValue($mapping, 'length')));
$loaded = true;
}
} elseif (null === $lengthConstraint->max) {
Expand Down
Expand Up @@ -88,7 +88,7 @@ public function testFieldConstraintsInvalidateFormIfFieldIsSubmitted()
public function testNonCompositeConstraintValidatedOnce()
{
$form = $this->formFactory->create(TextType::class, null, [
'constraints' => [new NotBlank(['groups' => ['foo', 'bar']])],
'constraints' => [new NotBlank(groups: ['foo', 'bar'])],
'validation_groups' => ['foo', 'bar'],
]);
$form->submit('');
Expand All @@ -105,12 +105,8 @@ public function testCompositeConstraintValidatedInEachGroup()
$form = $this->formFactory->create(FormType::class, null, [
'constraints' => [
new Collection([
'field1' => new NotBlank([
'groups' => ['field1'],
]),
'field2' => new NotBlank([
'groups' => ['field2'],
]),
'field1' => new NotBlank(groups: ['field1']),
'field2' => new NotBlank(groups: ['field2']),
]),
],
'validation_groups' => ['field1', 'field2'],
Expand All @@ -136,12 +132,8 @@ public function testCompositeConstraintValidatedInSequence()
$form = $this->formFactory->create(FormType::class, null, [
'constraints' => [
new Collection([
'field1' => new NotBlank([
'groups' => ['field1'],
]),
'field2' => new NotBlank([
'groups' => ['field2'],
]),
'field1' => new NotBlank(groups: ['field1']),
'field2' => new NotBlank(groups: ['field2']),
]),
],
'validation_groups' => new GroupSequence(['field1', 'field2']),
Expand All @@ -167,10 +159,10 @@ public function testFieldsValidateInSequence()
'validation_groups' => new GroupSequence(['group1', 'group2']),
])
->add('foo', TextType::class, [
'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])],
'constraints' => [new Length(min: 10, groups: ['group1'])],
])
->add('bar', TextType::class, [
'constraints' => [new NotBlank(['groups' => ['group2']])],
'constraints' => [new NotBlank(groups: ['group2'])],
])
;

Expand All @@ -188,13 +180,13 @@ public function testFieldsValidateInSequenceWithNestedGroupsArray()
'validation_groups' => new GroupSequence([['group1', 'group2'], 'group3']),
])
->add('foo', TextType::class, [
'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])],
'constraints' => [new Length(min: 10, groups: ['group1'])],
])
->add('bar', TextType::class, [
'constraints' => [new Length(['min' => 10, 'groups' => ['group2']])],
'constraints' => [new Length(min: 10, groups: ['group2'])],
])
->add('baz', TextType::class, [
'constraints' => [new NotBlank(['groups' => ['group3']])],
'constraints' => [new NotBlank(groups: ['group3'])],
])
;

Expand All @@ -214,13 +206,11 @@ public function testConstraintsInDifferentGroupsOnSingleField()
])
->add('foo', TextType::class, [
'constraints' => [
new NotBlank([
'groups' => ['group1'],
]),
new Length([
'groups' => ['group2'],
'max' => 3,
]),
new NotBlank(groups: ['group1']),
new Length(
groups: ['group2'],
max: 3,
),
],
]);
$form->submit([
Expand All @@ -242,13 +232,11 @@ public function testConstraintsInDifferentGroupsOnSingleFieldWithAdditionalField
->add('bar')
->add('foo', TextType::class, [
'constraints' => [
new NotBlank([
'groups' => ['group1'],
]),
new Length([
'groups' => ['group2'],
'max' => 3,
]),
new NotBlank(groups: ['group1']),
new Length(
groups: ['group2'],
max: 3,
),
],
]);
$form->submit([
Expand All @@ -268,11 +256,11 @@ public function testCascadeValidationToChildFormsUsingPropertyPaths()
'validation_groups' => ['group1', 'group2'],
])
->add('field1', null, [
'constraints' => [new NotBlank(['groups' => 'group1'])],
'constraints' => [new NotBlank(groups: ['group1'])],
'property_path' => '[foo]',
])
->add('field2', null, [
'constraints' => [new NotBlank(['groups' => 'group2'])],
'constraints' => [new NotBlank(groups: ['group2'])],
'property_path' => '[bar]',
])
;
Expand Down Expand Up @@ -359,11 +347,11 @@ public function testCascadeValidationToChildFormsUsingPropertyPathsValidatedInSe
'validation_groups' => new GroupSequence(['group1', 'group2']),
])
->add('field1', null, [
'constraints' => [new NotBlank(['groups' => 'group1'])],
'constraints' => [new NotBlank(groups: ['group1'])],
'property_path' => '[foo]',
])
->add('field2', null, [
'constraints' => [new NotBlank(['groups' => 'group2'])],
'constraints' => [new NotBlank(groups: ['group2'])],
'property_path' => '[bar]',
])
;
Expand All @@ -384,9 +372,7 @@ public function testContextIsPopulatedWithFormBeingValidated()
{
$form = $this->formFactory->create(FormType::class)
->add('field1', null, [
'constraints' => [new Expression([
'expression' => '!this.getParent().get("field2").getData()',
])],
'constraints' => [new Expression('!this.getParent().get("field2").getData()')],
])
->add('field2')
;
Expand All @@ -407,10 +393,10 @@ public function testContextIsPopulatedWithFormBeingValidatedUsingGroupSequence()
'validation_groups' => new GroupSequence(['group1']),
])
->add('field1', null, [
'constraints' => [new Expression([
'expression' => '!this.getParent().get("field2").getData()',
'groups' => ['group1'],
])],
'constraints' => [new Expression(
expression: '!this.getParent().get("field2").getData()',
groups: ['group1'],
)],
])
->add('field2')
;
Expand Down
Expand Up @@ -70,9 +70,9 @@ public function testValidate()
public function testValidateConstraints()
{
$object = new \stdClass();
$constraint1 = new NotNull(['groups' => ['group1', 'group2']]);
$constraint2 = new NotBlank(['groups' => 'group2']);
$constraint3 = new Length(['groups' => 'group2', 'min' => 3]);
$constraint1 = new NotNull(groups: ['group1', 'group2']);
$constraint2 = new NotBlank(groups: ['group2']);
$constraint3 = new Length(groups: ['group2'], min: 3);

$options = [
'validation_groups' => ['group1', 'group2'],
Expand Down Expand Up @@ -156,8 +156,8 @@ public function testMissingConstraintIndex()
public function testValidateConstraintsOptionEvenIfNoValidConstraint()
{
$object = new \stdClass();
$constraint1 = new NotNull(['groups' => ['group1', 'group2']]);
$constraint2 = new NotBlank(['groups' => 'group2']);
$constraint1 = new NotNull(groups: ['group1', 'group2']);
$constraint2 = new NotBlank(groups: ['group2']);

$parent = $this->getBuilder('parent', null)
->setCompound(true)
Expand Down Expand Up @@ -684,7 +684,7 @@ public function getValidationGroups(FormInterface $form)
public function testCauseForNotAllowedExtraFieldsIsTheFormConstraint()
{
$form = $this
->getBuilder('form', null, ['constraints' => [new NotBlank(['groups' => ['foo']])]])
->getBuilder('form', null, ['constraints' => [new NotBlank(groups: ['foo'])]])
->setCompound(true)
->setDataMapper(new DataMapper())
->getForm();
Expand Down
Expand Up @@ -84,8 +84,8 @@ public function testGroupSequenceWithConstraintsOption()
->create(FormTypeTest::TESTED_TYPE, null, ['validation_groups' => new GroupSequence(['First', 'Second'])])
->add('field', TextTypeTest::TESTED_TYPE, [
'constraints' => [
new Length(['min' => 10, 'groups' => ['First']]),
new NotBlank(['groups' => ['Second']]),
new Length(min: 10, groups: ['First']),
new NotBlank(groups: ['Second']),
],
])
;
Expand All @@ -102,7 +102,7 @@ public function testManyFieldsGroupSequenceWithConstraintsOption()
{
$formMetadata = new ClassMetadata(Form::class);
$authorMetadata = (new ClassMetadata(Author::class))
->addPropertyConstraint('firstName', new NotBlank(['groups' => 'Second']))
->addPropertyConstraint('firstName', new NotBlank(groups: ['Second']))
;
$metadataFactory = $this->createMock(MetadataFactoryInterface::class);
$metadataFactory->expects($this->any())
Expand Down Expand Up @@ -131,12 +131,12 @@ public function testManyFieldsGroupSequenceWithConstraintsOption()
->add('firstName', TextTypeTest::TESTED_TYPE)
->add('lastName', TextTypeTest::TESTED_TYPE, [
'constraints' => [
new Length(['min' => 10, 'groups' => ['First']]),
new Length(min: 10, groups: ['First']),
],
])
->add('australian', TextTypeTest::TESTED_TYPE, [
'constraints' => [
new NotBlank(['groups' => ['Second']]),
new NotBlank(groups: ['Second']),
],
])
;
Expand Down
Expand Up @@ -96,8 +96,8 @@ public static function guessRequiredProvider()
[new NotNull(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)],
[new NotBlank(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)],
[new IsTrue(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)],
[new Length(['min' => 10, 'max' => 10]), new ValueGuess(false, Guess::LOW_CONFIDENCE)],
[new Range(['min' => 1, 'max' => 20]), new ValueGuess(false, Guess::LOW_CONFIDENCE)],
[new Length(min: 10, max: 10), new ValueGuess(false, Guess::LOW_CONFIDENCE)],
[new Range(min: 1, max: 20), new ValueGuess(false, Guess::LOW_CONFIDENCE)],
];
}

Expand All @@ -122,7 +122,7 @@ public function testGuessRequiredReturnsFalseForUnmappedProperties()

public function testGuessMaxLengthForConstraintWithMaxValue()
{
$constraint = new Length(['max' => '2']);
$constraint = new Length(max: '2');

$result = $this->guesser->guessMaxLengthForConstraint($constraint);
$this->assertInstanceOf(ValueGuess::class, $result);
Expand All @@ -132,7 +132,7 @@ public function testGuessMaxLengthForConstraintWithMaxValue()

public function testGuessMaxLengthForConstraintWithMinValue()
{
$constraint = new Length(['min' => '2']);
$constraint = new Length(min: '2');

$result = $this->guesser->guessMaxLengthForConstraint($constraint);
$this->assertNull($result);
Expand All @@ -141,7 +141,7 @@ public function testGuessMaxLengthForConstraintWithMinValue()
public function testGuessMimeTypesForConstraintWithMimeTypesValue()
{
$mimeTypes = ['image/png', 'image/jpeg'];
$constraint = new File(['mimeTypes' => $mimeTypes]);
$constraint = new File(mimeTypes: $mimeTypes);
$typeGuess = $this->guesser->guessTypeForConstraint($constraint);
$this->assertInstanceOf(TypeGuess::class, $typeGuess);
$this->assertArrayHasKey('attr', $typeGuess->getOptions());
Expand All @@ -159,7 +159,7 @@ public function testGuessMimeTypesForConstraintWithoutMimeTypesValue()

public function testGuessMimeTypesForConstraintWithMimeTypesStringValue()
{
$constraint = new File(['mimeTypes' => 'image/*']);
$constraint = new File(mimeTypes: 'image/*');
$typeGuess = $this->guesser->guessTypeForConstraint($constraint);
$this->assertInstanceOf(TypeGuess::class, $typeGuess);
$this->assertArrayHasKey('attr', $typeGuess->getOptions());
Expand All @@ -169,7 +169,7 @@ public function testGuessMimeTypesForConstraintWithMimeTypesStringValue()

public function testGuessMimeTypesForConstraintWithMimeTypesEmptyStringValue()
{
$constraint = new File(['mimeTypes' => '']);
$constraint = new File(mimeTypes: '');
$typeGuess = $this->guesser->guessTypeForConstraint($constraint);
$this->assertInstanceOf(TypeGuess::class, $typeGuess);
$this->assertArrayNotHasKey('attr', $typeGuess->getOptions());
Expand Down
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Validator\Attribute\HasNamedArguments;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\LogicException;
Expand All @@ -28,9 +29,12 @@ abstract class AbstractComparison extends Constraint
public mixed $value = null;
public ?string $propertyPath = null;

#[HasNamedArguments]
public function __construct(mixed $value = null, ?string $propertyPath = null, ?string $message = null, ?array $groups = null, mixed $payload = null, array $options = [])
{
if (\is_array($value)) {
trigger_deprecation('symfony/validator', '7.2', 'Passing an array of options to configure the %s constraint is deprecated, use named arguments instead.', static::class);

$options = array_merge($value, $options);
} elseif (null !== $value) {
$options['value'] = $value;
Expand Down
6 changes: 6 additions & 0 deletions src/Symfony/Component/Validator/Constraints/Bic.php
Expand Up @@ -13,6 +13,7 @@

use Symfony\Component\Intl\Countries;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Validator\Attribute\HasNamedArguments;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\LogicException;
Expand Down Expand Up @@ -56,12 +57,17 @@ class Bic extends Constraint
* @param string|null $ibanPropertyPath Property path to the IBAN value when validating objects
* @param string[]|null $groups
*/
#[HasNamedArguments]
public function __construct(?array $options = null, ?string $message = null, ?string $iban = null, ?string $ibanPropertyPath = null, ?string $ibanMessage = null, ?array $groups = null, mixed $payload = null)
{
if (!class_exists(Countries::class)) {
throw new LogicException('The Intl component is required to use the Bic constraint. Try running "composer require symfony/intl".');
}

if (null !== $options && [] !== $options) {
trigger_deprecation('symfony/validator', '7.2', 'Passing an array of options to configure the %s constraint is deprecated, use named arguments instead.', static::class);
}

parent::__construct($options, $groups, $payload);

$this->message = $message ?? $this->message;
Expand Down
6 changes: 6 additions & 0 deletions src/Symfony/Component/Validator/Constraints/Blank.php
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Attribute\HasNamedArguments;
use Symfony\Component\Validator\Constraint;

/**
Expand All @@ -33,8 +34,13 @@ class Blank extends Constraint
* @param array<string,mixed>|null $options
* @param string[]|null $groups
*/
#[HasNamedArguments]
public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null)
{
if (null !== $options && [] !== $options) {
trigger_deprecation('symfony/validator', '7.2', 'Passing an array of options to configure the %s constraint is deprecated, use named arguments instead.', static::class);
}

parent::__construct($options ?? [], $groups, $payload);

$this->message = $message ?? $this->message;
Expand Down

0 comments on commit 0d1d920

Please sign in to comment.