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 28, 2024
1 parent f738888 commit e58d5f9
Show file tree
Hide file tree
Showing 156 changed files with 2,350 additions and 1,924 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ public function testFieldConstraintsInvalidateFormIfFieldIsSubmitted()
public function testNonCompositeConstraintValidatedOnce()
{
$form = $this->formFactory->create(TextType::class, null, [
'constraints' => [new NotBlank(['groups' => ['foo', 'bar']])],
'validation_groups' => ['foo', 'bar'],
]);
'constraints' => [new NotBlank(groups: ['foo', 'bar'])],
'validation_groups' => ['foo', 'bar'],
]);
$form->submit('');

$violations = $this->validator->validate($form);
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
Original file line number Diff line number Diff line change
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 All @@ -184,8 +184,8 @@ public function testDontValidateIfNoValidationGroups()
$object = new \stdClass();

$form = $this->getBuilder('name', '\stdClass', [
'validation_groups' => [],
])
'validation_groups' => [],
])
->setData($object)
->setCompound(true)
->setDataMapper(new DataMapper())
Expand Down Expand Up @@ -256,12 +256,12 @@ public function testDontValidateIfNotSynchronized()
$object = new \stdClass();

$form = $this->getBuilder('name', '\stdClass', [
'invalid_message' => 'invalid_message_key',
// Invalid message parameters must be supported, because the
// invalid message can be a translation key
// see https://github.com/symfony/symfony/issues/5144
'invalid_message_parameters' => ['{{ foo }}' => 'bar'],
])
'invalid_message' => 'invalid_message_key',
// Invalid message parameters must be supported, because the
// invalid message can be a translation key
// see https://github.com/symfony/symfony/issues/5144
'invalid_message_parameters' => ['{{ foo }}' => 'bar'],
])
->setData($object)
->addViewTransformer(new CallbackTransformer(
static fn ($data) => $data,
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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

0 comments on commit e58d5f9

Please sign in to comment.