diff --git a/UPGRADE-5.2.md b/UPGRADE-5.2.md new file mode 100644 index 0000000000000..f3a204fcce333 --- /dev/null +++ b/UPGRADE-5.2.md @@ -0,0 +1,30 @@ +UPGRADE FROM 5.1 to 5.2 +======================= + +Validator +--------- + + * Deprecated the `allowEmptyString` option of the `Length` constraint. + + Before: + + ```php + use Symfony\Component\Validator\Constraints as Assert; + + /** + * @Assert\Length(min=5, allowEmptyString=true) + */ + ``` + + After: + + ```php + use Symfony\Component\Validator\Constraints as Assert; + + /** + * @Assert\AtLeastOneOf({ + * @Assert\Blank(), + * @Assert\Length(min=5) + * }) + */ + ``` diff --git a/UPGRADE-6.0.md b/UPGRADE-6.0.md index 1d8243eff7d8a..0e3449d80bb9b 100644 --- a/UPGRADE-6.0.md +++ b/UPGRADE-6.0.md @@ -115,6 +115,34 @@ Security * Removed `DefaultLogoutSuccessHandler` in favor of `DefaultLogoutListener`. * Added a `logout(Request $request, Response $response, TokenInterface $token)` method to the `RememberMeServicesInterface`. +Validator +--------- + + * Removed the `allowEmptyString` option from the `Length` constraint. + + Before: + + ```php + use Symfony\Component\Validator\Constraints as Assert; + + /** + * @Assert\Length(min=5, allowEmptyString=true) + */ + ``` + + After: + + ```php + use Symfony\Component\Validator\Constraints as Assert; + + /** + * @Assert\AtLeastOneOf({ + * @Assert\Blank(), + * @Assert\Length(min=5) + * }) + */ + ``` + Yaml ---- diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DoctrineLoaderEntity.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DoctrineLoaderEntity.php index 8c0b348e3bf3a..d6aee2d18b0b1 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DoctrineLoaderEntity.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DoctrineLoaderEntity.php @@ -36,13 +36,13 @@ class DoctrineLoaderEntity extends DoctrineLoaderParentEntity /** * @ORM\Column(length=20) - * @Assert\Length(min=5, allowEmptyString=true) + * @Assert\Length(min=5) */ public $mergedMaxLength; /** * @ORM\Column(length=20) - * @Assert\Length(min=1, max=10, allowEmptyString=true) + * @Assert\Length(min=1, max=10) */ public $alreadyMappedMaxLength; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Resources/validator/BaseUser.xml b/src/Symfony/Bridge/Doctrine/Tests/Resources/validator/BaseUser.xml index 40b7a138d437b..bf64b92ca484d 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Resources/validator/BaseUser.xml +++ b/src/Symfony/Bridge/Doctrine/Tests/Resources/validator/BaseUser.xml @@ -13,7 +13,6 @@ - diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 598687e1a2607..4c90cc6316db8 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -67,7 +67,7 @@ public function testGroupSequenceWithConstraintsOption() ->create(FormTypeTest::TESTED_TYPE, null, (['validation_groups' => new GroupSequence(['First', 'Second'])])) ->add('field', TextTypeTest::TESTED_TYPE, [ 'constraints' => [ - new Length(['min' => 10, 'allowEmptyString' => true, 'groups' => ['First']]), + new Length(['min' => 10, 'groups' => ['First']]), new NotBlank(['groups' => ['Second']]), ], ]) @@ -83,8 +83,6 @@ public function testGroupSequenceWithConstraintsOption() public function testManyFieldsGroupSequenceWithConstraintsOption() { - $allowEmptyString = property_exists(Length::class, 'allowEmptyString') ? ['allowEmptyString' => true] : []; - $formMetadata = new ClassMetadata(Form::class); $authorMetadata = (new ClassMetadata(Author::class)) ->addPropertyConstraint('firstName', new NotBlank(['groups' => 'Second'])) @@ -116,7 +114,7 @@ public function testManyFieldsGroupSequenceWithConstraintsOption() ->add('firstName', TextTypeTest::TESTED_TYPE) ->add('lastName', TextTypeTest::TESTED_TYPE, [ 'constraints' => [ - new Length(['min' => 10, 'groups' => ['First']] + $allowEmptyString), + new Length(['min' => 10, 'groups' => ['First']]), ], ]) ->add('australian', TextTypeTest::TESTED_TYPE, [ diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php index 383b7556d51b8..cb9b93abdbf61 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php @@ -94,13 +94,11 @@ public function testFieldConstraintsInvalidateFormIfFieldIsSubmitted() public function testFieldsValidateInSequence() { - $allowEmptyString = property_exists(Length::class, 'allowEmptyString') ? ['allowEmptyString' => true] : []; - $form = $this->createForm(FormType::class, null, [ 'validation_groups' => new GroupSequence(['group1', 'group2']), ]) ->add('foo', TextType::class, [ - 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']] + $allowEmptyString)], + 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])], ]) ->add('bar', TextType::class, [ 'constraints' => [new NotBlank(['groups' => ['group2']])], @@ -117,16 +115,14 @@ public function testFieldsValidateInSequence() public function testFieldsValidateInSequenceWithNestedGroupsArray() { - $allowEmptyString = property_exists(Length::class, 'allowEmptyString') ? ['allowEmptyString' => true] : []; - $form = $this->createForm(FormType::class, null, [ 'validation_groups' => new GroupSequence([['group1', 'group2'], 'group3']), ]) ->add('foo', TextType::class, [ - 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']] + $allowEmptyString)], + 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])], ]) ->add('bar', TextType::class, [ - 'constraints' => [new Length(['min' => 10, 'groups' => ['group2']] + $allowEmptyString)], + 'constraints' => [new Length(['min' => 10, 'groups' => ['group2']])], ]) ->add('baz', TextType::class, [ 'constraints' => [new NotBlank(['groups' => ['group3']])], diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php index e96c8b60c3929..2b50c7cc2f063 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -66,7 +66,7 @@ public 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, 'allowEmptyString' => true]), 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)], ]; } @@ -102,7 +102,7 @@ public function testGuessMaxLengthForConstraintWithMaxValue() public function testGuessMaxLengthForConstraintWithMinValue() { - $constraint = new Length(['min' => '2', 'allowEmptyString' => true]); + $constraint = new Length(['min' => '2']); $result = $this->guesser->guessMaxLengthForConstraint($constraint); $this->assertNull($result); diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 9921ef6d4b495..df48d15b3ffe4 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -1,6 +1,34 @@ CHANGELOG ========= +5.2.0 +----- + + * deprecated the `allowEmptyString` option of the `Length` constraint + + Before: + + ```php + use Symfony\Component\Validator\Constraints as Assert; + + /** + * @Assert\Length(min=5, allowEmptyString=true) + */ + ``` + + After: + + ```php + use Symfony\Component\Validator\Constraints as Assert; + + /** + * @Assert\AtLeastOneOf({ + * @Assert\Blank(), + * @Assert\Length(min=5) + * }) + */ + ``` + 5.1.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/Length.php b/src/Symfony/Component/Validator/Constraints/Length.php index d3404277bef05..3daebf8ff1985 100644 --- a/src/Symfony/Component/Validator/Constraints/Length.php +++ b/src/Symfony/Component/Validator/Constraints/Length.php @@ -64,5 +64,9 @@ public function __construct($options = null) if (null !== $this->normalizer && !\is_callable($this->normalizer)) { throw new InvalidArgumentException(sprintf('The "normalizer" option must be a valid callable ("%s" given).', get_debug_type($this->normalizer))); } + + if (isset($options['allowEmptyString'])) { + trigger_deprecation('symfony/validator', '5.2', sprintf('The "allowEmptyString" option of the "%s" constraint is deprecated.', self::class)); + } } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LengthTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LengthTest.php index b0caef17c9e31..c1c9d60d8bbad 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LengthTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LengthTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Validator\Constraints\Length; /** @@ -19,6 +20,8 @@ */ class LengthTest extends TestCase { + use ExpectDeprecationTrait; + public function testNormalizerCanBeSet() { $length = new Length(['min' => 0, 'max' => 10, 'normalizer' => 'trim']); @@ -39,4 +42,23 @@ public function testInvalidNormalizerObjectThrowsException() $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("stdClass" given).'); new Length(['min' => 0, 'max' => 10, 'normalizer' => new \stdClass()]); } + + /** + * @group legacy + * @dataProvider allowEmptyStringOptionData + */ + public function testDeprecatedAllowEmptyStringOption(bool $value) + { + $this->expectDeprecation('Since symfony/validator 5.2: The "allowEmptyString" option of the "Symfony\Component\Validator\Constraints\Length" constraint is deprecated.'); + + new Length(['allowEmptyString' => $value, 'max' => 5]); + } + + public function allowEmptyStringOptionData() + { + return [ + [true], + [false], + ]; + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php index d7969afc565e4..584f1e4ae3c8a 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php @@ -29,6 +29,9 @@ public function testNullIsValid() $this->assertNoViolation(); } + /** + * @group legacy + */ public function testAllowEmptyString() { $this->validator->validate('', new Length(['value' => 6, 'allowEmptyString' => true])); diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index ad9a81eaba8ae..9e2a5f752bd55 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -17,6 +17,7 @@ ], "require": { "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php80": "^1.15",