From 8622b2aad3a79f5705dc9bf22c91054f73ff8207 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Jun 2025 16:08:14 +0200 Subject: [PATCH 01/57] Allow Symfony ^8.0 --- composer.json | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index 0eaac5f6b..899808727 100644 --- a/composer.json +++ b/composer.json @@ -24,23 +24,23 @@ "symfony/translation-contracts": "^2.5|^3" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/cache": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/string": "^6.4|^7.0", - "symfony/translation": "^6.4.3|^7.0.3", - "symfony/type-info": "^7.1", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/translation": "^6.4.3|^7.0.3|^8.0", + "symfony/type-info": "^7.1|^8.0", "egulias/email-validator": "^2.1.10|^3|^4" }, "conflict": { From 0766a1ce1f866ef201975b48445cf1f52c7052ce Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Jun 2025 17:50:55 +0200 Subject: [PATCH 02/57] Bump Symfony 8 to PHP >= 8.4 --- composer.json | 52 ++++++++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/composer.json b/composer.json index 899808727..ab0d10daa 100644 --- a/composer.json +++ b/composer.json @@ -16,43 +16,35 @@ } ], "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php83": "^1.27", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.0", "symfony/translation-contracts": "^2.5|^3" }, "require-dev": { - "symfony/console": "^6.4|^7.0|^8.0", - "symfony/finder": "^6.4|^7.0|^8.0", - "symfony/http-client": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/http-kernel": "^6.4|^7.0|^8.0", - "symfony/intl": "^6.4|^7.0|^8.0", - "symfony/yaml": "^6.4|^7.0|^8.0", - "symfony/config": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/cache": "^6.4|^7.0|^8.0", - "symfony/mime": "^6.4|^7.0|^8.0", - "symfony/property-access": "^6.4|^7.0|^8.0", - "symfony/property-info": "^6.4|^7.0|^8.0", - "symfony/string": "^6.4|^7.0|^8.0", - "symfony/translation": "^6.4.3|^7.0.3|^8.0", - "symfony/type-info": "^7.1|^8.0", - "egulias/email-validator": "^2.1.10|^3|^4" + "egulias/email-validator": "^2.1.10|^3|^4", + "symfony/cache": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/property-info": "^7.4|^8.0", + "symfony/string": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/type-info": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" }, "conflict": { "doctrine/lexer": "<1.1", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<7.0", - "symfony/expression-language": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/intl": "<6.4", - "symfony/property-info": "<6.4", - "symfony/translation": "<6.4.3|>=7.0,<7.0.3", - "symfony/yaml": "<6.4" + "symfony/doctrine-bridge": "<7.4" }, "autoload": { "psr-4": { "Symfony\\Component\\Validator\\": "" }, From a39ece78f1de00cd521011c171e2e4312d8bdb28 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 3 Jun 2025 17:41:25 +0200 Subject: [PATCH 03/57] Remove deadcode after the bump to PHP >= 8.4 --- Constraints/NoSuspiciousCharactersValidator.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Constraints/NoSuspiciousCharactersValidator.php b/Constraints/NoSuspiciousCharactersValidator.php index 0b7a78ef9..d82a62d57 100644 --- a/Constraints/NoSuspiciousCharactersValidator.php +++ b/Constraints/NoSuspiciousCharactersValidator.php @@ -99,17 +99,7 @@ public function validate(mixed $value, Constraint $constraint): void } foreach (self::CHECK_ERROR as $check => $error) { - if (\PHP_VERSION_ID < 80204) { - if (!($checks & $check)) { - continue; - } - - $checker->setChecks($check); - - if (!$checker->isSuspicious($value)) { - continue; - } - } elseif (!($errorCode & $check)) { + if (!($errorCode & $check)) { continue; } From 981ef58db66dc6e951a56863d75f164fae889bfb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 4 Jun 2025 18:31:05 +0200 Subject: [PATCH 04/57] Enforce return types on all components --- ConstraintValidatorInterface.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ConstraintValidatorInterface.php b/ConstraintValidatorInterface.php index fe7da2e8f..68faace61 100644 --- a/ConstraintValidatorInterface.php +++ b/ConstraintValidatorInterface.php @@ -20,15 +20,11 @@ interface ConstraintValidatorInterface { /** * Initializes the constraint validator. - * - * @return void */ - public function initialize(ExecutionContextInterface $context); + public function initialize(ExecutionContextInterface $context): void; /** * Checks if the passed value is valid. - * - * @return void */ - public function validate(mixed $value, Constraint $constraint); + public function validate(mixed $value, Constraint $constraint): void; } From 042e49c91286d5494c9268a2689dcb7e3ccdca11 Mon Sep 17 00:00:00 2001 From: Mathias Arlaud Date: Mon, 2 Jun 2025 16:22:00 +0200 Subject: [PATCH 05/57] [PropertyInfo] Remove deprecated code --- Mapping/Loader/PropertyInfoLoader.php | 142 +++--------------- .../Mapping/Loader/PropertyInfoLoaderTest.php | 35 ----- 2 files changed, 22 insertions(+), 155 deletions(-) diff --git a/Mapping/Loader/PropertyInfoLoader.php b/Mapping/Loader/PropertyInfoLoader.php index 57d65696e..6e6199153 100644 --- a/Mapping/Loader/PropertyInfoLoader.php +++ b/Mapping/Loader/PropertyInfoLoader.php @@ -14,7 +14,6 @@ use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; -use Symfony\Component\PropertyInfo\Type as PropertyInfoType; use Symfony\Component\TypeInfo\Type as TypeInfoType; use Symfony\Component\TypeInfo\Type\BuiltinType; use Symfony\Component\TypeInfo\Type\CollectionType; @@ -67,8 +66,8 @@ public function loadClassMetadata(ClassMetadata $metadata): bool continue; } - $types = $this->getPropertyTypes($className, $property); - if (null === $types) { + $type = $this->typeExtractor->getType($className, $property); + if (null === $type) { continue; } @@ -106,71 +105,36 @@ public function loadClassMetadata(ClassMetadata $metadata): bool $loaded = true; - // BC layer for PropertyTypeExtractorInterface::getTypes(). - // Can be removed as soon as PropertyTypeExtractorInterface::getTypes() is removed (8.0). - if (\is_array($types)) { - $builtinTypes = []; - $nullable = false; - $scalar = true; - - foreach ($types as $type) { - $builtinTypes[] = $type->getBuiltinType(); - - if ($scalar && !\in_array($type->getBuiltinType(), ['int', 'float', 'string', 'bool'], true)) { - $scalar = false; - } - - if (!$nullable && $type->isNullable()) { - $nullable = true; - } - } + if ($hasTypeConstraint) { + continue; + } - if (!$hasTypeConstraint) { - if (1 === \count($builtinTypes)) { - if ($types[0]->isCollection() && \count($collectionValueType = $types[0]->getCollectionValueTypes()) > 0) { - [$collectionValueType] = $collectionValueType; - $this->handleAllConstraintLegacy($property, $allConstraint, $collectionValueType, $metadata); - } + // BC layer for type-info < 7.2 + if (!class_exists(NullableType::class)) { + $nullable = false; - $metadata->addPropertyConstraint($property, $this->getTypeConstraintLegacy($builtinTypes[0], $types[0])); - } elseif ($scalar) { - $metadata->addPropertyConstraint($property, new Type(type: 'scalar')); - } + if ($type instanceof UnionType && $type->isNullable()) { + $nullable = true; + $type = $type->asNonNullable(); } } else { - if ($hasTypeConstraint) { - continue; - } - - $type = $types; - - // BC layer for type-info < 7.2 - if (!class_exists(NullableType::class)) { - $nullable = false; - - if ($type instanceof UnionType && $type->isNullable()) { - $nullable = true; - $type = $type->asNonNullable(); - } - } else { - $nullable = $type->isNullable(); - - if ($type instanceof NullableType) { - $type = $type->getWrappedType(); - } - } + $nullable = $type->isNullable(); if ($type instanceof NullableType) { $type = $type->getWrappedType(); } + } - if ($type instanceof CollectionType) { - $this->handleAllConstraint($property, $allConstraint, $type->getCollectionValueType(), $metadata); - } + if ($type instanceof NullableType) { + $type = $type->getWrappedType(); + } - if (null !== $typeConstraint = $this->getTypeConstraint($type)) { - $metadata->addPropertyConstraint($property, $typeConstraint); - } + if ($type instanceof CollectionType) { + $this->handleAllConstraint($property, $allConstraint, $type->getCollectionValueType(), $metadata); + } + + if (null !== $typeConstraint = $this->getTypeConstraint($type)) { + $metadata->addPropertyConstraint($property, $typeConstraint); } if (!$nullable && !$hasNotBlankConstraint && !$hasNotNullConstraint) { @@ -181,34 +145,6 @@ public function loadClassMetadata(ClassMetadata $metadata): bool return $loaded; } - /** - * BC layer for PropertyTypeExtractorInterface::getTypes(). - * Can be removed as soon as PropertyTypeExtractorInterface::getTypes() is removed (8.0). - * - * @return TypeInfoType|list|null - */ - private function getPropertyTypes(string $className, string $property): TypeInfoType|array|null - { - if (class_exists(TypeInfoType::class) && method_exists($this->typeExtractor, 'getType')) { - return $this->typeExtractor->getType($className, $property); - } - - return $this->typeExtractor->getTypes($className, $property); - } - - /** - * BC layer for PropertyTypeExtractorInterface::getTypes(). - * Can be removed as soon as PropertyTypeExtractorInterface::getTypes() is removed (8.0). - */ - private function getTypeConstraintLegacy(string $builtinType, PropertyInfoType $type): Type - { - if (PropertyInfoType::BUILTIN_TYPE_OBJECT === $builtinType && null !== $className = $type->getClassName()) { - return new Type(type: $className); - } - - return new Type(type: $builtinType); - } - private function getTypeConstraint(TypeInfoType $type): ?Type { // BC layer for type-info < 7.2 @@ -289,38 +225,4 @@ private function handleAllConstraint(string $property, ?All $allConstraint, Type $allConstraint->constraints = array_merge($allConstraint->constraints, $constraints); } } - - /** - * BC layer for PropertyTypeExtractorInterface::getTypes(). - * Can be removed as soon as PropertyTypeExtractorInterface::getTypes() is removed (8.0). - */ - private function handleAllConstraintLegacy(string $property, ?All $allConstraint, PropertyInfoType $propertyInfoType, ClassMetadata $metadata): void - { - $containsTypeConstraint = false; - $containsNotNullConstraint = false; - if (null !== $allConstraint) { - foreach ($allConstraint->constraints as $constraint) { - if ($constraint instanceof Type) { - $containsTypeConstraint = true; - } elseif ($constraint instanceof NotNull) { - $containsNotNullConstraint = true; - } - } - } - - $constraints = []; - if (!$containsNotNullConstraint && !$propertyInfoType->isNullable()) { - $constraints[] = new NotNull(); - } - - if (!$containsTypeConstraint) { - $constraints[] = $this->getTypeConstraintLegacy($propertyInfoType->getBuiltinType(), $propertyInfoType); - } - - if (null === $allConstraint) { - $metadata->addPropertyConstraint($property, new All(constraints: $constraints)); - } else { - $allConstraint->constraints = array_merge($allConstraint->constraints, $constraints); - } - } } diff --git a/Tests/Mapping/Loader/PropertyInfoLoaderTest.php b/Tests/Mapping/Loader/PropertyInfoLoaderTest.php index ae5253a3f..6b4b40b7a 100644 --- a/Tests/Mapping/Loader/PropertyInfoLoaderTest.php +++ b/Tests/Mapping/Loader/PropertyInfoLoaderTest.php @@ -15,7 +15,6 @@ use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; -use Symfony\Component\PropertyInfo\Type as LegacyType; use Symfony\Component\TypeInfo\Type; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Iban; @@ -62,7 +61,6 @@ public function testLoadClassMetadata() private int $i = 0; private int $j = 0; private array $types; - private array $legacyTypes; public function getType(string $class, string $property, array $context = []): ?Type { @@ -86,29 +84,6 @@ public function getType(string $class, string $property, array $context = []): ? return $type; } - - public function getTypes(string $class, string $property, array $context = []): ?array - { - $this->legacyTypes ??= [ - [new LegacyType('string', true)], - [new LegacyType('string')], - [new LegacyType('string', true), new LegacyType('int'), new LegacyType('bool')], - [new LegacyType('object', true, Entity::class)], - [new LegacyType('array', true, null, true, null, new LegacyType('object', false, Entity::class))], - [new LegacyType('array', true, null, true)], - [new LegacyType('float', true)], // The existing constraint is float - [new LegacyType('string', true)], - [new LegacyType('string', true)], - [new LegacyType('array', true, null, true, null, new LegacyType('float'))], - [new LegacyType('string')], - [new LegacyType('string')], - ]; - - $legacyType = $this->legacyTypes[$this->j]; - ++$this->j; - - return $legacyType; - } }; $propertyAccessExtractor = $this->createMock(PropertyAccessExtractorInterface::class); @@ -240,11 +215,6 @@ public function getType(string $class, string $property, array $context = []): ? { return Type::string(); } - - public function getTypes(string $class, string $property, array $context = []): ?array - { - return [new LegacyType('string')]; - } }; $propertyAccessExtractor = $this->createMock(PropertyAccessExtractorInterface::class); @@ -279,11 +249,6 @@ public function getType(string $class, string $property, array $context = []): ? { return Type::string(); } - - public function getTypes(string $class, string $property, array $context = []): ?array - { - return [new LegacyType('string')]; - } }; } From fc7db30be7f0e4e2e035263668b19e353f73281d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 6 Jun 2025 23:15:51 +0200 Subject: [PATCH 06/57] require PropertyInfo 8.0+ in the Doctrine bridge --- .../Mapping/Loader/PropertyInfoLoaderTest.php | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Tests/Mapping/Loader/PropertyInfoLoaderTest.php b/Tests/Mapping/Loader/PropertyInfoLoaderTest.php index 6b4b40b7a..ae5253a3f 100644 --- a/Tests/Mapping/Loader/PropertyInfoLoaderTest.php +++ b/Tests/Mapping/Loader/PropertyInfoLoaderTest.php @@ -15,6 +15,7 @@ use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\PropertyInfo\Type as LegacyType; use Symfony\Component\TypeInfo\Type; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Iban; @@ -61,6 +62,7 @@ public function testLoadClassMetadata() private int $i = 0; private int $j = 0; private array $types; + private array $legacyTypes; public function getType(string $class, string $property, array $context = []): ?Type { @@ -84,6 +86,29 @@ public function getType(string $class, string $property, array $context = []): ? return $type; } + + public function getTypes(string $class, string $property, array $context = []): ?array + { + $this->legacyTypes ??= [ + [new LegacyType('string', true)], + [new LegacyType('string')], + [new LegacyType('string', true), new LegacyType('int'), new LegacyType('bool')], + [new LegacyType('object', true, Entity::class)], + [new LegacyType('array', true, null, true, null, new LegacyType('object', false, Entity::class))], + [new LegacyType('array', true, null, true)], + [new LegacyType('float', true)], // The existing constraint is float + [new LegacyType('string', true)], + [new LegacyType('string', true)], + [new LegacyType('array', true, null, true, null, new LegacyType('float'))], + [new LegacyType('string')], + [new LegacyType('string')], + ]; + + $legacyType = $this->legacyTypes[$this->j]; + ++$this->j; + + return $legacyType; + } }; $propertyAccessExtractor = $this->createMock(PropertyAccessExtractorInterface::class); @@ -215,6 +240,11 @@ public function getType(string $class, string $property, array $context = []): ? { return Type::string(); } + + public function getTypes(string $class, string $property, array $context = []): ?array + { + return [new LegacyType('string')]; + } }; $propertyAccessExtractor = $this->createMock(PropertyAccessExtractorInterface::class); @@ -249,6 +279,11 @@ public function getType(string $class, string $property, array $context = []): ? { return Type::string(); } + + public function getTypes(string $class, string $property, array $context = []): ?array + { + return [new LegacyType('string')]; + } }; } From 04c451b35fd47412b1209befd82804d13f6e9da3 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Fri, 27 Jun 2025 22:34:39 +0200 Subject: [PATCH 07/57] [Validator] Remove deprecated `INVALID_BANK_CODE_ERROR` constant --- CHANGELOG.md | 5 +++++ Constraints/Bic.php | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8146d2a5..cbda4981d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +8.0 +--- + + * Remove `Bic::INVALID_BANK_CODE_ERROR` constant. This error code was not used in the Bic constraint validator anymore. + 7.3 --- diff --git a/Constraints/Bic.php b/Constraints/Bic.php index 5390d5556..53ef941fa 100644 --- a/Constraints/Bic.php +++ b/Constraints/Bic.php @@ -39,10 +39,6 @@ class Bic extends Constraint public const INVALID_LENGTH_ERROR = '66dad313-af0b-4214-8566-6c799be9789c'; public const INVALID_CHARACTERS_ERROR = 'f424c529-7add-4417-8f2d-4b656e4833e2'; - /** - * @deprecated since Symfony 7.1, to be removed in 8.0 - */ - public const INVALID_BANK_CODE_ERROR = '00559357-6170-4f29-aebd-d19330aa19cf'; public const INVALID_COUNTRY_CODE_ERROR = '1ce76f8d-3c1f-451c-9e62-fe9c3ed486ae'; public const INVALID_CASE_ERROR = '11884038-3312-4ae5-9d04-699f782130c7'; public const INVALID_IBAN_COUNTRY_CODE_ERROR = '29a2c3bb-587b-4996-b6f5-53081364cea5'; @@ -50,7 +46,6 @@ class Bic extends Constraint protected const ERROR_NAMES = [ self::INVALID_LENGTH_ERROR => 'INVALID_LENGTH_ERROR', self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR', - self::INVALID_BANK_CODE_ERROR => 'INVALID_BANK_CODE_ERROR', self::INVALID_COUNTRY_CODE_ERROR => 'INVALID_COUNTRY_CODE_ERROR', self::INVALID_CASE_ERROR => 'INVALID_CASE_ERROR', ]; From b6fd31cbfe78b7e761ef9c97c9f98fb3097e05a5 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 9 Jun 2025 12:37:44 +0200 Subject: [PATCH 08/57] deprecate handling options in the base Constraint class --- CHANGELOG.md | 127 ++++++++++++++++ Constraint.php | 17 +++ Constraints/AbstractComparison.php | 10 +- Constraints/All.php | 16 +- Constraints/AtLeastOneOf.php | 13 +- Constraints/Blank.php | 2 +- Constraints/Callback.php | 9 +- Constraints/CardScheme.php | 13 +- Constraints/Cascade.php | 8 +- Constraints/Choice.php | 12 +- Constraints/Collection.php | 9 +- Constraints/Composite.php | 4 + Constraints/Count.php | 2 - Constraints/CssColor.php | 13 +- Constraints/DateTime.php | 10 +- Constraints/Existence.php | 14 ++ Constraints/Expression.php | 13 +- Constraints/IsFalse.php | 2 +- Constraints/IsNull.php | 2 +- Constraints/IsTrue.php | 2 +- Constraints/Isbn.php | 15 +- Constraints/Length.php | 2 - Constraints/NotBlank.php | 2 +- Constraints/NotNull.php | 2 +- Constraints/PasswordStrength.php | 6 +- Constraints/Regex.php | 12 +- Constraints/Sequentially.php | 13 +- Constraints/Timezone.php | 10 +- Constraints/Traverse.php | 9 +- Constraints/Type.php | 12 +- Constraints/Valid.php | 2 +- Constraints/When.php | 22 +-- Tests/ConstraintTest.php | 138 +++++++++++++++--- Tests/Constraints/ChoiceTest.php | 3 + Tests/Constraints/CompositeTest.php | 47 ++---- Tests/Constraints/CompoundTest.php | 6 + Tests/Fixtures/ConstraintA.php | 6 +- .../ConstraintWithRequiredArgument.php | 2 +- Tests/Fixtures/LegacyConstraintA.php | 31 ++++ Tests/Mapping/ClassMetadataTest.php | 50 +++---- .../Fixtures/ConstraintWithNamedArguments.php | 2 +- ...nstraintWithoutValueWithNamedArguments.php | 2 +- Tests/Mapping/MemberMetadataTest.php | 10 +- 43 files changed, 530 insertions(+), 172 deletions(-) create mode 100644 Tests/Fixtures/LegacyConstraintA.php diff --git a/CHANGELOG.md b/CHANGELOG.md index e8146d2a5..8d1fc55e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,133 @@ CHANGELOG ========= +7.4 +--- + + * Deprecate evaluating options in the base `Constraint` class. Initialize properties in the constructor of the concrete constraint + class instead. + + Before: + + ```php + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + public function __construct(?array $options = null) + { + parent::__construct($options); + } + } + ``` + + After: + + ```php + use Symfony\Component\Validator\Attribute\HasNamedArguments; + + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + #[HasNamedArguments] + public function __construct($option1 = null, $option2 = null, ?array $groups = null, mixed $payload = null) + { + parent::__construct(null, $groups, $payload); + + $this->option1 = $option1; + $this->option2 = $option2; + } + } + ``` + + * Deprecate the `getRequiredOptions()` method of the base `Constraint` class. Use mandatory constructor arguments instead. + + Before: + + ```php + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + public function __construct(?array $options = null) + { + parent::__construct($options); + } + + public function getRequiredOptions() + { + return ['option1']; + } + } + ``` + + After: + + ```php + use Symfony\Component\Validator\Attribute\HasNamedArguments; + + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + #[HasNamedArguments] + public function __construct($option1, $option2 = null, ?array $groups = null, mixed $payload = null) + { + parent::__construct(null, $groups, $payload); + + $this->option1 = $option1; + $this->option2 = $option2; + } + } + ``` + * Deprecate the `normalizeOptions()` and `getDefaultOption()` methods of the base `Constraint` class without replacements. + Overriding them in child constraint will not have any effects starting with Symfony 8.0. + * Deprecate passing an array of options to the `Composite` constraint class. Initialize the properties referenced with `getNestedConstraints()` + in child classes before calling the constructor of `Composite`. + + Before: + + ```php + class CustomCompositeConstraint extends Composite + { + public array $constraints = []; + + public function __construct(?array $options = null) + { + parent::__construct($options); + } + + protected function getCompositeOption(): string + { + return 'constraints'; + } + } + ``` + + After: + + ```php + use Symfony\Component\Validator\Attribute\HasNamedArguments; + + class CustomCompositeConstraint extends Composite + { + public array $constraints = []; + + #[HasNamedArguments] + public function __construct(array $constraints, ?array $groups = null, mixed $payload = null) + { + $this->constraints = $constraints; + + parent::__construct(null, $groups, $payload); + } + } + ``` + 7.3 --- diff --git a/Constraint.php b/Constraint.php index 5fd8ce84c..42ed471c6 100644 --- a/Constraint.php +++ b/Constraint.php @@ -110,6 +110,17 @@ public function __construct(mixed $options = null, ?array $groups = null, mixed { unset($this->groups); // enable lazy initialization + if (null === $options && (\func_num_args() > 0 || (new \ReflectionMethod($this, 'getRequiredOptions'))->getDeclaringClass()->getName() === self::class)) { + if (null !== $groups) { + $this->groups = $groups; + } + $this->payload = $payload; + + return; + } + + trigger_deprecation('symfony/validator', '7.4', 'Support for evaluating options in the base Constraint class is deprecated. Initialize properties in the constructor of %s instead.', static::class); + $options = $this->normalizeOptions($options); if (null !== $groups) { $options['groups'] = $groups; @@ -122,6 +133,8 @@ public function __construct(mixed $options = null, ?array $groups = null, mixed } /** + * @deprecated since Symfony 7.4 + * * @return array */ protected function normalizeOptions(mixed $options): array @@ -241,6 +254,8 @@ public function addImplicitGroupName(string $group): void * * Override this method to define a default option. * + * @deprecated since Symfony 7.4 + * * @see __construct() */ public function getDefaultOption(): ?string @@ -255,6 +270,8 @@ public function getDefaultOption(): ?string * * @return string[] * + * @deprecated since Symfony 7.4 + * * @see __construct() */ public function getRequiredOptions(): array diff --git a/Constraints/AbstractComparison.php b/Constraints/AbstractComparison.php index 3830da789..523a81296 100644 --- a/Constraints/AbstractComparison.php +++ b/Constraints/AbstractComparison.php @@ -39,16 +39,15 @@ public function __construct(mixed $value = null, ?string $propertyPath = null, ? } elseif (null !== $value) { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; - } - $options['value'] = $value; + $options['value'] = $value; + } } parent::__construct($options, $groups, $payload); $this->message = $message ?? $this->message; + $this->value = $value ?? $this->value; $this->propertyPath = $propertyPath ?? $this->propertyPath; if (null === $this->value && null === $this->propertyPath) { @@ -64,6 +63,9 @@ public function __construct(mixed $value = null, ?string $propertyPath = null, ? } } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'value'; diff --git a/Constraints/All.php b/Constraints/All.php index 92ded329b..b1a477782 100644 --- a/Constraints/All.php +++ b/Constraints/All.php @@ -32,18 +32,28 @@ class All extends Composite #[HasNamedArguments] public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($constraints) && !array_is_list($constraints)) { + if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - parent::__construct($constraints ?? [], $groups, $payload); + parent::__construct($constraints, $groups, $payload); + } else { + $this->constraints = $constraints; + + parent::__construct(null, $groups, $payload); + } } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'constraints'; } + /** + * @deprecated since Symfony 7.4 + */ public function getRequiredOptions(): array { return ['constraints']; diff --git a/Constraints/AtLeastOneOf.php b/Constraints/AtLeastOneOf.php index 20d55f458..c988726ae 100644 --- a/Constraints/AtLeastOneOf.php +++ b/Constraints/AtLeastOneOf.php @@ -43,22 +43,31 @@ class AtLeastOneOf extends Composite #[HasNamedArguments] public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null, ?string $message = null, ?string $messageCollection = null, ?bool $includeInternalMessages = null) { - if (\is_array($constraints) && !array_is_list($constraints)) { + if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + $options = $constraints; + } else { + $this->constraints = $constraints; } - parent::__construct($constraints ?? [], $groups, $payload); + parent::__construct($options ?? null, $groups, $payload); $this->message = $message ?? $this->message; $this->messageCollection = $messageCollection ?? $this->messageCollection; $this->includeInternalMessages = $includeInternalMessages ?? $this->includeInternalMessages; } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'constraints'; } + /** + * @deprecated since Symfony 7.4 + */ public function getRequiredOptions(): array { return ['constraints']; diff --git a/Constraints/Blank.php b/Constraints/Blank.php index 72fbae57a..cc0f648b2 100644 --- a/Constraints/Blank.php +++ b/Constraints/Blank.php @@ -41,7 +41,7 @@ public function __construct(?array $options = null, ?string $message = null, ?ar trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - parent::__construct($options ?? [], $groups, $payload); + parent::__construct($options, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/Callback.php b/Constraints/Callback.php index 44b51ac2a..3afe2a1a5 100644 --- a/Constraints/Callback.php +++ b/Constraints/Callback.php @@ -44,11 +44,7 @@ public function __construct(array|string|callable|null $callback = null, ?array if (!\is_array($callback) || (!isset($callback['callback']) && !isset($callback['groups']) && !isset($callback['payload']))) { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; } - - $options['callback'] = $callback; } else { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); @@ -56,8 +52,13 @@ public function __construct(array|string|callable|null $callback = null, ?array } parent::__construct($options, $groups, $payload); + + $this->callback = $callback ?? $this->callback; } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'callback'; diff --git a/Constraints/CardScheme.php b/Constraints/CardScheme.php index a75e9f7ab..7d2b76951 100644 --- a/Constraints/CardScheme.php +++ b/Constraints/CardScheme.php @@ -62,23 +62,28 @@ public function __construct(array|string|null $schemes, ?string $message = null, } else { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; - } - $options['value'] = $schemes; + $options['value'] = $schemes; + } } parent::__construct($options, $groups, $payload); + $this->schemes = $schemes ?? $this->schemes; $this->message = $message ?? $this->message; } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'schemes'; } + /** + * @deprecated since Symfony 7.4 + */ public function getRequiredOptions(): array { return ['schemes']; diff --git a/Constraints/Cascade.php b/Constraints/Cascade.php index 7d90cfcf7..97ecdf655 100644 --- a/Constraints/Cascade.php +++ b/Constraints/Cascade.php @@ -37,19 +37,23 @@ public function __construct(array|string|null $exclude = null, ?array $options = $options = array_merge($exclude, $options ?? []); $options['exclude'] = array_flip((array) ($options['exclude'] ?? [])); + $exclude = $options['exclude'] ?? null; } else { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - $this->exclude = array_flip((array) $exclude); + $exclude = array_flip((array) $exclude); + $this->exclude = $exclude; } if (\is_array($options) && \array_key_exists('groups', $options)) { throw new ConstraintDefinitionException(\sprintf('The option "groups" is not supported by the constraint "%s".', __CLASS__)); } - parent::__construct($options); + parent::__construct($options, null, $options['payload'] ?? null); + + $this->exclude = $exclude ?? $this->exclude; } public function getTargets(): string|array diff --git a/Constraints/Choice.php b/Constraints/Choice.php index 1435a762b..3849bbf17 100644 --- a/Constraints/Choice.php +++ b/Constraints/Choice.php @@ -45,6 +45,9 @@ class Choice extends Constraint public string $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.'; public bool $match = true; + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'choices'; @@ -62,7 +65,7 @@ public function getDefaultOption(): ?string */ #[HasNamedArguments] public function __construct( - string|array $options = [], + string|array|null $options = null, ?array $choices = null, callable|string|null $callback = null, ?bool $multiple = null, @@ -79,17 +82,14 @@ public function __construct( ) { if (\is_array($options) && $options && array_is_list($options)) { $choices ??= $options; - $options = []; + $options = null; } elseif (\is_array($options) && [] !== $options) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - if (null !== $choices) { - $options['value'] = $choices; - } - parent::__construct($options, $groups, $payload); + $this->choices = $choices ?? $this->choices; $this->callback = $callback ?? $this->callback; $this->multiple = $multiple ?? $this->multiple; $this->strict = $strict ?? $this->strict; diff --git a/Constraints/Collection.php b/Constraints/Collection.php index eca5a4eee..c0fc237f0 100644 --- a/Constraints/Collection.php +++ b/Constraints/Collection.php @@ -46,12 +46,14 @@ class Collection extends Composite public function __construct(mixed $fields = null, ?array $groups = null, mixed $payload = null, ?bool $allowExtraFields = null, ?bool $allowMissingFields = null, ?string $extraFieldsMessage = null, ?string $missingFieldsMessage = null) { if (self::isFieldsOption($fields)) { - $fields = ['fields' => $fields]; + $this->fields = $fields; } else { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + + $options = $fields; } - parent::__construct($fields, $groups, $payload); + parent::__construct($options ?? null, $groups, $payload); $this->allowExtraFields = $allowExtraFields ?? $this->allowExtraFields; $this->allowMissingFields = $allowMissingFields ?? $this->allowMissingFields; @@ -76,6 +78,9 @@ protected function initializeNestedConstraints(): void } } + /** + * @deprecated since Symfony 7.4 + */ public function getRequiredOptions(): array { return ['fields']; diff --git a/Constraints/Composite.php b/Constraints/Composite.php index ce6283b84..6b91580bc 100644 --- a/Constraints/Composite.php +++ b/Constraints/Composite.php @@ -53,6 +53,10 @@ abstract class Composite extends Constraint #[HasNamedArguments] public function __construct(mixed $options = null, ?array $groups = null, mixed $payload = null) { + if (null !== $options) { + trigger_deprecation('symfony/validator', '7.4', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + } + parent::__construct($options, $groups, $payload); $this->initializeNestedConstraints(); diff --git a/Constraints/Count.php b/Constraints/Count.php index 108872904..9a26cc008 100644 --- a/Constraints/Count.php +++ b/Constraints/Count.php @@ -72,8 +72,6 @@ public function __construct( $exactly = $options['value'] ?? null; } elseif (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; } $min ??= $options['min'] ?? null; diff --git a/Constraints/CssColor.php b/Constraints/CssColor.php index 793a4a576..1a8cfd0da 100644 --- a/Constraints/CssColor.php +++ b/Constraints/CssColor.php @@ -73,7 +73,7 @@ public function __construct(array|string $formats = [], ?string $message = null, $validationModesAsString = implode(', ', self::$validationModes); if (!$formats) { - $options['value'] = self::$validationModes; + $formats = self::$validationModes; } elseif (\is_array($formats) && \is_string(key($formats))) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); @@ -82,28 +82,33 @@ public function __construct(array|string $formats = [], ?string $message = null, if ([] === array_intersect(self::$validationModes, $formats)) { throw new InvalidArgumentException(\sprintf('The "formats" parameter value is not valid. It must contain one or more of the following values: "%s".', $validationModesAsString)); } - - $options['value'] = $formats; } elseif (\is_string($formats)) { if (!\in_array($formats, self::$validationModes, true)) { throw new InvalidArgumentException(\sprintf('The "formats" parameter value is not valid. It must contain one or more of the following values: "%s".', $validationModesAsString)); } - $options['value'] = [$formats]; + $formats = [$formats]; } else { throw new InvalidArgumentException('The "formats" parameter type is not valid. It should be a string or an array.'); } parent::__construct($options, $groups, $payload); + $this->formats = $formats ?? $this->formats; $this->message = $message ?? $this->message; } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): string { return 'formats'; } + /** + * @deprecated since Symfony 7.4 + */ public function getRequiredOptions(): array { return ['formats']; diff --git a/Constraints/DateTime.php b/Constraints/DateTime.php index 6b287be75..96e7493ea 100644 --- a/Constraints/DateTime.php +++ b/Constraints/DateTime.php @@ -52,18 +52,20 @@ public function __construct(string|array|null $format = null, ?string $message = } elseif (null !== $format) { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; - } - $options['value'] = $format; + $options['value'] = $format; + } } parent::__construct($options, $groups, $payload); + $this->format = $format ?? $this->format; $this->message = $message ?? $this->message; } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'format'; diff --git a/Constraints/Existence.php b/Constraints/Existence.php index 72bc1da61..a31d74446 100644 --- a/Constraints/Existence.php +++ b/Constraints/Existence.php @@ -20,6 +20,20 @@ abstract class Existence extends Composite { public array|Constraint $constraints = []; + public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null) + { + if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { + parent::__construct($constraints, $groups, $payload); + } else { + $this->constraints = $constraints; + + parent::__construct(null, $groups, $payload); + } + } + + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'constraints'; diff --git a/Constraints/Expression.php b/Constraints/Expression.php index a739acbb8..ac0e99e28 100644 --- a/Constraints/Expression.php +++ b/Constraints/Expression.php @@ -67,25 +67,30 @@ public function __construct( } else { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; - } - $options['value'] = $expression; + $options['value'] = $expression; + } } parent::__construct($options, $groups, $payload); $this->message = $message ?? $this->message; + $this->expression = $expression ?? $this->expression; $this->values = $values ?? $this->values; $this->negate = $negate ?? $this->negate; } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'expression'; } + /** + * @deprecated since Symfony 7.4 + */ public function getRequiredOptions(): array { return ['expression']; diff --git a/Constraints/IsFalse.php b/Constraints/IsFalse.php index bcdadeaf9..aa19d191d 100644 --- a/Constraints/IsFalse.php +++ b/Constraints/IsFalse.php @@ -41,7 +41,7 @@ public function __construct(?array $options = null, ?string $message = null, ?ar trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - parent::__construct($options ?? [], $groups, $payload); + parent::__construct($options, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/IsNull.php b/Constraints/IsNull.php index fa04703ea..4aac68b4f 100644 --- a/Constraints/IsNull.php +++ b/Constraints/IsNull.php @@ -41,7 +41,7 @@ public function __construct(?array $options = null, ?string $message = null, ?ar trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - parent::__construct($options ?? [], $groups, $payload); + parent::__construct($options, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/IsTrue.php b/Constraints/IsTrue.php index 3c0345e77..ea20cc80d 100644 --- a/Constraints/IsTrue.php +++ b/Constraints/IsTrue.php @@ -41,7 +41,7 @@ public function __construct(?array $options = null, ?string $message = null, ?ar trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - parent::__construct($options ?? [], $groups, $payload); + parent::__construct($options, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/Isbn.php b/Constraints/Isbn.php index 45ca4e4b8..471a39ca8 100644 --- a/Constraints/Isbn.php +++ b/Constraints/Isbn.php @@ -70,14 +70,9 @@ public function __construct( trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($type, $options ?? []); - } elseif (null !== $type) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; - } - - $options['value'] = $type; + $type = $options['type'] ?? null; + } elseif (\is_array($options)) { + trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } parent::__construct($options, $groups, $payload); @@ -86,8 +81,12 @@ public function __construct( $this->isbn10Message = $isbn10Message ?? $this->isbn10Message; $this->isbn13Message = $isbn13Message ?? $this->isbn13Message; $this->bothIsbnMessage = $bothIsbnMessage ?? $this->bothIsbnMessage; + $this->type = $type ?? $this->type; } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'type'; diff --git a/Constraints/Length.php b/Constraints/Length.php index ce1460c6e..6678e7dc1 100644 --- a/Constraints/Length.php +++ b/Constraints/Length.php @@ -91,8 +91,6 @@ public function __construct( $exactly = $options['value'] ?? null; } elseif (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; } $min ??= $options['min'] ?? null; diff --git a/Constraints/NotBlank.php b/Constraints/NotBlank.php index 725e7eede..f108021ba 100644 --- a/Constraints/NotBlank.php +++ b/Constraints/NotBlank.php @@ -47,7 +47,7 @@ public function __construct(?array $options = null, ?string $message = null, ?bo trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - parent::__construct($options ?? [], $groups, $payload); + parent::__construct($options, $groups, $payload); $this->message = $message ?? $this->message; $this->allowNull = $allowNull ?? $this->allowNull; diff --git a/Constraints/NotNull.php b/Constraints/NotNull.php index 28596925e..e2c784ebb 100644 --- a/Constraints/NotNull.php +++ b/Constraints/NotNull.php @@ -41,7 +41,7 @@ public function __construct(?array $options = null, ?string $message = null, ?ar trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - parent::__construct($options ?? [], $groups, $payload); + parent::__construct($options, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/PasswordStrength.php b/Constraints/PasswordStrength.php index 3867cfbda..030d48141 100644 --- a/Constraints/PasswordStrength.php +++ b/Constraints/PasswordStrength.php @@ -49,9 +49,11 @@ public function __construct(?array $options = null, ?int $minScore = null, ?arra { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - $options['minScore'] ??= self::STRENGTH_MEDIUM; + $options['minScore'] ??= self::STRENGTH_MEDIUM; + } else { + $minScore ??= self::STRENGTH_MEDIUM; + } parent::__construct($options, $groups, $payload); diff --git a/Constraints/Regex.php b/Constraints/Regex.php index 5c8501fa0..0881ae0b3 100644 --- a/Constraints/Regex.php +++ b/Constraints/Regex.php @@ -58,18 +58,16 @@ public function __construct( trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($pattern, $options ?? []); + $pattern = $options['pattern'] ?? null; } elseif (null !== $pattern) { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; } - - $options['value'] = $pattern; } parent::__construct($options, $groups, $payload); + $this->pattern = $pattern ?? $this->pattern; $this->message = $message ?? $this->message; $this->htmlPattern = $htmlPattern ?? $this->htmlPattern; $this->match = $match ?? $this->match; @@ -80,11 +78,17 @@ public function __construct( } } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'pattern'; } + /** + * @deprecated since Symfony 7.4 + */ public function getRequiredOptions(): array { return ['pattern']; diff --git a/Constraints/Sequentially.php b/Constraints/Sequentially.php index 6389ebb89..f695204b1 100644 --- a/Constraints/Sequentially.php +++ b/Constraints/Sequentially.php @@ -32,18 +32,27 @@ class Sequentially extends Composite #[HasNamedArguments] public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($constraints) && !array_is_list($constraints)) { + if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + $options = $constraints; + } else { + $this->constraints = $constraints; } - parent::__construct($constraints ?? [], $groups, $payload); + parent::__construct($options ?? null, $groups, $payload); } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'constraints'; } + /** + * @deprecated since Symfony 7.4 + */ public function getRequiredOptions(): array { return ['constraints']; diff --git a/Constraints/Timezone.php b/Constraints/Timezone.php index 93b0692ef..66734faf4 100644 --- a/Constraints/Timezone.php +++ b/Constraints/Timezone.php @@ -67,15 +67,14 @@ public function __construct( } elseif (null !== $zone) { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; - } - $options['value'] = $zone; + $options['value'] = $zone; + } } parent::__construct($options, $groups, $payload); + $this->zone = $zone ?? $this->zone; $this->message = $message ?? $this->message; $this->countryCode = $countryCode ?? $this->countryCode; $this->intlCompatible = $intlCompatible ?? $this->intlCompatible; @@ -92,6 +91,9 @@ public function __construct( } } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'zone'; diff --git a/Constraints/Traverse.php b/Constraints/Traverse.php index d8546e323..fa63624f6 100644 --- a/Constraints/Traverse.php +++ b/Constraints/Traverse.php @@ -37,11 +37,18 @@ public function __construct(bool|array|null $traverse = null, mixed $payload = n if (\is_array($traverse)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + $options = $traverse; + $traverse = $options['traverse'] ?? null; } - parent::__construct($traverse, null, $payload); + parent::__construct($options ?? null, $payload); + + $this->traverse = $traverse ?? $this->traverse; } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'traverse'; diff --git a/Constraints/Type.php b/Constraints/Type.php index f3fe56dbb..1c8ded6aa 100644 --- a/Constraints/Type.php +++ b/Constraints/Type.php @@ -43,14 +43,11 @@ public function __construct(string|array|null $type, ?string $message = null, ?a trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($type, $options ?? []); + $type = $options['type'] ?? null; } elseif (null !== $type) { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } else { - $options = []; } - - $options['value'] = $type; } elseif (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } @@ -58,13 +55,20 @@ public function __construct(string|array|null $type, ?string $message = null, ?a parent::__construct($options, $groups, $payload); $this->message = $message ?? $this->message; + $this->type = $type ?? $this->type; } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { return 'type'; } + /** + * @deprecated since Symfony 7.4 + */ public function getRequiredOptions(): array { return ['type']; diff --git a/Constraints/Valid.php b/Constraints/Valid.php index 48deae8ac..0e60574f1 100644 --- a/Constraints/Valid.php +++ b/Constraints/Valid.php @@ -36,7 +36,7 @@ public function __construct(?array $options = null, ?array $groups = null, $payl trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - parent::__construct($options ?? [], $groups, $payload); + parent::__construct($options, $groups, $payload); $this->traverse = $traverse ?? $this->traverse; } diff --git a/Constraints/When.php b/Constraints/When.php index f32b81a37..cafdec08d 100644 --- a/Constraints/When.php +++ b/Constraints/When.php @@ -52,13 +52,15 @@ public function __construct(string|Expression|array|\Closure $expression, array| } else { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + + $options['expression'] = $expression; + $options['constraints'] = $constraints; + $options['otherwise'] = $otherwise; } else { - $options = []; + $this->expression = $expression; + $this->constraints = $constraints; + $this->otherwise = $otherwise; } - - $options['expression'] = $expression; - $options['constraints'] = $constraints; - $options['otherwise'] = $otherwise; } if (!\is_array($options['constraints'] ?? [])) { @@ -69,15 +71,7 @@ public function __construct(string|Expression|array|\Closure $expression, array| $options['otherwise'] = [$options['otherwise']]; } - if (null !== $groups) { - $options['groups'] = $groups; - } - - if (null !== $payload) { - $options['payload'] = $payload; - } - - parent::__construct($options); + parent::__construct($options, $groups, $payload); $this->values = $values ?? $this->values; } diff --git a/Tests/ConstraintTest.php b/Tests/ConstraintTest.php index 80e33c7b7..441850977 100644 --- a/Tests/ConstraintTest.php +++ b/Tests/ConstraintTest.php @@ -25,12 +25,16 @@ use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithTypedProperty; use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValue; use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValueAsDefault; +use Symfony\Component\Validator\Tests\Fixtures\LegacyConstraintA; class ConstraintTest extends TestCase { + /** + * @group legacy + */ public function testSetProperties() { - $constraint = new ConstraintA([ + $constraint = new LegacyConstraintA([ 'property1' => 'foo', 'property2' => 'bar', ]); @@ -39,24 +43,33 @@ public function testSetProperties() $this->assertEquals('bar', $constraint->property2); } + /** + * @group legacy + */ public function testSetNotExistingPropertyThrowsException() { $this->expectException(InvalidOptionsException::class); - new ConstraintA([ + new LegacyConstraintA([ 'foo' => 'bar', ]); } + /** + * @group legacy + */ public function testMagicPropertiesAreNotAllowed() { - $constraint = new ConstraintA(); + $constraint = new LegacyConstraintA(); $this->expectException(InvalidOptionsException::class); $constraint->foo = 'bar'; } + /** + * @group legacy + */ public function testInvalidAndRequiredOptionsPassed() { $this->expectException(InvalidOptionsException::class); @@ -67,28 +80,40 @@ public function testInvalidAndRequiredOptionsPassed() ]); } + /** + * @group legacy + */ public function testSetDefaultProperty() { - $constraint = new ConstraintA('foo'); + $constraint = new LegacyConstraintA('foo'); $this->assertEquals('foo', $constraint->property2); } + /** + * @group legacy + */ public function testSetDefaultPropertyDoctrineStyle() { - $constraint = new ConstraintA(['value' => 'foo']); + $constraint = new LegacyConstraintA(['value' => 'foo']); $this->assertEquals('foo', $constraint->property2); } + /** + * @group legacy + */ public function testSetDefaultPropertyDoctrineStylePlusOtherProperty() { - $constraint = new ConstraintA(['value' => 'foo', 'property1' => 'bar']); + $constraint = new LegacyConstraintA(['value' => 'foo', 'property1' => 'bar']); $this->assertEquals('foo', $constraint->property2); $this->assertEquals('bar', $constraint->property1); } + /** + * @group legacy + */ public function testSetDefaultPropertyDoctrineStyleWhenDefaultPropertyIsNamedValue() { $constraint = new ConstraintWithValueAsDefault(['value' => 'foo']); @@ -97,6 +122,9 @@ public function testSetDefaultPropertyDoctrineStyleWhenDefaultPropertyIsNamedVal $this->assertNull($constraint->property); } + /** + * @group legacy + */ public function testDontSetDefaultPropertyIfValuePropertyExists() { $constraint = new ConstraintWithValue(['value' => 'foo']); @@ -105,6 +133,9 @@ public function testDontSetDefaultPropertyIfValuePropertyExists() $this->assertNull($constraint->property); } + /** + * @group legacy + */ public function testSetUndefinedDefaultProperty() { $this->expectException(ConstraintDefinitionException::class); @@ -112,6 +143,9 @@ public function testSetUndefinedDefaultProperty() new ConstraintB('foo'); } + /** + * @group legacy + */ public function testRequiredOptionsMustBeDefined() { $this->expectException(MissingOptionsException::class); @@ -119,6 +153,9 @@ public function testRequiredOptionsMustBeDefined() new ConstraintC(); } + /** + * @group legacy + */ public function testRequiredOptionsPassed() { $constraint = new ConstraintC(['option1' => 'default']); @@ -126,26 +163,35 @@ public function testRequiredOptionsPassed() $this->assertSame('default', $constraint->option1); } + /** + * @group legacy + */ public function testGroupsAreConvertedToArray() { - $constraint = new ConstraintA(['groups' => 'Foo']); + $constraint = new LegacyConstraintA(['groups' => 'Foo']); $this->assertEquals(['Foo'], $constraint->groups); } public function testAddDefaultGroupAddsGroup() { - $constraint = new ConstraintA(['groups' => 'Default']); + $constraint = new ConstraintA(null, null, ['Default']); $constraint->addImplicitGroupName('Foo'); $this->assertEquals(['Default', 'Foo'], $constraint->groups); } + /** + * @group legacy + */ public function testAllowsSettingZeroRequiredPropertyValue() { - $constraint = new ConstraintA(0); + $constraint = new LegacyConstraintA(0); $this->assertEquals(0, $constraint->property2); } + /** + * @group legacy + */ public function testCanCreateConstraintWithNoDefaultOptionAndEmptyArray() { $constraint = new ConstraintB([]); @@ -169,7 +215,19 @@ public function testGetTargetsCanBeArray() public function testSerialize() { - $constraint = new ConstraintA([ + $constraint = new ConstraintA('foo', 'bar'); + + $restoredConstraint = unserialize(serialize($constraint)); + + $this->assertEquals($constraint, $restoredConstraint); + } + + /** + * @group legacy + */ + public function testSerializeDoctrineStyle() + { + $constraint = new LegacyConstraintA([ 'property1' => 'foo', 'property2' => 'bar', ]); @@ -181,14 +239,28 @@ public function testSerialize() public function testSerializeInitializesGroupsOptionToDefault() { - $constraint = new ConstraintA([ + $constraint = new ConstraintA('foo', 'bar'); + + $constraint = unserialize(serialize($constraint)); + + $expected = new ConstraintA('foo', 'bar', ['Default']); + + $this->assertEquals($expected, $constraint); + } + + /** + * @group legacy + */ + public function testSerializeInitializesGroupsOptionToDefaultDoctrineStyle() + { + $constraint = new LegacyConstraintA([ 'property1' => 'foo', 'property2' => 'bar', ]); $constraint = unserialize(serialize($constraint)); - $expected = new ConstraintA([ + $expected = new LegacyConstraintA([ 'property1' => 'foo', 'property2' => 'bar', 'groups' => 'Default', @@ -199,7 +271,19 @@ public function testSerializeInitializesGroupsOptionToDefault() public function testSerializeKeepsCustomGroups() { - $constraint = new ConstraintA([ + $constraint = new ConstraintA('foo', 'bar', ['MyGroup']); + + $constraint = unserialize(serialize($constraint)); + + $this->assertSame(['MyGroup'], $constraint->groups); + } + + /** + * @group legacy + */ + public function testSerializeKeepsCustomGroupsDoctrineStyle() + { + $constraint = new LegacyConstraintA([ 'property1' => 'foo', 'property2' => 'bar', 'groups' => 'MyGroup', @@ -216,35 +300,47 @@ public function testGetErrorNameForUnknownCode() Constraint::getErrorName(1); } + /** + * @group legacy + */ public function testOptionsAsDefaultOption() { - $constraint = new ConstraintA($options = ['value1']); + $constraint = new LegacyConstraintA($options = ['value1']); $this->assertEquals($options, $constraint->property2); - $constraint = new ConstraintA($options = ['value1', 'property1' => 'value2']); + $constraint = new LegacyConstraintA($options = ['value1', 'property1' => 'value2']); $this->assertEquals($options, $constraint->property2); } + /** + * @group legacy + */ public function testInvalidOptions() { $this->expectException(InvalidOptionsException::class); - $this->expectExceptionMessage('The options "0", "5" do not exist in constraint "Symfony\Component\Validator\Tests\Fixtures\ConstraintA".'); - new ConstraintA(['property2' => 'foo', 'bar', 5 => 'baz']); + $this->expectExceptionMessage('The options "0", "5" do not exist in constraint "Symfony\Component\Validator\Tests\Fixtures\LegacyConstraintA".'); + new LegacyConstraintA(['property2' => 'foo', 'bar', 5 => 'baz']); } + /** + * @group legacy + */ public function testOptionsWithInvalidInternalPointer() { $options = ['property1' => 'foo']; next($options); next($options); - $constraint = new ConstraintA($options); + $constraint = new LegacyConstraintA($options); $this->assertEquals('foo', $constraint->property1); } + /** + * @group legacy + */ public function testAttributeSetUndefinedDefaultOption() { $this->expectException(ConstraintDefinitionException::class); @@ -252,6 +348,9 @@ public function testAttributeSetUndefinedDefaultOption() new ConstraintB(['value' => 1]); } + /** + * @group legacy + */ public function testStaticPropertiesAreNoOptions() { $this->expectException(InvalidOptionsException::class); @@ -261,6 +360,9 @@ public function testStaticPropertiesAreNoOptions() ]); } + /** + * @group legacy + */ public function testSetTypedProperty() { $constraint = new ConstraintWithTypedProperty([ diff --git a/Tests/Constraints/ChoiceTest.php b/Tests/Constraints/ChoiceTest.php index 9c58dd107..2173c45f5 100644 --- a/Tests/Constraints/ChoiceTest.php +++ b/Tests/Constraints/ChoiceTest.php @@ -19,6 +19,9 @@ class ChoiceTest extends TestCase { + /** + * @group legacy + */ public function testSetDefaultPropertyChoice() { $constraint = new ConstraintChoiceWithPreset('A'); diff --git a/Tests/Constraints/CompositeTest.php b/Tests/Constraints/CompositeTest.php index 9329ef1a2..bc5a8316a 100644 --- a/Tests/Constraints/CompositeTest.php +++ b/Tests/Constraints/CompositeTest.php @@ -24,9 +24,11 @@ class ConcreteComposite extends Composite { public array|Constraint $constraints = []; - public function __construct(mixed $options = null, public array|Constraint $otherNested = []) + public function __construct(array|Constraint $constraints = [], public array|Constraint $otherNested = [], ?array $groups = null) { - parent::__construct($options); + $this->constraints = $constraints; + + parent::__construct(null, $groups); } protected function getCompositeOption(): array @@ -89,16 +91,14 @@ public function testMergeNestedGroupsIfNoExplicitParentGroup() public function testSetImplicitNestedGroupsIfExplicitParentGroup() { - $constraint = new ConcreteComposite([ - 'constraints' => [ + $constraint = new ConcreteComposite( + [ new NotNull(), new NotBlank(), ], - 'otherNested' => [ - new Length(exactly: 10), - ], - 'groups' => ['Default', 'Strict'], - ]); + new Length(exactly: 10), + ['Default', 'Strict'], + ); $this->assertEquals(['Default', 'Strict'], $constraint->groups); $this->assertEquals(['Default', 'Strict'], $constraint->constraints[0]->groups); @@ -108,16 +108,14 @@ public function testSetImplicitNestedGroupsIfExplicitParentGroup() public function testExplicitNestedGroupsMustBeSubsetOfExplicitParentGroups() { - $constraint = new ConcreteComposite([ - 'constraints' => [ + $constraint = new ConcreteComposite( + [ new NotNull(groups: ['Default']), new NotBlank(groups: ['Strict']), ], - 'otherNested' => [ - new Length(exactly: 10, groups: ['Strict']), - ], - 'groups' => ['Default', 'Strict'], - ]); + new Length(exactly: 10, groups: ['Strict']), + ['Default', 'Strict'] + ); $this->assertEquals(['Default', 'Strict'], $constraint->groups); $this->assertEquals(['Default'], $constraint->constraints[0]->groups); @@ -128,26 +126,13 @@ public function testExplicitNestedGroupsMustBeSubsetOfExplicitParentGroups() public function testFailIfExplicitNestedGroupsNotSubsetOfExplicitParentGroups() { $this->expectException(ConstraintDefinitionException::class); - new ConcreteComposite([ - 'constraints' => [ - new NotNull(groups: ['Default', 'Foobar']), - ], - 'groups' => ['Default', 'Strict'], - ]); + new ConcreteComposite(new NotNull(groups: ['Default', 'Foobar']), [], ['Default', 'Strict']); } public function testFailIfExplicitNestedGroupsNotSubsetOfExplicitParentGroupsInOtherNested() { $this->expectException(ConstraintDefinitionException::class); - new ConcreteComposite([ - 'constraints' => [ - new NotNull(groups: ['Default']), - ], - 'otherNested' => [ - new NotNull(groups: ['Default', 'Foobar']), - ], - 'groups' => ['Default', 'Strict'], - ]); + new ConcreteComposite(new NotNull(groups: ['Default']), new NotNull(groups: ['Default', 'Foobar']),['Default', 'Strict']); } public function testImplicitGroupNamesAreForwarded() diff --git a/Tests/Constraints/CompoundTest.php b/Tests/Constraints/CompoundTest.php index 9b515a48c..c3c55eb3e 100644 --- a/Tests/Constraints/CompoundTest.php +++ b/Tests/Constraints/CompoundTest.php @@ -38,6 +38,9 @@ public function testGroupsAndPayload() $this->assertSame($payload, $compound->payload); } + /** + * @group legacy + */ public function testGroupsAndPayloadInOptionsArray() { $payload = new \stdClass(); @@ -47,6 +50,9 @@ public function testGroupsAndPayloadInOptionsArray() $this->assertSame($payload, $compound->payload); } + /** + * @group legacy + */ public function testCanDependOnNormalizedOptions() { $constraint = new ForwardingOptionCompound($min = 3); diff --git a/Tests/Fixtures/ConstraintA.php b/Tests/Fixtures/ConstraintA.php index 51e8ae6a7..6a0cc10ef 100644 --- a/Tests/Fixtures/ConstraintA.php +++ b/Tests/Fixtures/ConstraintA.php @@ -19,9 +19,11 @@ class ConstraintA extends Constraint public $property1; public $property2; - public function getDefaultOption(): ?string + public function __construct($property1 = null, $property2 = null, $groups = null) { - return 'property2'; + parent::__construct(null, $groups); + $this->property1 = $property1; + $this->property2 = $property2; } public function getTargets(): string|array diff --git a/Tests/Fixtures/ConstraintWithRequiredArgument.php b/Tests/Fixtures/ConstraintWithRequiredArgument.php index f8abc8a56..93123677a 100644 --- a/Tests/Fixtures/ConstraintWithRequiredArgument.php +++ b/Tests/Fixtures/ConstraintWithRequiredArgument.php @@ -22,7 +22,7 @@ final class ConstraintWithRequiredArgument extends Constraint #[HasNamedArguments] public function __construct(string $requiredArg, ?array $groups = null, mixed $payload = null) { - parent::__construct([], $groups, $payload); + parent::__construct(null, $groups, $payload); $this->requiredArg = $requiredArg; } diff --git a/Tests/Fixtures/LegacyConstraintA.php b/Tests/Fixtures/LegacyConstraintA.php new file mode 100644 index 000000000..b115608de --- /dev/null +++ b/Tests/Fixtures/LegacyConstraintA.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures; + +use Symfony\Component\Validator\Constraint; + +#[\Attribute] +class LegacyConstraintA extends Constraint +{ + public $property1; + public $property2; + + public function getDefaultOption(): ?string + { + return 'property2'; + } + + public function getTargets(): string|array + { + return [self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT]; + } +} diff --git a/Tests/Mapping/ClassMetadataTest.php b/Tests/Mapping/ClassMetadataTest.php index edfacae16..ce12b31d4 100644 --- a/Tests/Mapping/ClassMetadataTest.php +++ b/Tests/Mapping/ClassMetadataTest.php @@ -88,8 +88,8 @@ public function testAddMultiplePropertyConstraints() $this->metadata->addPropertyConstraints('lastName', [new ConstraintA(), new ConstraintB()]); $constraints = [ - new ConstraintA(['groups' => ['Default', 'Entity']]), - new ConstraintB(['groups' => ['Default', 'Entity']]), + new ConstraintA(null, null, ['Default', 'Entity']), + new ConstraintB(null, ['Default', 'Entity']), ]; $properties = $this->metadata->getPropertyMetadata('lastName'); @@ -105,8 +105,8 @@ public function testAddGetterConstraints() $this->metadata->addGetterConstraint('lastName', new ConstraintB()); $constraints = [ - new ConstraintA(['groups' => ['Default', 'Entity']]), - new ConstraintB(['groups' => ['Default', 'Entity']]), + new ConstraintA(null, null, ['Default', 'Entity']), + new ConstraintB(null, ['Default', 'Entity']), ]; $properties = $this->metadata->getPropertyMetadata('lastName'); @@ -121,8 +121,8 @@ public function testAddMultipleGetterConstraints() $this->metadata->addGetterConstraints('lastName', [new ConstraintA(), new ConstraintB()]); $constraints = [ - new ConstraintA(['groups' => ['Default', 'Entity']]), - new ConstraintB(['groups' => ['Default', 'Entity']]), + new ConstraintA(null, null, ['Default', 'Entity']), + new ConstraintB(null, ['Default', 'Entity']), ]; $properties = $this->metadata->getPropertyMetadata('lastName'); @@ -141,15 +141,15 @@ public function testMergeConstraintsMergesClassConstraints() $this->metadata->addConstraint(new ConstraintA()); $constraints = [ - new ConstraintA(['groups' => [ + new ConstraintA(null, null, [ 'Default', 'EntityParent', 'Entity', - ]]), - new ConstraintA(['groups' => [ + ]), + new ConstraintA(null, null, [ 'Default', 'Entity', - ]]), + ]), ]; $this->assertEquals($constraints, $this->metadata->getConstraints()); @@ -159,23 +159,21 @@ public function testMergeConstraintsMergesMemberConstraints() { $parent = new ClassMetadata(self::PARENTCLASS); $parent->addPropertyConstraint('firstName', new ConstraintA()); - $parent->addPropertyConstraint('firstName', new ConstraintB(['groups' => 'foo'])); + $parent->addPropertyConstraint('firstName', new ConstraintB(null, ['foo'])); $this->metadata->addPropertyConstraint('firstName', new ConstraintA()); $this->metadata->mergeConstraints($parent); - $constraintA1 = new ConstraintA(['groups' => [ + $constraintA1 = new ConstraintA(null, null, [ 'Default', 'EntityParent', 'Entity', - ]]); - $constraintA2 = new ConstraintA(['groups' => [ + ]); + $constraintA2 = new ConstraintA(null, null, [ 'Default', 'Entity', - ]]); - $constraintB = new ConstraintB([ - 'groups' => ['foo'], ]); + $constraintB = new ConstraintB(null, ['foo']); $members = $this->metadata->getPropertyMetadata('firstName'); @@ -219,17 +217,17 @@ public function testMergeConstraintsKeepsPrivateMembersSeparate() $this->metadata->addPropertyConstraint('internal', new ConstraintA()); $parentConstraints = [ - new ConstraintA(['groups' => [ + new ConstraintA(null, null, [ 'Default', 'EntityParent', 'Entity', - ]]), + ]), ]; $constraints = [ - new ConstraintA(['groups' => [ + new ConstraintA(null, null, [ 'Default', 'Entity', - ]]), + ]), ]; $members = $this->metadata->getPropertyMetadata('internal'); @@ -250,8 +248,8 @@ public function testGetReflectionClass() public function testSerialize() { - $this->metadata->addConstraint(new ConstraintA(['property1' => 'A'])); - $this->metadata->addConstraint(new ConstraintB(['groups' => 'TestGroup'])); + $this->metadata->addConstraint(new ConstraintA('A')); + $this->metadata->addConstraint(new ConstraintB(null, ['TestGroup'])); $this->metadata->addPropertyConstraint('firstName', new ConstraintA()); $this->metadata->addGetterConstraint('lastName', new ConstraintB()); @@ -395,9 +393,11 @@ class ClassCompositeConstraint extends Composite { public $nested; - public function getDefaultOption(): ?string + public function __construct(array $nested) { - return $this->getCompositeOption(); + $this->nested = $nested; + + parent::__construct(); } protected function getCompositeOption(): string diff --git a/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php b/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php index 70579011c..8dfc6dd1b 100644 --- a/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php +++ b/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php @@ -21,7 +21,7 @@ class ConstraintWithNamedArguments extends Constraint #[HasNamedArguments] public function __construct(array|string|null $choices = [], ?array $groups = null) { - parent::__construct([], $groups); + parent::__construct(null, $groups); $this->choices = $choices; } diff --git a/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php b/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php index af950fc13..48b67362c 100644 --- a/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php +++ b/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php @@ -19,7 +19,7 @@ class ConstraintWithoutValueWithNamedArguments extends Constraint #[HasNamedArguments] public function __construct(?array $groups = null) { - parent::__construct([], $groups); + parent::__construct(null, $groups); } public function getTargets(): string diff --git a/Tests/Mapping/MemberMetadataTest.php b/Tests/Mapping/MemberMetadataTest.php index 84d047f10..d5dfb9ec0 100644 --- a/Tests/Mapping/MemberMetadataTest.php +++ b/Tests/Mapping/MemberMetadataTest.php @@ -74,8 +74,8 @@ public function testAddCompositeConstraintAcceptsDeepNestedPropertyConstraints() public function testSerialize() { - $this->metadata->addConstraint(new ConstraintA(['property1' => 'A'])); - $this->metadata->addConstraint(new ConstraintB(['groups' => 'TestGroup'])); + $this->metadata->addConstraint(new ConstraintA('A')); + $this->metadata->addConstraint(new ConstraintB(null, ['TestGroup'])); $metadata = unserialize(serialize($this->metadata)); @@ -116,9 +116,11 @@ class PropertyCompositeConstraint extends Composite { public $nested; - public function getDefaultOption(): ?string + public function __construct(array $nested) { - return $this->getCompositeOption(); + $this->nested = $nested; + + parent::__construct(); } protected function getCompositeOption(): string From c21845a5560ad55c6b9242f9d156dc8d22fc2ce2 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 8 Jul 2025 11:08:29 +0200 Subject: [PATCH 09/57] Various CS fixes --- Constraint.php | 2 +- Constraints/Expression.php | 2 +- Tests/Constraints/CompositeTest.php | 2 +- Tests/Constraints/LocaleValidatorTest.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Constraint.php b/Constraint.php index 42ed471c6..17d8cc313 100644 --- a/Constraint.php +++ b/Constraint.php @@ -110,7 +110,7 @@ public function __construct(mixed $options = null, ?array $groups = null, mixed { unset($this->groups); // enable lazy initialization - if (null === $options && (\func_num_args() > 0 || (new \ReflectionMethod($this, 'getRequiredOptions'))->getDeclaringClass()->getName() === self::class)) { + if (null === $options && (\func_num_args() > 0 || self::class === (new \ReflectionMethod($this, 'getRequiredOptions'))->getDeclaringClass()->getName())) { if (null !== $groups) { $this->groups = $groups; } diff --git a/Constraints/Expression.php b/Constraints/Expression.php index ac0e99e28..783108b43 100644 --- a/Constraints/Expression.php +++ b/Constraints/Expression.php @@ -68,7 +68,7 @@ public function __construct( if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - $options['value'] = $expression; + $options['value'] = $expression; } } diff --git a/Tests/Constraints/CompositeTest.php b/Tests/Constraints/CompositeTest.php index bc5a8316a..f2670dded 100644 --- a/Tests/Constraints/CompositeTest.php +++ b/Tests/Constraints/CompositeTest.php @@ -132,7 +132,7 @@ public function testFailIfExplicitNestedGroupsNotSubsetOfExplicitParentGroups() public function testFailIfExplicitNestedGroupsNotSubsetOfExplicitParentGroupsInOtherNested() { $this->expectException(ConstraintDefinitionException::class); - new ConcreteComposite(new NotNull(groups: ['Default']), new NotNull(groups: ['Default', 'Foobar']),['Default', 'Strict']); + new ConcreteComposite(new NotNull(groups: ['Default']), new NotNull(groups: ['Default', 'Foobar']), ['Default', 'Strict']); } public function testImplicitGroupNamesAreForwarded() diff --git a/Tests/Constraints/LocaleValidatorTest.php b/Tests/Constraints/LocaleValidatorTest.php index 5a060e4da..3b3819512 100644 --- a/Tests/Constraints/LocaleValidatorTest.php +++ b/Tests/Constraints/LocaleValidatorTest.php @@ -97,7 +97,7 @@ public function testTooLongLocale() $this->validator->validate($locale, $constraint); $this->buildViolation('myMessage') - ->setParameter('{{ value }}', '"' . $locale . '"') + ->setParameter('{{ value }}', '"'.$locale.'"') ->setCode(Locale::NO_SUCH_LOCALE_ERROR) ->assertRaised(); } From 425555adce6072062ee5d154e594833cf44d2bc8 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 10 Jul 2025 08:20:22 +0200 Subject: [PATCH 10/57] fix BC layer for Expression constraint from options array --- Constraints/Expression.php | 1 + Tests/Constraints/ExpressionTest.php | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/Constraints/Expression.php b/Constraints/Expression.php index 783108b43..a04df9fd3 100644 --- a/Constraints/Expression.php +++ b/Constraints/Expression.php @@ -64,6 +64,7 @@ public function __construct( trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($expression, $options ?? []); + $expression = null; } else { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); diff --git a/Tests/Constraints/ExpressionTest.php b/Tests/Constraints/ExpressionTest.php index 89db330b9..f702d9fa4 100644 --- a/Tests/Constraints/ExpressionTest.php +++ b/Tests/Constraints/ExpressionTest.php @@ -41,6 +41,18 @@ public function testAttributes() self::assertSame('some attached data', $cConstraint->payload); self::assertFalse($cConstraint->negate); } + + /** + * @group legacy + */ + public function testInitializeWithOptionsArray() + { + $constraint = new Expression([ + 'expression' => '!this.getParent().get("field2").getData()', + ]); + + $this->assertSame('!this.getParent().get("field2").getData()', $constraint->expression); + } } class ExpressionDummy From 944b444a4576019bdbd3b25dcc4f0e4695d7c293 Mon Sep 17 00:00:00 2001 From: Gregor Harlan Date: Sat, 12 Jul 2025 15:55:19 +0200 Subject: [PATCH 11/57] optimize `in_array` calls --- Constraints/BicValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Constraints/BicValidator.php b/Constraints/BicValidator.php index 55b6bbbc0..0c3e42b98 100644 --- a/Constraints/BicValidator.php +++ b/Constraints/BicValidator.php @@ -78,7 +78,7 @@ public function validate(mixed $value, Constraint $constraint): void $canonicalize = str_replace(' ', '', $value); // the bic must be either 8 or 11 characters long - if (!\in_array(\strlen($canonicalize), [8, 11])) { + if (!\in_array(\strlen($canonicalize), [8, 11], true)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Bic::INVALID_LENGTH_ERROR) From a23b5201166bcf166c8863767cd890a764225692 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 13 Jul 2025 10:07:08 +0200 Subject: [PATCH 12/57] mark getRequiredOptions()/getDefaultOption() of UniqueEntity as deprecated --- CHANGELOG.md | 2 ++ Constraint.php | 14 ++++++++++---- Constraints/AbstractComparison.php | 4 ++++ Constraints/All.php | 8 ++++++++ Constraints/AtLeastOneOf.php | 8 ++++++++ Constraints/Callback.php | 4 ++++ Constraints/CardScheme.php | 8 ++++++++ Constraints/Choice.php | 4 ++++ Constraints/Collection.php | 4 ++++ Constraints/CssColor.php | 8 ++++++++ Constraints/DateTime.php | 4 ++++ Constraints/Existence.php | 4 ++++ Constraints/Expression.php | 8 ++++++++ Constraints/Isbn.php | 4 ++++ Constraints/Regex.php | 8 ++++++++ Constraints/Sequentially.php | 8 ++++++++ Constraints/Timezone.php | 4 ++++ Constraints/Traverse.php | 4 ++++ Constraints/Type.php | 8 ++++++++ Constraints/When.php | 16 ++++++++++------ 20 files changed, 122 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d1fc55e6..dc7c083bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 7.4 --- + * Deprecate `getRequiredOptions()` and `getDefaultOption()` methods of the `All`, `AtLeastOneOf`, `CardScheme`, `Collection`, + `CssColor`, `Expression`, `Regex`, `Sequentially`, `Type`, and `When` constraints * Deprecate evaluating options in the base `Constraint` class. Initialize properties in the constructor of the concrete constraint class instead. diff --git a/Constraint.php b/Constraint.php index 17d8cc313..5563500eb 100644 --- a/Constraint.php +++ b/Constraint.php @@ -140,9 +140,9 @@ public function __construct(mixed $options = null, ?array $groups = null, mixed protected function normalizeOptions(mixed $options): array { $normalizedOptions = []; - $defaultOption = $this->getDefaultOption(); + $defaultOption = $this->getDefaultOption(false); $invalidOptions = []; - $missingOptions = array_flip($this->getRequiredOptions()); + $missingOptions = array_flip($this->getRequiredOptions(false)); $knownOptions = get_class_vars(static::class); if (\is_array($options) && isset($options['value']) && !property_exists($this, 'value')) { @@ -255,11 +255,14 @@ public function addImplicitGroupName(string $group): void * Override this method to define a default option. * * @deprecated since Symfony 7.4 - * * @see __construct() */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return null; } @@ -271,11 +274,14 @@ public function getDefaultOption(): ?string * @return string[] * * @deprecated since Symfony 7.4 - * * @see __construct() */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return []; } diff --git a/Constraints/AbstractComparison.php b/Constraints/AbstractComparison.php index 523a81296..586a23ef4 100644 --- a/Constraints/AbstractComparison.php +++ b/Constraints/AbstractComparison.php @@ -68,6 +68,10 @@ public function __construct(mixed $value = null, ?string $propertyPath = null, ? */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'value'; } } diff --git a/Constraints/All.php b/Constraints/All.php index b1a477782..4b36ead8c 100644 --- a/Constraints/All.php +++ b/Constraints/All.php @@ -48,6 +48,10 @@ public function __construct(mixed $constraints = null, ?array $groups = null, mi */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'constraints'; } @@ -56,6 +60,10 @@ public function getDefaultOption(): ?string */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['constraints']; } diff --git a/Constraints/AtLeastOneOf.php b/Constraints/AtLeastOneOf.php index c988726ae..dc6e73f1c 100644 --- a/Constraints/AtLeastOneOf.php +++ b/Constraints/AtLeastOneOf.php @@ -62,6 +62,10 @@ public function __construct(mixed $constraints = null, ?array $groups = null, mi */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'constraints'; } @@ -70,6 +74,10 @@ public function getDefaultOption(): ?string */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['constraints']; } diff --git a/Constraints/Callback.php b/Constraints/Callback.php index 3afe2a1a5..f11f4c37f 100644 --- a/Constraints/Callback.php +++ b/Constraints/Callback.php @@ -61,6 +61,10 @@ public function __construct(array|string|callable|null $callback = null, ?array */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'callback'; } diff --git a/Constraints/CardScheme.php b/Constraints/CardScheme.php index 7d2b76951..75d137c63 100644 --- a/Constraints/CardScheme.php +++ b/Constraints/CardScheme.php @@ -78,6 +78,10 @@ public function __construct(array|string|null $schemes, ?string $message = null, */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'schemes'; } @@ -86,6 +90,10 @@ public function getDefaultOption(): ?string */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['schemes']; } } diff --git a/Constraints/Choice.php b/Constraints/Choice.php index 3849bbf17..8bc380735 100644 --- a/Constraints/Choice.php +++ b/Constraints/Choice.php @@ -50,6 +50,10 @@ class Choice extends Constraint */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'choices'; } diff --git a/Constraints/Collection.php b/Constraints/Collection.php index c0fc237f0..91bcbfd75 100644 --- a/Constraints/Collection.php +++ b/Constraints/Collection.php @@ -83,6 +83,10 @@ protected function initializeNestedConstraints(): void */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['fields']; } diff --git a/Constraints/CssColor.php b/Constraints/CssColor.php index 1a8cfd0da..1c23a6df6 100644 --- a/Constraints/CssColor.php +++ b/Constraints/CssColor.php @@ -103,6 +103,10 @@ public function __construct(array|string $formats = [], ?string $message = null, */ public function getDefaultOption(): string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'formats'; } @@ -111,6 +115,10 @@ public function getDefaultOption(): string */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['formats']; } } diff --git a/Constraints/DateTime.php b/Constraints/DateTime.php index 96e7493ea..3cf906269 100644 --- a/Constraints/DateTime.php +++ b/Constraints/DateTime.php @@ -68,6 +68,10 @@ public function __construct(string|array|null $format = null, ?string $message = */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'format'; } } diff --git a/Constraints/Existence.php b/Constraints/Existence.php index a31d74446..a867f09e5 100644 --- a/Constraints/Existence.php +++ b/Constraints/Existence.php @@ -36,6 +36,10 @@ public function __construct(mixed $constraints = null, ?array $groups = null, mi */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'constraints'; } diff --git a/Constraints/Expression.php b/Constraints/Expression.php index a04df9fd3..7298b297f 100644 --- a/Constraints/Expression.php +++ b/Constraints/Expression.php @@ -86,6 +86,10 @@ public function __construct( */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'expression'; } @@ -94,6 +98,10 @@ public function getDefaultOption(): ?string */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['expression']; } diff --git a/Constraints/Isbn.php b/Constraints/Isbn.php index 471a39ca8..7e34cb53b 100644 --- a/Constraints/Isbn.php +++ b/Constraints/Isbn.php @@ -89,6 +89,10 @@ public function __construct( */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'type'; } } diff --git a/Constraints/Regex.php b/Constraints/Regex.php index 0881ae0b3..df1b386be 100644 --- a/Constraints/Regex.php +++ b/Constraints/Regex.php @@ -83,6 +83,10 @@ public function __construct( */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'pattern'; } @@ -91,6 +95,10 @@ public function getDefaultOption(): ?string */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['pattern']; } diff --git a/Constraints/Sequentially.php b/Constraints/Sequentially.php index f695204b1..e72e58170 100644 --- a/Constraints/Sequentially.php +++ b/Constraints/Sequentially.php @@ -47,6 +47,10 @@ public function __construct(mixed $constraints = null, ?array $groups = null, mi */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'constraints'; } @@ -55,6 +59,10 @@ public function getDefaultOption(): ?string */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['constraints']; } diff --git a/Constraints/Timezone.php b/Constraints/Timezone.php index 66734faf4..193b35eeb 100644 --- a/Constraints/Timezone.php +++ b/Constraints/Timezone.php @@ -96,6 +96,10 @@ public function __construct( */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'zone'; } } diff --git a/Constraints/Traverse.php b/Constraints/Traverse.php index fa63624f6..63e8462c4 100644 --- a/Constraints/Traverse.php +++ b/Constraints/Traverse.php @@ -51,6 +51,10 @@ public function __construct(bool|array|null $traverse = null, mixed $payload = n */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'traverse'; } diff --git a/Constraints/Type.php b/Constraints/Type.php index 1c8ded6aa..7e07a6fcb 100644 --- a/Constraints/Type.php +++ b/Constraints/Type.php @@ -63,6 +63,10 @@ public function __construct(string|array|null $type, ?string $message = null, ?a */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'type'; } @@ -71,6 +75,10 @@ public function getDefaultOption(): ?string */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['type']; } } diff --git a/Constraints/When.php b/Constraints/When.php index cafdec08d..58293f3f3 100644 --- a/Constraints/When.php +++ b/Constraints/When.php @@ -31,12 +31,12 @@ class When extends Composite public array|Constraint $otherwise = []; /** - * @param string|Expression|array|\Closure(object): bool $expression The condition to evaluate, either as a closure or using the ExpressionLanguage syntax - * @param Constraint[]|Constraint|null $constraints One or multiple constraints that are applied if the expression returns true - * @param array|null $values The values of the custom variables used in the expression (defaults to []) - * @param string[]|null $groups - * @param array|null $options - * @param Constraint[]|Constraint $otherwise One or multiple constraints that are applied if the expression returns false + * @param string|Expression|array|\Closure(object): bool $expression The condition to evaluate, either as a closure or using the ExpressionLanguage syntax + * @param Constraint[]|Constraint|null $constraints One or multiple constraints that are applied if the expression returns true + * @param array|null $values The values of the custom variables used in the expression (defaults to []) + * @param string[]|null $groups + * @param array|null $options + * @param Constraint[]|Constraint $otherwise One or multiple constraints that are applied if the expression returns false */ #[HasNamedArguments] public function __construct(string|Expression|array|\Closure $expression, array|Constraint|null $constraints = null, ?array $values = null, ?array $groups = null, $payload = null, ?array $options = null, array|Constraint $otherwise = []) @@ -78,6 +78,10 @@ public function __construct(string|Expression|array|\Closure $expression, array| public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['expression', 'constraints']; } From 1de1a859d9e01b24bbec253f3214fff44ec07407 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 16 Jul 2025 11:36:09 +0200 Subject: [PATCH 13/57] fix detecting missing required options --- Constraints/All.php | 5 +++++ Constraints/AtLeastOneOf.php | 5 +++++ Constraints/CardScheme.php | 10 ++++++---- Constraints/Expression.php | 9 +++++---- Constraints/Regex.php | 11 +++++++---- Constraints/Sequentially.php | 5 +++++ Constraints/Type.php | 5 +++++ Constraints/When.php | 5 +++++ Tests/Constraints/CardSchemeTest.php | 10 ++++++++++ Tests/Constraints/ExpressionTest.php | 10 ++++++++++ Tests/Constraints/RegexTest.php | 10 ++++++++++ Tests/Constraints/TypeTest.php | 10 ++++++++++ Tests/Constraints/WhenTest.php | 14 ++++++++++++++ 13 files changed, 97 insertions(+), 12 deletions(-) diff --git a/Constraints/All.php b/Constraints/All.php index 4b36ead8c..64c6d53be 100644 --- a/Constraints/All.php +++ b/Constraints/All.php @@ -13,6 +13,7 @@ use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * When applied to an array (or Traversable object), this constraint allows you to apply @@ -32,6 +33,10 @@ class All extends Composite #[HasNamedArguments] public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null) { + if (null === $constraints || [] === $constraints) { + throw new MissingOptionsException(\sprintf('The options "constraints" must be set for constraint "%s".', self::class), ['constraints']); + } + if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); diff --git a/Constraints/AtLeastOneOf.php b/Constraints/AtLeastOneOf.php index dc6e73f1c..92f3cc60e 100644 --- a/Constraints/AtLeastOneOf.php +++ b/Constraints/AtLeastOneOf.php @@ -13,6 +13,7 @@ use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * Checks that at least one of the given constraint is satisfied. @@ -43,6 +44,10 @@ class AtLeastOneOf extends Composite #[HasNamedArguments] public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null, ?string $message = null, ?string $messageCollection = null, ?bool $includeInternalMessages = null) { + if (null === $constraints || [] === $constraints) { + throw new MissingOptionsException(\sprintf('The options "constraints" must be set for constraint "%s".', self::class), ['constraints']); + } + if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = $constraints; diff --git a/Constraints/CardScheme.php b/Constraints/CardScheme.php index 125cd4993..c13ede0f9 100644 --- a/Constraints/CardScheme.php +++ b/Constraints/CardScheme.php @@ -13,6 +13,7 @@ use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * Validates a credit card number for a given credit card company. @@ -55,18 +56,19 @@ class CardScheme extends Constraint #[HasNamedArguments] public function __construct(array|string|null $schemes, ?string $message = null, ?array $groups = null, mixed $payload = null, ?array $options = null) { + if (null === $schemes && !isset($options['schemes'])) { + throw new MissingOptionsException(\sprintf('The options "schemes" must be set for constraint "%s".', self::class), ['schemes']); + } + if (\is_array($schemes) && \is_string(key($schemes))) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($schemes, $options ?? []); + $schemes = null; } else { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - - if (null !== $schemes) { - $options['value'] = $schemes; - } } parent::__construct($options, $groups, $payload); diff --git a/Constraints/Expression.php b/Constraints/Expression.php index 6a8701118..71e20e448 100644 --- a/Constraints/Expression.php +++ b/Constraints/Expression.php @@ -16,6 +16,7 @@ use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\LogicException; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * Validates a value using an expression from the Expression Language component. @@ -60,6 +61,10 @@ public function __construct( throw new LogicException(\sprintf('The "symfony/expression-language" component is required to use the "%s" constraint. Try running "composer require symfony/expression-language".', __CLASS__)); } + if (null === $expression && !isset($options['expression'])) { + throw new MissingOptionsException(\sprintf('The options "expression" must be set for constraint "%s".', self::class), ['expression']); + } + if (\is_array($expression)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); @@ -69,10 +74,6 @@ public function __construct( if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - - if (null !== $expression) { - $options['value'] = $expression; - } } parent::__construct($options, $groups, $payload); diff --git a/Constraints/Regex.php b/Constraints/Regex.php index df1b386be..8c3881d84 100644 --- a/Constraints/Regex.php +++ b/Constraints/Regex.php @@ -14,6 +14,7 @@ use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\InvalidArgumentException; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * Validates that a value matches a regular expression. @@ -54,15 +55,17 @@ public function __construct( mixed $payload = null, ?array $options = null, ) { + if (null === $pattern && !isset($options['pattern'])) { + throw new MissingOptionsException(\sprintf('The options "pattern" must be set for constraint "%s".', self::class), ['pattern']); + } + if (\is_array($pattern)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($pattern, $options ?? []); $pattern = $options['pattern'] ?? null; - } elseif (null !== $pattern) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } + } elseif (\is_array($options)) { + trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } parent::__construct($options, $groups, $payload); diff --git a/Constraints/Sequentially.php b/Constraints/Sequentially.php index e72e58170..2fe6615d2 100644 --- a/Constraints/Sequentially.php +++ b/Constraints/Sequentially.php @@ -13,6 +13,7 @@ use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * Use this constraint to sequentially validate nested constraints. @@ -32,6 +33,10 @@ class Sequentially extends Composite #[HasNamedArguments] public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null) { + if (null === $constraints || [] === $constraints) { + throw new MissingOptionsException(\sprintf('The options "constraints" must be set for constraint "%s".', self::class), ['constraints']); + } + if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = $constraints; diff --git a/Constraints/Type.php b/Constraints/Type.php index 7e07a6fcb..84e743b56 100644 --- a/Constraints/Type.php +++ b/Constraints/Type.php @@ -13,6 +13,7 @@ use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * Validates that a value is of a specific data type. @@ -39,6 +40,10 @@ class Type extends Constraint #[HasNamedArguments] public function __construct(string|array|null $type, ?string $message = null, ?array $groups = null, mixed $payload = null, ?array $options = null) { + if (null === $type && !isset($options['type'])) { + throw new MissingOptionsException(\sprintf('The options "type" must be set for constraint "%s".', self::class), ['type']); + } + if (\is_array($type) && \is_string(key($type))) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); diff --git a/Constraints/When.php b/Constraints/When.php index fbe9b84b7..c0c94c077 100644 --- a/Constraints/When.php +++ b/Constraints/When.php @@ -16,6 +16,7 @@ use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\LogicException; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * Conditionally apply validation constraints based on an expression using the ExpressionLanguage syntax. @@ -59,6 +60,10 @@ public function __construct(string|Expression|array|\Closure $expression, array| } $options['otherwise'] = $otherwise; } else { + if (null === $constraints) { + throw new MissingOptionsException(\sprintf('The options "constraints" must be set for constraint "%s".', self::class), ['constraints']); + } + $this->expression = $expression; $this->constraints = $constraints; $this->otherwise = $otherwise; diff --git a/Tests/Constraints/CardSchemeTest.php b/Tests/Constraints/CardSchemeTest.php index a50930b9b..154d35a25 100644 --- a/Tests/Constraints/CardSchemeTest.php +++ b/Tests/Constraints/CardSchemeTest.php @@ -46,6 +46,16 @@ public function testMissingSchemes() new CardScheme(null); } + + /** + * @group legacy + */ + public function testSchemesInOptionsArray() + { + $constraint = new CardScheme(null, options: ['schemes' => [CardScheme::MASTERCARD]]); + + $this->assertSame([CardScheme::MASTERCARD], $constraint->schemes); + } } class CardSchemeDummy diff --git a/Tests/Constraints/ExpressionTest.php b/Tests/Constraints/ExpressionTest.php index 9f7172f40..22e5c624e 100644 --- a/Tests/Constraints/ExpressionTest.php +++ b/Tests/Constraints/ExpressionTest.php @@ -73,6 +73,16 @@ public function testInitializeWithOptionsArray() $this->assertSame('!this.getParent().get("field2").getData()', $constraint->expression); } + + /** + * @group legacy + */ + public function testExpressionInOptionsArray() + { + $constraint = new Expression(null, options: ['expression' => '!this.getParent().get("field2").getData()']); + + $this->assertSame('!this.getParent().get("field2").getData()', $constraint->expression); + } } class ExpressionDummy diff --git a/Tests/Constraints/RegexTest.php b/Tests/Constraints/RegexTest.php index 853e0d785..5d3919ab8 100644 --- a/Tests/Constraints/RegexTest.php +++ b/Tests/Constraints/RegexTest.php @@ -158,6 +158,16 @@ public function testMissingPatternDoctrineStyle() new Regex([]); } + + /** + * @group legacy + */ + public function testPatternInOptionsArray() + { + $constraint = new Regex(null, options: ['pattern' => '/^[0-9]+$/']); + + $this->assertSame('/^[0-9]+$/', $constraint->pattern); + } } class RegexDummy diff --git a/Tests/Constraints/TypeTest.php b/Tests/Constraints/TypeTest.php index 73acddd43..a56cc514c 100644 --- a/Tests/Constraints/TypeTest.php +++ b/Tests/Constraints/TypeTest.php @@ -45,6 +45,16 @@ public function testMissingType() new Type(null); } + + /** + * @group legacy + */ + public function testTypeInOptionsArray() + { + $constraint = new Type(null, options: ['type' => 'digit']); + + $this->assertSame('digit', $constraint->type); + } } class TypeDummy diff --git a/Tests/Constraints/WhenTest.php b/Tests/Constraints/WhenTest.php index 6f82c6429..21d606701 100644 --- a/Tests/Constraints/WhenTest.php +++ b/Tests/Constraints/WhenTest.php @@ -154,4 +154,18 @@ public function testAttributesWithClosure() self::assertSame([], $fooConstraint->otherwise); self::assertSame(['Default', 'WhenTestWithClosure'], $fooConstraint->groups); } + + /** + * @group legacy + */ + public function testConstraintsInOptionsArray() + { + $constraints = [ + new NotNull(), + new Length(min: 10), + ]; + $constraint = new When('true', options: ['constraints' => $constraints]); + + $this->assertSame($constraints, $constraint->constraints); + } } From d2401db305962f1bad03a8c27aae69200b9c9886 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 17 Jul 2025 19:03:41 +0200 Subject: [PATCH 14/57] Remove legacy code paths that rely on feature checks --- .../NoSuspiciousCharactersValidator.php | 19 +----- Mapping/Loader/PropertyInfoLoader.php | 35 +---------- Tests/Constraints/FileValidatorTestCase.php | 58 +++++++++---------- Tests/Constraints/ImageValidatorTest.php | 9 --- 4 files changed, 33 insertions(+), 88 deletions(-) diff --git a/Constraints/NoSuspiciousCharactersValidator.php b/Constraints/NoSuspiciousCharactersValidator.php index d82a62d57..a209b9628 100644 --- a/Constraints/NoSuspiciousCharactersValidator.php +++ b/Constraints/NoSuspiciousCharactersValidator.php @@ -75,24 +75,9 @@ public function validate(mixed $value, Constraint $constraint): void } $checker = new \Spoofchecker(); - $checks = $constraint->checks; - - if (method_exists($checker, 'setRestrictionLevel')) { - $checks |= self::CHECK_RESTRICTION_LEVEL; - $checker->setRestrictionLevel($constraint->restrictionLevel ?? NoSuspiciousCharacters::RESTRICTION_LEVEL_MODERATE); - } elseif (NoSuspiciousCharacters::RESTRICTION_LEVEL_MINIMAL === $constraint->restrictionLevel) { - $checks |= self::CHECK_CHAR_LIMIT; - } elseif (NoSuspiciousCharacters::RESTRICTION_LEVEL_SINGLE_SCRIPT === $constraint->restrictionLevel) { - $checks |= self::CHECK_SINGLE_SCRIPT | self::CHECK_CHAR_LIMIT; - } elseif ($constraint->restrictionLevel) { - throw new LogicException('You can only use one of RESTRICTION_LEVEL_NONE, RESTRICTION_LEVEL_MINIMAL or RESTRICTION_LEVEL_SINGLE_SCRIPT with intl compiled against ICU < 58.'); - } else { - $checks |= self::CHECK_SINGLE_SCRIPT; - } - + $checker->setRestrictionLevel($constraint->restrictionLevel ?? NoSuspiciousCharacters::RESTRICTION_LEVEL_MODERATE); $checker->setAllowedLocales(implode(',', $constraint->locales ?? $this->defaultLocales)); - - $checker->setChecks($checks); + $checker->setChecks($constraint->checks | self::CHECK_RESTRICTION_LEVEL); if (!$checker->isSuspicious($value, $errorCode)) { return; diff --git a/Mapping/Loader/PropertyInfoLoader.php b/Mapping/Loader/PropertyInfoLoader.php index 6e6199153..1d20201b6 100644 --- a/Mapping/Loader/PropertyInfoLoader.php +++ b/Mapping/Loader/PropertyInfoLoader.php @@ -109,20 +109,10 @@ public function loadClassMetadata(ClassMetadata $metadata): bool continue; } - // BC layer for type-info < 7.2 - if (!class_exists(NullableType::class)) { - $nullable = false; + $nullable = $type->isNullable(); - if ($type instanceof UnionType && $type->isNullable()) { - $nullable = true; - $type = $type->asNonNullable(); - } - } else { - $nullable = $type->isNullable(); - - if ($type instanceof NullableType) { - $type = $type->getWrappedType(); - } + if ($type instanceof NullableType) { + $type = $type->getWrappedType(); } if ($type instanceof NullableType) { @@ -147,25 +137,6 @@ public function loadClassMetadata(ClassMetadata $metadata): bool private function getTypeConstraint(TypeInfoType $type): ?Type { - // BC layer for type-info < 7.2 - if (!interface_exists(CompositeTypeInterface::class)) { - if ($type instanceof UnionType || $type instanceof IntersectionType) { - return ($type->isA(TypeIdentifier::INT) || $type->isA(TypeIdentifier::FLOAT) || $type->isA(TypeIdentifier::STRING) || $type->isA(TypeIdentifier::BOOL)) ? new Type(['type' => 'scalar']) : null; - } - - $baseType = $type->getBaseType(); - - if ($baseType instanceof ObjectType) { - return new Type(type: $baseType->getClassName()); - } - - if (TypeIdentifier::MIXED !== $baseType->getTypeIdentifier()) { - return new Type(type: $baseType->getTypeIdentifier()->value); - } - - return null; - } - if ($type instanceof CompositeTypeInterface) { return $type->isIdentifiedBy( TypeIdentifier::INT, diff --git a/Tests/Constraints/FileValidatorTestCase.php b/Tests/Constraints/FileValidatorTestCase.php index b1ebf530e..585e56b87 100644 --- a/Tests/Constraints/FileValidatorTestCase.php +++ b/Tests/Constraints/FileValidatorTestCase.php @@ -500,36 +500,34 @@ public static function uploadedFileErrorProvider() [(string) \UPLOAD_ERR_EXTENSION, 'uploadExtensionErrorMessage'], ]; - if (class_exists(UploadedFile::class)) { - // when no maxSize is specified on constraint, it should use the ini value - $tests[] = [(string) \UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', [ - '{{ limit }}' => UploadedFile::getMaxFilesize() / 1048576, - '{{ suffix }}' => 'MiB', - ]]; - - // it should use the smaller limitation (maxSize option in this case) - $tests[] = [(string) \UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', [ - '{{ limit }}' => 1, - '{{ suffix }}' => 'bytes', - ], '1']; - - // access FileValidator::factorizeSizes() private method to format max file size - $reflection = new \ReflectionClass(new FileValidator()); - $method = $reflection->getMethod('factorizeSizes'); - [, $limit, $suffix] = $method->invokeArgs(new FileValidator(), [0, UploadedFile::getMaxFilesize(), false]); - - // it correctly parses the maxSize option and not only uses simple string comparison - // 1000G should be bigger than the ini value - $tests[] = [(string) \UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', [ - '{{ limit }}' => $limit, - '{{ suffix }}' => $suffix, - ], '1000G']; - - $tests[] = [(string) \UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', [ - '{{ limit }}' => '100', - '{{ suffix }}' => 'kB', - ], '100K']; - } + // when no maxSize is specified on constraint, it should use the ini value + $tests[] = [(string) \UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', [ + '{{ limit }}' => UploadedFile::getMaxFilesize() / 1048576, + '{{ suffix }}' => 'MiB', + ]]; + + // it should use the smaller limitation (maxSize option in this case) + $tests[] = [(string) \UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', [ + '{{ limit }}' => 1, + '{{ suffix }}' => 'bytes', + ], '1']; + + // access FileValidator::factorizeSizes() private method to format max file size + $reflection = new \ReflectionClass(new FileValidator()); + $method = $reflection->getMethod('factorizeSizes'); + [, $limit, $suffix] = $method->invokeArgs(new FileValidator(), [0, UploadedFile::getMaxFilesize(), false]); + + // it correctly parses the maxSize option and not only uses simple string comparison + // 1000G should be bigger than the ini value + $tests[] = [(string) \UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', [ + '{{ limit }}' => $limit, + '{{ suffix }}' => $suffix, + ], '1000G']; + + $tests[] = [(string) \UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', [ + '{{ limit }}' => '100', + '{{ suffix }}' => 'kB', + ], '100K']; return $tests; } diff --git a/Tests/Constraints/ImageValidatorTest.php b/Tests/Constraints/ImageValidatorTest.php index 7a7aa9197..f5d712208 100644 --- a/Tests/Constraints/ImageValidatorTest.php +++ b/Tests/Constraints/ImageValidatorTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; use Symfony\Component\HttpFoundation\File\File; -use Symfony\Component\Mime\MimeTypes; use Symfony\Component\Validator\Constraints\Image; use Symfony\Component\Validator\Constraints\ImageValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -696,10 +695,6 @@ public static function provideSvgWithoutViolation(): iterable */ public function testExtensionValid(string $name) { - if (!class_exists(MimeTypes::class)) { - $this->markTestSkipped('Guessing the mime type is not possible'); - } - $constraint = new Image(mimeTypes: [], extensions: ['gif'], extensionsMessage: 'myMessage'); $this->validator->validate(new File(__DIR__.'/Fixtures/'.$name), $constraint); @@ -742,10 +737,6 @@ public static function provideInvalidExtension(): iterable public function testExtensionAutodetectMimeTypesInvalid() { - if (!class_exists(MimeTypes::class)) { - $this->markTestSkipped('Guessing the mime type is not possible'); - } - $path = __DIR__.'/Fixtures/invalid-content.gif'; $constraint = new Image(mimeTypesMessage: 'myMessage', extensions: ['gif']); From 2aff3f8760533928bd05e5d210dec3b2d5320042 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 25 Jul 2025 22:48:43 +0200 Subject: [PATCH 15/57] remove docblocks for deprecated argument types --- CHANGELOG.md | 37 +++++++++++--------------- Constraints/All.php | 4 +-- Constraints/AtLeastOneOf.php | 10 +++---- Constraints/Bic.php | 1 - Constraints/Blank.php | 3 +-- Constraints/Callback.php | 4 +-- Constraints/CardScheme.php | 5 ++-- Constraints/Cascade.php | 3 +-- Constraints/Collection.php | 8 +++--- Constraints/Count.php | 12 ++++----- Constraints/Country.php | 5 ++-- Constraints/CssColor.php | 5 ++-- Constraints/Currency.php | 3 +-- Constraints/Date.php | 3 +-- Constraints/DateTime.php | 5 ++-- Constraints/DisableAutoMapping.php | 3 --- Constraints/Email.php | 3 +-- Constraints/EnableAutoMapping.php | 3 --- Constraints/Expression.php | 9 +++---- Constraints/ExpressionSyntax.php | 7 +++-- Constraints/File.php | 1 - Constraints/Hostname.php | 5 ++-- Constraints/Iban.php | 3 +-- Constraints/Image.php | 1 - Constraints/Ip.php | 1 - Constraints/IsFalse.php | 3 +-- Constraints/IsNull.php | 3 +-- Constraints/IsTrue.php | 3 +-- Constraints/Isbn.php | 7 +++-- Constraints/Isin.php | 3 +-- Constraints/Issn.php | 7 +++-- Constraints/Json.php | 3 +-- Constraints/Language.php | 5 ++-- Constraints/Length.php | 15 +++++------ Constraints/Locale.php | 5 ++-- Constraints/Luhn.php | 3 +-- Constraints/NoSuspiciousCharacters.php | 1 - Constraints/NotBlank.php | 5 ++-- Constraints/NotCompromisedPassword.php | 7 +++-- Constraints/NotNull.php | 3 +-- Constraints/PasswordStrength.php | 5 ++-- Constraints/Range.php | 1 - Constraints/Regex.php | 9 +++---- Constraints/Sequentially.php | 4 +-- Constraints/Time.php | 5 ++-- Constraints/Timezone.php | 9 +++---- Constraints/Traverse.php | 2 +- Constraints/Type.php | 5 ++-- Constraints/Ulid.php | 5 ++-- Constraints/Unique.php | 5 ++-- Constraints/Url.php | 9 +++---- Constraints/Uuid.php | 1 - Constraints/Valid.php | 5 ++-- Constraints/When.php | 11 ++++---- 54 files changed, 119 insertions(+), 174 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc7c083bc..a57b3c190 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,16 +31,14 @@ CHANGELOG class CustomConstraint extends Constraint { - public $option1; - public $option2; - #[HasNamedArguments] - public function __construct($option1 = null, $option2 = null, ?array $groups = null, mixed $payload = null) - { + public function __construct( + public $option1 = null, + public $option2 = null, + ?array $groups = null, + mixed $payload = null, + ) { parent::__construct(null, $groups, $payload); - - $this->option1 = $option1; - $this->option2 = $option2; } } ``` @@ -74,16 +72,14 @@ CHANGELOG class CustomConstraint extends Constraint { - public $option1; - public $option2; - #[HasNamedArguments] - public function __construct($option1, $option2 = null, ?array $groups = null, mixed $payload = null) - { + public function __construct( + public $option1, + public $option2 = null, + ?array $groups = null, + mixed $payload = null, + ) { parent::__construct(null, $groups, $payload); - - $this->option1 = $option1; - $this->option2 = $option2; } } ``` @@ -118,13 +114,12 @@ CHANGELOG class CustomCompositeConstraint extends Composite { - public array $constraints = []; - #[HasNamedArguments] - public function __construct(array $constraints, ?array $groups = null, mixed $payload = null) + public function __construct( + public array $constraints, + ?array $groups = null, + mixed $payload = null) { - $this->constraints = $constraints; - parent::__construct(null, $groups, $payload); } } diff --git a/Constraints/All.php b/Constraints/All.php index 64c6d53be..533599ad0 100644 --- a/Constraints/All.php +++ b/Constraints/All.php @@ -27,8 +27,8 @@ class All extends Composite public array|Constraint $constraints = []; /** - * @param array|array|Constraint|null $constraints - * @param string[]|null $groups + * @param array|Constraint|null $constraints + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/AtLeastOneOf.php b/Constraints/AtLeastOneOf.php index 92f3cc60e..bc99b3385 100644 --- a/Constraints/AtLeastOneOf.php +++ b/Constraints/AtLeastOneOf.php @@ -35,11 +35,11 @@ class AtLeastOneOf extends Composite public bool $includeInternalMessages = true; /** - * @param array|array|null $constraints An array of validation constraints - * @param string[]|null $groups - * @param string|null $message Intro of the failure message that will be followed by the failed constraint(s) message(s) - * @param string|null $messageCollection Failure message for All and Collection inner constraints - * @param bool|null $includeInternalMessages Whether to include inner constraint messages (defaults to true) + * @param array|null $constraints An array of validation constraints + * @param string[]|null $groups + * @param string|null $message Intro of the failure message that will be followed by the failed constraint(s) message(s) + * @param string|null $messageCollection Failure message for All and Collection inner constraints + * @param bool|null $includeInternalMessages Whether to include inner constraint messages (defaults to true) */ #[HasNamedArguments] public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null, ?string $message = null, ?string $messageCollection = null, ?bool $includeInternalMessages = null) diff --git a/Constraints/Bic.php b/Constraints/Bic.php index 5390d5556..ef1ae1660 100644 --- a/Constraints/Bic.php +++ b/Constraints/Bic.php @@ -65,7 +65,6 @@ class Bic extends Constraint public string $mode = self::VALIDATION_MODE_STRICT; /** - * @param array|null $options * @param string|null $iban An IBAN value to validate that its country code is the same as the BIC's one * @param string|null $ibanPropertyPath Property path to the IBAN value when validating objects * @param string[]|null $groups diff --git a/Constraints/Blank.php b/Constraints/Blank.php index cc0f648b2..b03586933 100644 --- a/Constraints/Blank.php +++ b/Constraints/Blank.php @@ -31,8 +31,7 @@ class Blank extends Constraint public string $message = 'This value should be blank.'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/Callback.php b/Constraints/Callback.php index f11f4c37f..f38aa9899 100644 --- a/Constraints/Callback.php +++ b/Constraints/Callback.php @@ -28,8 +28,8 @@ class Callback extends Constraint public $callback; /** - * @param string|string[]|callable|array|null $callback The callback definition - * @param string[]|null $groups + * @param string|string[]|callable|null $callback The callback definition + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(array|string|callable|null $callback = null, ?array $groups = null, mixed $payload = null, ?array $options = null) diff --git a/Constraints/CardScheme.php b/Constraints/CardScheme.php index c13ede0f9..706969796 100644 --- a/Constraints/CardScheme.php +++ b/Constraints/CardScheme.php @@ -49,9 +49,8 @@ class CardScheme extends Constraint public array|string|null $schemes = null; /** - * @param non-empty-string|non-empty-string[]|array|null $schemes Name(s) of the number scheme(s) used to validate the credit card number - * @param string[]|null $groups - * @param array|null $options + * @param non-empty-string|non-empty-string[]|null $schemes Name(s) of the number scheme(s) used to validate the credit card number + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(array|string|null $schemes, ?string $message = null, ?array $groups = null, mixed $payload = null, ?array $options = null) diff --git a/Constraints/Cascade.php b/Constraints/Cascade.php index 97ecdf655..86419d7e6 100644 --- a/Constraints/Cascade.php +++ b/Constraints/Cascade.php @@ -26,8 +26,7 @@ class Cascade extends Constraint public array $exclude = []; /** - * @param non-empty-string[]|non-empty-string|array|null $exclude Properties excluded from validation - * @param array|null $options + * @param non-empty-string[]|non-empty-string|null $exclude Properties excluded from validation */ #[HasNamedArguments] public function __construct(array|string|null $exclude = null, ?array $options = null) diff --git a/Constraints/Collection.php b/Constraints/Collection.php index 174291da6..cfd3bef55 100644 --- a/Constraints/Collection.php +++ b/Constraints/Collection.php @@ -38,10 +38,10 @@ class Collection extends Composite public string $missingFieldsMessage = 'This field is missing.'; /** - * @param array|array|null $fields An associative array defining keys in the collection and their constraints - * @param string[]|null $groups - * @param bool|null $allowExtraFields Whether to allow additional keys not declared in the configured fields (defaults to false) - * @param bool|null $allowMissingFields Whether to allow the collection to lack some fields declared in the configured fields (defaults to false) + * @param array|null $fields An associative array defining keys in the collection and their constraints + * @param string[]|null $groups + * @param bool|null $allowExtraFields Whether to allow additional keys not declared in the configured fields (defaults to false) + * @param bool|null $allowMissingFields Whether to allow the collection to lack some fields declared in the configured fields (defaults to false) */ #[HasNamedArguments] public function __construct(mixed $fields = null, ?array $groups = null, mixed $payload = null, ?bool $allowExtraFields = null, ?bool $allowMissingFields = null, ?string $extraFieldsMessage = null, ?string $missingFieldsMessage = null) diff --git a/Constraints/Count.php b/Constraints/Count.php index 9a26cc008..c947c9225 100644 --- a/Constraints/Count.php +++ b/Constraints/Count.php @@ -44,12 +44,12 @@ class Count extends Constraint public ?int $divisibleBy = null; /** - * @param int<0, max>|array|null $exactly The exact expected number of elements - * @param int<0, max>|null $min Minimum expected number of elements - * @param int<0, max>|null $max Maximum expected number of elements - * @param positive-int|null $divisibleBy The number the collection count should be divisible by - * @param string[]|null $groups - * @param array|null $options + * @param int<0, max>|null $exactly The exact expected number of elements + * @param int<0, max>|null $min Minimum expected number of elements + * @param int<0, max>|null $max Maximum expected number of elements + * @param positive-int|null $divisibleBy The number the collection count should be divisible by + * @param string[]|null $groups + * @param array|null $options */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Country.php b/Constraints/Country.php index 135f996dd..89d4717b4 100644 --- a/Constraints/Country.php +++ b/Constraints/Country.php @@ -36,9 +36,8 @@ class Country extends Constraint public bool $alpha3 = false; /** - * @param array|null $options - * @param bool|null $alpha3 Whether to check for alpha-3 codes instead of alpha-2 (defaults to false) - * @param string[]|null $groups + * @param bool|null $alpha3 Whether to check for alpha-3 codes instead of alpha-2 (defaults to false) + * @param string[]|null $groups * * @see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3#Current_codes */ diff --git a/Constraints/CssColor.php b/Constraints/CssColor.php index 1c23a6df6..0e87e20db 100644 --- a/Constraints/CssColor.php +++ b/Constraints/CssColor.php @@ -63,9 +63,8 @@ class CssColor extends Constraint public array|string $formats; /** - * @param non-empty-string[]|non-empty-string|array $formats The types of CSS colors allowed ({@see https://symfony.com/doc/current/reference/constraints/CssColor.html#formats}) - * @param string[]|null $groups - * @param array|null $options + * @param non-empty-string[]|non-empty-string $formats The types of CSS colors allowed ({@see https://symfony.com/doc/current/reference/constraints/CssColor.html#formats}) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(array|string $formats = [], ?string $message = null, ?array $groups = null, $payload = null, ?array $options = null) diff --git a/Constraints/Currency.php b/Constraints/Currency.php index c8f6417b3..678538a8a 100644 --- a/Constraints/Currency.php +++ b/Constraints/Currency.php @@ -36,8 +36,7 @@ class Currency extends Constraint public string $message = 'This value is not a valid currency.'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/Date.php b/Constraints/Date.php index adb48474f..f2ae75691 100644 --- a/Constraints/Date.php +++ b/Constraints/Date.php @@ -35,8 +35,7 @@ class Date extends Constraint public string $message = 'This value is not a valid date.'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/DateTime.php b/Constraints/DateTime.php index 3cf906269..f9e94f0c2 100644 --- a/Constraints/DateTime.php +++ b/Constraints/DateTime.php @@ -38,9 +38,8 @@ class DateTime extends Constraint public string $message = 'This value is not a valid datetime.'; /** - * @param non-empty-string|array|null $format The datetime format to match (defaults to 'Y-m-d H:i:s') - * @param string[]|null $groups - * @param array|null $options + * @param non-empty-string|null $format The datetime format to match (defaults to 'Y-m-d H:i:s') + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(string|array|null $format = null, ?string $message = null, ?array $groups = null, mixed $payload = null, ?array $options = null) diff --git a/Constraints/DisableAutoMapping.php b/Constraints/DisableAutoMapping.php index 7cbea8b38..926d8be25 100644 --- a/Constraints/DisableAutoMapping.php +++ b/Constraints/DisableAutoMapping.php @@ -26,9 +26,6 @@ #[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::TARGET_CLASS)] class DisableAutoMapping extends Constraint { - /** - * @param array|null $options - */ #[HasNamedArguments] public function __construct(?array $options = null, mixed $payload = null) { diff --git a/Constraints/Email.php b/Constraints/Email.php index 4a66986b2..193384019 100644 --- a/Constraints/Email.php +++ b/Constraints/Email.php @@ -47,8 +47,7 @@ class Email extends Constraint public $normalizer; /** - * @param array|null $options - * @param self::VALIDATION_MODE_*|null $mode The pattern used to validate the email address; pass null to use the default mode configured for the EmailValidator + * @param self::VALIDATION_MODE_*|null $mode The pattern used to validate the email address; pass null to use the default mode configured for the EmailValidator * @param string[]|null $groups */ #[HasNamedArguments] diff --git a/Constraints/EnableAutoMapping.php b/Constraints/EnableAutoMapping.php index 873430677..58e77805a 100644 --- a/Constraints/EnableAutoMapping.php +++ b/Constraints/EnableAutoMapping.php @@ -26,9 +26,6 @@ #[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::TARGET_CLASS)] class EnableAutoMapping extends Constraint { - /** - * @param array|null $options - */ #[HasNamedArguments] public function __construct(?array $options = null, mixed $payload = null) { diff --git a/Constraints/Expression.php b/Constraints/Expression.php index 71e20e448..ee3c2dd93 100644 --- a/Constraints/Expression.php +++ b/Constraints/Expression.php @@ -41,11 +41,10 @@ class Expression extends Constraint public bool $negate = true; /** - * @param string|ExpressionObject|array|null $expression The expression to evaluate - * @param array|null $values The values of the custom variables used in the expression (defaults to an empty array) - * @param string[]|null $groups - * @param array|null $options - * @param bool|null $negate Whether to fail if the expression evaluates to true (defaults to false) + * @param string|ExpressionObject|null $expression The expression to evaluate + * @param array|null $values The values of the custom variables used in the expression (defaults to an empty array) + * @param string[]|null $groups + * @param bool|null $negate Whether to fail if the expression evaluates to true (defaults to false) */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/ExpressionSyntax.php b/Constraints/ExpressionSyntax.php index 5a0a09de1..55ed3c542 100644 --- a/Constraints/ExpressionSyntax.php +++ b/Constraints/ExpressionSyntax.php @@ -33,10 +33,9 @@ class ExpressionSyntax extends Constraint public ?array $allowedVariables = null; /** - * @param array|null $options - * @param non-empty-string|null $service The service used to validate the constraint instead of the default one - * @param string[]|null $allowedVariables Restrict the available variables in the expression to these values (defaults to null that allows any variable) - * @param string[]|null $groups + * @param non-empty-string|null $service The service used to validate the constraint instead of the default one + * @param string[]|null $allowedVariables Restrict the available variables in the expression to these values (defaults to null that allows any variable) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?string $service = null, ?array $allowedVariables = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/File.php b/Constraints/File.php index 7d93a2084..0e436dc9e 100644 --- a/Constraints/File.php +++ b/Constraints/File.php @@ -91,7 +91,6 @@ class File extends Constraint protected int|string|null $maxSize = null; /** - * @param array|null $options * @param positive-int|string|null $maxSize The max size of the underlying file * @param bool|null $binaryFormat Pass true to use binary-prefixed units (KiB, MiB, etc.) or false to use SI-prefixed units (kB, MB) in displayed messages. Pass null to guess the format from the maxSize option. (defaults to null) * @param string[]|string|null $mimeTypes Acceptable media type(s). Prefer the extensions option that also enforce the file's extension consistency. diff --git a/Constraints/Hostname.php b/Constraints/Hostname.php index ca9bc3a32..f388c950c 100644 --- a/Constraints/Hostname.php +++ b/Constraints/Hostname.php @@ -32,9 +32,8 @@ class Hostname extends Constraint public bool $requireTld = true; /** - * @param array|null $options - * @param bool|null $requireTld Whether to require the hostname to include its top-level domain (defaults to true) - * @param string[]|null $groups + * @param bool|null $requireTld Whether to require the hostname to include its top-level domain (defaults to true) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Iban.php b/Constraints/Iban.php index 459fb5fb0..4898155c1 100644 --- a/Constraints/Iban.php +++ b/Constraints/Iban.php @@ -43,8 +43,7 @@ class Iban extends Constraint public string $message = 'This is not a valid International Bank Account Number (IBAN).'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/Image.php b/Constraints/Image.php index d9b7c8822..b47dc8ba6 100644 --- a/Constraints/Image.php +++ b/Constraints/Image.php @@ -91,7 +91,6 @@ class Image extends File public string $corruptedMessage = 'The image file is corrupted.'; /** - * @param array|null $options * @param positive-int|string|null $maxSize The max size of the underlying file * @param bool|null $binaryFormat Pass true to use binary-prefixed units (KiB, MiB, etc.) or false to use SI-prefixed units (kB, MB) in displayed messages. Pass null to guess the format from the maxSize option. (defaults to null) * @param non-empty-string[]|null $mimeTypes Acceptable media types diff --git a/Constraints/Ip.php b/Constraints/Ip.php index 4db552a76..91f247156 100644 --- a/Constraints/Ip.php +++ b/Constraints/Ip.php @@ -108,7 +108,6 @@ class Ip extends Constraint public $normalizer; /** - * @param array|null $options * @param self::V4*|self::V6*|self::ALL*|null $version The IP version to validate (defaults to {@see self::V4}) * @param string[]|null $groups */ diff --git a/Constraints/IsFalse.php b/Constraints/IsFalse.php index aa19d191d..722f2a247 100644 --- a/Constraints/IsFalse.php +++ b/Constraints/IsFalse.php @@ -31,8 +31,7 @@ class IsFalse extends Constraint public string $message = 'This value should be false.'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/IsNull.php b/Constraints/IsNull.php index 4aac68b4f..7447aed9f 100644 --- a/Constraints/IsNull.php +++ b/Constraints/IsNull.php @@ -31,8 +31,7 @@ class IsNull extends Constraint public string $message = 'This value should be null.'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/IsTrue.php b/Constraints/IsTrue.php index ea20cc80d..58d25b594 100644 --- a/Constraints/IsTrue.php +++ b/Constraints/IsTrue.php @@ -31,8 +31,7 @@ class IsTrue extends Constraint public string $message = 'This value should be true.'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/Isbn.php b/Constraints/Isbn.php index 7e34cb53b..5251150f3 100644 --- a/Constraints/Isbn.php +++ b/Constraints/Isbn.php @@ -50,10 +50,9 @@ class Isbn extends Constraint public ?string $message = null; /** - * @param self::ISBN_*|array|null $type The type of ISBN to validate (i.e. {@see Isbn::ISBN_10}, {@see Isbn::ISBN_13} or null to accept both, defaults to null) - * @param string|null $message If defined, this message has priority over the others - * @param string[]|null $groups - * @param array|null $options + * @param self::ISBN_*|null $type The type of ISBN to validate (i.e. {@see Isbn::ISBN_10}, {@see Isbn::ISBN_13} or null to accept both, defaults to null) + * @param string|null $message If defined, this message has priority over the others + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Isin.php b/Constraints/Isin.php index 7bd9abe2d..821ec62d5 100644 --- a/Constraints/Isin.php +++ b/Constraints/Isin.php @@ -40,8 +40,7 @@ class Isin extends Constraint public string $message = 'This value is not a valid International Securities Identification Number (ISIN).'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/Issn.php b/Constraints/Issn.php index 048c18f5e..1c4ba88d0 100644 --- a/Constraints/Issn.php +++ b/Constraints/Issn.php @@ -46,10 +46,9 @@ class Issn extends Constraint public bool $requireHyphen = false; /** - * @param array|null $options - * @param bool|null $caseSensitive Whether to allow the value to end with a lowercase character (defaults to false) - * @param bool|null $requireHyphen Whether to require a hyphenated ISSN value (defaults to false) - * @param string[]|null $groups + * @param bool|null $caseSensitive Whether to allow the value to end with a lowercase character (defaults to false) + * @param bool|null $requireHyphen Whether to require a hyphenated ISSN value (defaults to false) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Json.php b/Constraints/Json.php index 18078a2fe..8798c94aa 100644 --- a/Constraints/Json.php +++ b/Constraints/Json.php @@ -31,8 +31,7 @@ class Json extends Constraint public string $message = 'This value should be valid JSON.'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/Language.php b/Constraints/Language.php index 61ac4644b..dfa91b4f7 100644 --- a/Constraints/Language.php +++ b/Constraints/Language.php @@ -36,9 +36,8 @@ class Language extends Constraint public bool $alpha3 = false; /** - * @param array|null $options - * @param bool|null $alpha3 Pass true to validate the language with three-letter code (ISO 639-2 (2T)) or false with two-letter code (ISO 639-1) (defaults to false) - * @param string[]|null $groups + * @param bool|null $alpha3 Pass true to validate the language with three-letter code (ISO 639-2 (2T)) or false with two-letter code (ISO 639-1) (defaults to false) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Length.php b/Constraints/Length.php index 6678e7dc1..3c7f93ae6 100644 --- a/Constraints/Length.php +++ b/Constraints/Length.php @@ -59,14 +59,13 @@ class Length extends Constraint public string $countUnit = self::COUNT_CODEPOINTS; /** - * @param positive-int|array|null $exactly The exact expected length - * @param int<0, max>|null $min The minimum expected length - * @param positive-int|null $max The maximum expected length - * @param string|null $charset The charset to be used when computing value's length (defaults to UTF-8) - * @param callable|null $normalizer A callable to normalize value before it is validated - * @param self::COUNT_*|null $countUnit The character count unit for the length check (defaults to {@see Length::COUNT_CODEPOINTS}) - * @param string[]|null $groups - * @param array|null $options + * @param positive-int|null $exactly The exact expected length + * @param int<0, max>|null $min The minimum expected length + * @param positive-int|null $max The maximum expected length + * @param string|null $charset The charset to be used when computing value's length (defaults to UTF-8) + * @param callable|null $normalizer A callable to normalize value before it is validated + * @param self::COUNT_*|null $countUnit The character count unit for the length check (defaults to {@see Length::COUNT_CODEPOINTS}) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Locale.php b/Constraints/Locale.php index 0ffe4b0e8..d309fecee 100644 --- a/Constraints/Locale.php +++ b/Constraints/Locale.php @@ -36,9 +36,8 @@ class Locale extends Constraint public bool $canonicalize = true; /** - * @param array|null $options - * @param bool|null $canonicalize Whether to canonicalize the value before validation (defaults to true) (see {@see https://www.php.net/manual/en/locale.canonicalize.php}) - * @param string[]|null $groups + * @param bool|null $canonicalize Whether to canonicalize the value before validation (defaults to true) (see {@see https://www.php.net/manual/en/locale.canonicalize.php}) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Luhn.php b/Constraints/Luhn.php index 9421fc3c7..f2e93a867 100644 --- a/Constraints/Luhn.php +++ b/Constraints/Luhn.php @@ -37,8 +37,7 @@ class Luhn extends Constraint public string $message = 'Invalid card number.'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/NoSuspiciousCharacters.php b/Constraints/NoSuspiciousCharacters.php index f0d28dba2..2a5ba530c 100644 --- a/Constraints/NoSuspiciousCharacters.php +++ b/Constraints/NoSuspiciousCharacters.php @@ -83,7 +83,6 @@ class NoSuspiciousCharacters extends Constraint public ?array $locales = null; /** - * @param array|null $options * @param int-mask-of|null $checks A bitmask of the checks to perform on the string (defaults to all checks) * @param int-mask-of|null $restrictionLevel Configures the set of acceptable characters for the validated string through a specified "level" (defaults to * {@see NoSuspiciousCharacters::RESTRICTION_LEVEL_MODERATE} on ICU >= 58, {@see NoSuspiciousCharacters::RESTRICTION_LEVEL_SINGLE_SCRIPT} otherwise) diff --git a/Constraints/NotBlank.php b/Constraints/NotBlank.php index f108021ba..f26f6aff8 100644 --- a/Constraints/NotBlank.php +++ b/Constraints/NotBlank.php @@ -36,9 +36,8 @@ class NotBlank extends Constraint public $normalizer; /** - * @param array|null $options - * @param bool|null $allowNull Whether to allow null values (defaults to false) - * @param string[]|null $groups + * @param bool|null $allowNull Whether to allow null values (defaults to false) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?bool $allowNull = null, ?callable $normalizer = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/NotCompromisedPassword.php b/Constraints/NotCompromisedPassword.php index ef1e03da9..8a6219580 100644 --- a/Constraints/NotCompromisedPassword.php +++ b/Constraints/NotCompromisedPassword.php @@ -33,10 +33,9 @@ class NotCompromisedPassword extends Constraint public bool $skipOnError = false; /** - * @param array|null $options - * @param positive-int|null $threshold The number of times the password should have been leaked to consider it is compromised (defaults to 1) - * @param bool|null $skipOnError Whether to ignore HTTP errors while requesting the API and thus consider the password valid (defaults to false) - * @param string[]|null $groups + * @param positive-int|null $threshold The number of times the password should have been leaked to consider it is compromised (defaults to 1) + * @param bool|null $skipOnError Whether to ignore HTTP errors while requesting the API and thus consider the password valid (defaults to false) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/NotNull.php b/Constraints/NotNull.php index e2c784ebb..b00c72bed 100644 --- a/Constraints/NotNull.php +++ b/Constraints/NotNull.php @@ -31,8 +31,7 @@ class NotNull extends Constraint public string $message = 'This value should not be null.'; /** - * @param array|null $options - * @param string[]|null $groups + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/PasswordStrength.php b/Constraints/PasswordStrength.php index 030d48141..7ad2b13fd 100644 --- a/Constraints/PasswordStrength.php +++ b/Constraints/PasswordStrength.php @@ -40,9 +40,8 @@ final class PasswordStrength extends Constraint public int $minScore; /** - * @param array|null $options - * @param self::STRENGTH_*|null $minScore The minimum required strength of the password (defaults to {@see PasswordStrength::STRENGTH_MEDIUM}) - * @param string[]|null $groups + * @param self::STRENGTH_*|null $minScore The minimum required strength of the password (defaults to {@see PasswordStrength::STRENGTH_MEDIUM}) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(?array $options = null, ?int $minScore = null, ?array $groups = null, mixed $payload = null, ?string $message = null) diff --git a/Constraints/Range.php b/Constraints/Range.php index e27dc3501..dff5bf06d 100644 --- a/Constraints/Range.php +++ b/Constraints/Range.php @@ -49,7 +49,6 @@ class Range extends Constraint public ?string $maxPropertyPath = null; /** - * @param array|null $options * @param string|null $invalidMessage The message if min and max values are numeric but the given value is not * @param string|null $invalidDateTimeMessage The message if min and max values are PHP datetimes but the given value is not * @param int|float|non-empty-string|null $min The minimum value, either numeric or a datetime string representation diff --git a/Constraints/Regex.php b/Constraints/Regex.php index 8c3881d84..8ab6d0619 100644 --- a/Constraints/Regex.php +++ b/Constraints/Regex.php @@ -38,11 +38,10 @@ class Regex extends Constraint public $normalizer; /** - * @param string|array|null $pattern The regular expression to match - * @param string|null $htmlPattern The pattern to use in the HTML5 pattern attribute - * @param bool|null $match Whether to validate the value matches the configured pattern or not (defaults to true) - * @param string[]|null $groups - * @param array|null $options + * @param string|null $pattern The regular expression to match + * @param string|null $htmlPattern The pattern to use in the HTML5 pattern attribute + * @param bool|null $match Whether to validate the value matches the configured pattern or not (defaults to true) + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Sequentially.php b/Constraints/Sequentially.php index 2fe6615d2..ff53be7af 100644 --- a/Constraints/Sequentially.php +++ b/Constraints/Sequentially.php @@ -27,8 +27,8 @@ class Sequentially extends Composite public array|Constraint $constraints = []; /** - * @param Constraint[]|array|null $constraints An array of validation constraints - * @param string[]|null $groups + * @param Constraint[]|null $constraints An array of validation constraints + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null) diff --git a/Constraints/Time.php b/Constraints/Time.php index a99702cb2..e166ec0ff 100644 --- a/Constraints/Time.php +++ b/Constraints/Time.php @@ -34,9 +34,8 @@ class Time extends Constraint public string $message = 'This value is not a valid time.'; /** - * @param array|null $options - * @param string[]|null $groups - * @param bool|null $withSeconds Whether to allow seconds in the given value (defaults to true) + * @param string[]|null $groups + * @param bool|null $withSeconds Whether to allow seconds in the given value (defaults to true) */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Timezone.php b/Constraints/Timezone.php index 193b35eeb..7c8297652 100644 --- a/Constraints/Timezone.php +++ b/Constraints/Timezone.php @@ -42,11 +42,10 @@ class Timezone extends Constraint ]; /** - * @param int|array|null $zone Restrict valid timezones to this geographical zone (defaults to {@see \DateTimeZone::ALL}) - * @param string|null $countryCode Restrict the valid timezones to this country if the zone option is {@see \DateTimeZone::PER_COUNTRY} - * @param bool|null $intlCompatible Whether to restrict valid timezones to ones available in PHP's intl (defaults to false) - * @param string[]|null $groups - * @param array|null $options + * @param int|null $zone Restrict valid timezones to this geographical zone (defaults to {@see \DateTimeZone::ALL}) + * @param string|null $countryCode Restrict the valid timezones to this country if the zone option is {@see \DateTimeZone::PER_COUNTRY} + * @param bool|null $intlCompatible Whether to restrict valid timezones to ones available in PHP's intl (defaults to false) + * @param string[]|null $groups * * @see \DateTimeZone */ diff --git a/Constraints/Traverse.php b/Constraints/Traverse.php index 63e8462c4..6571b31f1 100644 --- a/Constraints/Traverse.php +++ b/Constraints/Traverse.php @@ -26,7 +26,7 @@ class Traverse extends Constraint public bool $traverse = true; /** - * @param bool|array|null $traverse Whether to traverse the given object or not (defaults to true). Pass an associative array to configure the constraint's options (e.g. payload). + * @param bool|null $traverse Whether to traverse the given object or not (defaults to true). Pass an associative array to configure the constraint's options (e.g. payload). */ #[HasNamedArguments] public function __construct(bool|array|null $traverse = null, mixed $payload = null) diff --git a/Constraints/Type.php b/Constraints/Type.php index 84e743b56..4c119a8c7 100644 --- a/Constraints/Type.php +++ b/Constraints/Type.php @@ -33,9 +33,8 @@ class Type extends Constraint public string|array|null $type = null; /** - * @param string|list|array|null $type The type(s) to enforce on the value - * @param string[]|null $groups - * @param array|null $options + * @param string|list|null $type The type(s) to enforce on the value + * @param string[]|null $groups */ #[HasNamedArguments] public function __construct(string|array|null $type, ?string $message = null, ?array $groups = null, mixed $payload = null, ?array $options = null) diff --git a/Constraints/Ulid.php b/Constraints/Ulid.php index 91d395fd2..c9f9dbaf6 100644 --- a/Constraints/Ulid.php +++ b/Constraints/Ulid.php @@ -47,9 +47,8 @@ class Ulid extends Constraint public string $format = self::FORMAT_BASE_32; /** - * @param array|null $options - * @param string[]|null $groups - * @param self::FORMAT_*|null $format + * @param string[]|null $groups + * @param self::FORMAT_*|null $format */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Unique.php b/Constraints/Unique.php index 1e6503785..3794b192c 100644 --- a/Constraints/Unique.php +++ b/Constraints/Unique.php @@ -38,9 +38,8 @@ class Unique extends Constraint public $normalizer; /** - * @param array|null $options - * @param string[]|null $groups - * @param string[]|string|null $fields Defines the key or keys in the collection that should be checked for uniqueness (defaults to null, which ensure uniqueness for all keys) + * @param string[]|null $groups + * @param string[]|string|null $fields Defines the key or keys in the collection that should be checked for uniqueness (defaults to null, which ensure uniqueness for all keys) */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Url.php b/Constraints/Url.php index b3e7256a0..8a7549cb9 100644 --- a/Constraints/Url.php +++ b/Constraints/Url.php @@ -40,11 +40,10 @@ class Url extends Constraint public $normalizer; /** - * @param array|null $options - * @param string[]|null $protocols The protocols considered to be valid for the URL (e.g. http, https, ftp, etc.) (defaults to ['http', 'https'] - * @param bool|null $relativeProtocol Whether to accept URL without the protocol (i.e. //example.com) (defaults to false) - * @param string[]|null $groups - * @param bool|null $requireTld Whether to require the URL to include a top-level domain (defaults to false) + * @param string[]|null $protocols The protocols considered to be valid for the URL (e.g. http, https, ftp, etc.) (defaults to ['http', 'https'] + * @param bool|null $relativeProtocol Whether to accept URL without the protocol (i.e. //example.com) (defaults to false) + * @param string[]|null $groups + * @param bool|null $requireTld Whether to require the URL to include a top-level domain (defaults to false) */ #[HasNamedArguments] public function __construct( diff --git a/Constraints/Uuid.php b/Constraints/Uuid.php index 9c6526457..3602c2fb8 100644 --- a/Constraints/Uuid.php +++ b/Constraints/Uuid.php @@ -96,7 +96,6 @@ class Uuid extends Constraint public $normalizer; /** - * @param array|null $options * @param self::V*[]|self::V*|null $versions Specific UUID versions (defaults to {@see Uuid::ALL_VERSIONS}) * @param bool|null $strict Whether to force the value to follow the RFC's input format rules; pass false to allow alternate formats (defaults to true) * @param string[]|null $groups diff --git a/Constraints/Valid.php b/Constraints/Valid.php index 0e60574f1..6106627c6 100644 --- a/Constraints/Valid.php +++ b/Constraints/Valid.php @@ -25,9 +25,8 @@ class Valid extends Constraint public bool $traverse = true; /** - * @param array|null $options - * @param string[]|null $groups - * @param bool|null $traverse Whether to validate {@see \Traversable} objects (defaults to true) + * @param string[]|null $groups + * @param bool|null $traverse Whether to validate {@see \Traversable} objects (defaults to true) */ #[HasNamedArguments] public function __construct(?array $options = null, ?array $groups = null, $payload = null, ?bool $traverse = null) diff --git a/Constraints/When.php b/Constraints/When.php index c0c94c077..b7482f938 100644 --- a/Constraints/When.php +++ b/Constraints/When.php @@ -32,12 +32,11 @@ class When extends Composite public array|Constraint $otherwise = []; /** - * @param string|Expression|array|\Closure(object): bool $expression The condition to evaluate, either as a closure or using the ExpressionLanguage syntax - * @param Constraint[]|Constraint|null $constraints One or multiple constraints that are applied if the expression returns true - * @param array|null $values The values of the custom variables used in the expression (defaults to []) - * @param string[]|null $groups - * @param array|null $options - * @param Constraint[]|Constraint $otherwise One or multiple constraints that are applied if the expression returns false + * @param string|Expression|\Closure(object): bool $expression The condition to evaluate, either as a closure or using the ExpressionLanguage syntax + * @param Constraint[]|Constraint|null $constraints One or multiple constraints that are applied if the expression returns true + * @param array|null $values The values of the custom variables used in the expression (defaults to []) + * @param string[]|null $groups + * @param Constraint[]|Constraint $otherwise One or multiple constraints that are applied if the expression returns false */ #[HasNamedArguments] public function __construct(string|Expression|array|\Closure $expression, array|Constraint|null $constraints = null, ?array $values = null, ?array $groups = null, $payload = null, ?array $options = null, array|Constraint $otherwise = []) From 77ab6eccfe5a04b87ee33d5f0fce83c3765cd898 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Mon, 16 Jun 2025 16:37:14 +0200 Subject: [PATCH 16/57] [Validator] Add `min` and `max` in both error messages of `LengthValidator` --- CHANGELOG.md | 1 + Constraints/LengthValidator.php | 16 ++++++++++++++-- Tests/Constraints/LengthValidatorTest.php | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc7c083bc..5bd5b63c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.4 --- + * Add the `min` and `max` parameter to the `Length` constraint violation * Deprecate `getRequiredOptions()` and `getDefaultOption()` methods of the `All`, `AtLeastOneOf`, `CardScheme`, `Collection`, `CssColor`, `Expression`, `Regex`, `Sequentially`, `Type`, and `When` constraints * Deprecate evaluating options in the base `Constraint` class. Initialize properties in the constructor of the concrete constraint diff --git a/Constraints/LengthValidator.php b/Constraints/LengthValidator.php index 985660bc2..b30f6722d 100644 --- a/Constraints/LengthValidator.php +++ b/Constraints/LengthValidator.php @@ -71,9 +71,15 @@ public function validate(mixed $value, Constraint $constraint): void if (null !== $constraint->max && $length > $constraint->max) { $exactlyOptionEnabled = $constraint->min == $constraint->max; - $this->context->buildViolation($exactlyOptionEnabled ? $constraint->exactMessage : $constraint->maxMessage) + $builder = $this->context->buildViolation($exactlyOptionEnabled ? $constraint->exactMessage : $constraint->maxMessage); + if (null !== $constraint->min) { + $builder->setParameter('{{ min }}', $constraint->min); + } + + $builder ->setParameter('{{ value }}', $this->formatValue($stringValue)) ->setParameter('{{ limit }}', $constraint->max) + ->setParameter('{{ max }}', $constraint->max) // To be consistent with the min error message ->setParameter('{{ value_length }}', $length) ->setInvalidValue($value) ->setPlural($constraint->max) @@ -86,9 +92,15 @@ public function validate(mixed $value, Constraint $constraint): void if (null !== $constraint->min && $length < $constraint->min) { $exactlyOptionEnabled = $constraint->min == $constraint->max; - $this->context->buildViolation($exactlyOptionEnabled ? $constraint->exactMessage : $constraint->minMessage) + $builder = $this->context->buildViolation($exactlyOptionEnabled ? $constraint->exactMessage : $constraint->minMessage); + if (null !== $constraint->max) { + $builder->setParameter('{{ max }}', $constraint->max); + } + + $builder ->setParameter('{{ value }}', $this->formatValue($stringValue)) ->setParameter('{{ limit }}', $constraint->min) + ->setParameter('{{ min }}', $constraint->min) // To be consistent with the max error message ->setParameter('{{ value_length }}', $length) ->setInvalidValue($value) ->setPlural($constraint->min) diff --git a/Tests/Constraints/LengthValidatorTest.php b/Tests/Constraints/LengthValidatorTest.php index 10f61f50b..81351ffb2 100644 --- a/Tests/Constraints/LengthValidatorTest.php +++ b/Tests/Constraints/LengthValidatorTest.php @@ -40,6 +40,8 @@ public function testEmptyStringIsInvalid() $this->buildViolation('myMessage') ->setParameter('{{ value }}', '""') ->setParameter('{{ limit }}', $limit) + ->setParameter('{{ min }}', $limit) + ->setParameter('{{ max }}', $limit) ->setParameter('{{ value_length }}', 0) ->setInvalidValue('') ->setPlural($limit) @@ -196,6 +198,7 @@ public function testInvalidValuesMin(int|string $value, int $valueLength) $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"'.$value.'"') ->setParameter('{{ limit }}', 4) + ->setParameter('{{ min }}', 4) ->setParameter('{{ value_length }}', $valueLength) ->setInvalidValue($value) ->setPlural(4) @@ -215,6 +218,7 @@ public function testInvalidValuesMinNamed(int|string $value, int $valueLength) $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"'.$value.'"') ->setParameter('{{ limit }}', 4) + ->setParameter('{{ min }}', 4) ->setParameter('{{ value_length }}', $valueLength) ->setInvalidValue($value) ->setPlural(4) @@ -237,6 +241,7 @@ public function testInvalidValuesMax(int|string $value, int $valueLength) $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"'.$value.'"') ->setParameter('{{ limit }}', 4) + ->setParameter('{{ max }}', 4) ->setParameter('{{ value_length }}', $valueLength) ->setInvalidValue($value) ->setPlural(4) @@ -256,6 +261,7 @@ public function testInvalidValuesMaxNamed(int|string $value, int $valueLength) $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"'.$value.'"') ->setParameter('{{ limit }}', 4) + ->setParameter('{{ max }}', 4) ->setParameter('{{ value_length }}', $valueLength) ->setInvalidValue($value) ->setPlural(4) @@ -279,6 +285,8 @@ public function testInvalidValuesExactLessThanFour(int|string $value, int $value $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"'.$value.'"') ->setParameter('{{ limit }}', 4) + ->setParameter('{{ min }}', 4) + ->setParameter('{{ max }}', 4) ->setParameter('{{ value_length }}', $valueLength) ->setInvalidValue($value) ->setPlural(4) @@ -298,6 +306,8 @@ public function testInvalidValuesExactLessThanFourNamed(int|string $value, int $ $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"'.$value.'"') ->setParameter('{{ limit }}', 4) + ->setParameter('{{ min }}', 4) + ->setParameter('{{ max }}', 4) ->setParameter('{{ value_length }}', $valueLength) ->setInvalidValue($value) ->setPlural(4) @@ -321,6 +331,8 @@ public function testInvalidValuesExactMoreThanFour(int|string $value, int $value $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"'.$value.'"') ->setParameter('{{ limit }}', 4) + ->setParameter('{{ min }}', 4) + ->setParameter('{{ max }}', 4) ->setParameter('{{ value_length }}', $valueLength) ->setInvalidValue($value) ->setPlural(4) @@ -363,6 +375,8 @@ public function testInvalidValuesExactDefaultCountUnitWithGraphemeInput() $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"'."A\u{0300}".'"') ->setParameter('{{ limit }}', 1) + ->setParameter('{{ min }}', 1) + ->setParameter('{{ max }}', 1) ->setParameter('{{ value_length }}', 2) ->setInvalidValue("A\u{0300}") ->setPlural(1) @@ -379,6 +393,8 @@ public function testInvalidValuesExactBytesCountUnitWithGraphemeInput() $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"'."A\u{0300}".'"') ->setParameter('{{ limit }}', 1) + ->setParameter('{{ min }}', 1) + ->setParameter('{{ max }}', 1) ->setParameter('{{ value_length }}', 3) ->setInvalidValue("A\u{0300}") ->setPlural(1) From f604b0eae87e893526a4a1198e14d6ea66add4df Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 28 Jul 2025 08:32:50 +0200 Subject: [PATCH 17/57] deprecate passing choices as $options argument to Choice constraint --- CHANGELOG.md | 1 + Constraints/Choice.php | 1 + .../Constraints/AtLeastOneOfValidatorTest.php | 2 +- Tests/Constraints/ChoiceTest.php | 2 +- Tests/Constraints/ChoiceValidatorTest.php | 17 ++++++------ Tests/Mapping/Loader/XmlFileLoaderTest.php | 20 ++++++++++++-- Tests/Mapping/Loader/YamlFileLoaderTest.php | 20 ++++++++++++-- .../constraint-mapping-value-option.xml | 27 +++++++++++++++++++ .../constraint-mapping-value-option.yml | 10 +++++++ Tests/Mapping/Loader/constraint-mapping.xml | 11 -------- Tests/Mapping/Loader/constraint-mapping.yml | 5 ---- 11 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 Tests/Mapping/Loader/constraint-mapping-value-option.xml create mode 100644 Tests/Mapping/Loader/constraint-mapping-value-option.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index f635c68da..c95fc1b84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.4 --- + * Deprecate passing a list of choices to the first argument of the `Choice` constraint. Use the `choices` option instead * Add the `min` and `max` parameter to the `Length` constraint violation * Deprecate `getRequiredOptions()` and `getDefaultOption()` methods of the `All`, `AtLeastOneOf`, `CardScheme`, `Collection`, `CssColor`, `Expression`, `Regex`, `Sequentially`, `Type`, and `When` constraints diff --git a/Constraints/Choice.php b/Constraints/Choice.php index 8bc380735..cf353907d 100644 --- a/Constraints/Choice.php +++ b/Constraints/Choice.php @@ -85,6 +85,7 @@ public function __construct( ?bool $match = null, ) { if (\is_array($options) && $options && array_is_list($options)) { + trigger_deprecation('symfony/validator', '7.4', 'Support for passing the choices as the first argument to %s is deprecated.', static::class); $choices ??= $options; $options = null; } elseif (\is_array($options) && [] !== $options) { diff --git a/Tests/Constraints/AtLeastOneOfValidatorTest.php b/Tests/Constraints/AtLeastOneOfValidatorTest.php index 22b53dd13..59b737edc 100644 --- a/Tests/Constraints/AtLeastOneOfValidatorTest.php +++ b/Tests/Constraints/AtLeastOneOfValidatorTest.php @@ -317,7 +317,7 @@ public function testValidateNestedAtLeaseOneOfConstraints() new Collection([ 'bar' => new AtLeastOneOf([ new Type('int'), - new Choice(['test1', 'test2']), + new Choice(choices: ['test1', 'test2']), ]), ]), new Collection([ diff --git a/Tests/Constraints/ChoiceTest.php b/Tests/Constraints/ChoiceTest.php index 2173c45f5..ddfb31b11 100644 --- a/Tests/Constraints/ChoiceTest.php +++ b/Tests/Constraints/ChoiceTest.php @@ -66,7 +66,7 @@ class ChoiceDummy #[Choice(choices: ['foo', 'bar'], message: 'myMessage')] private $b; - #[Choice([1, 2], groups: ['my_group'], payload: 'some attached data')] + #[Choice(choices: [1, 2], groups: ['my_group'], payload: 'some attached data')] private $c; #[Choice(choices: ['one' => 1, 'two' => 2])] diff --git a/Tests/Constraints/ChoiceValidatorTest.php b/Tests/Constraints/ChoiceValidatorTest.php index 39affe442..acfbb8419 100644 --- a/Tests/Constraints/ChoiceValidatorTest.php +++ b/Tests/Constraints/ChoiceValidatorTest.php @@ -74,20 +74,21 @@ public function testValidCallbackExpected() $this->validator->validate('foobar', new Choice(callback: 'abcd')); } - /** - * @dataProvider provideConstraintsWithChoicesArray - */ - public function testValidChoiceArray(Choice $constraint) + public function testValidChoiceArray() { - $this->validator->validate('bar', $constraint); + $this->validator->validate('bar', new Choice(choices: ['foo', 'bar'])); $this->assertNoViolation(); } - public static function provideConstraintsWithChoicesArray(): iterable + /** + * @group legacy + */ + public function testValidChoiceArrayFirstArgument() { - yield 'first argument' => [new Choice(['foo', 'bar'])]; - yield 'named arguments' => [new Choice(choices: ['foo', 'bar'])]; + $this->validator->validate('bar', new Choice(['foo', 'bar'])); + + $this->assertNoViolation(); } /** diff --git a/Tests/Mapping/Loader/XmlFileLoaderTest.php b/Tests/Mapping/Loader/XmlFileLoaderTest.php index 08a4bb862..3b0872df2 100644 --- a/Tests/Mapping/Loader/XmlFileLoaderTest.php +++ b/Tests/Mapping/Loader/XmlFileLoaderTest.php @@ -22,6 +22,7 @@ use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Regex; use Symfony\Component\Validator\Constraints\Traverse; +use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; @@ -76,8 +77,6 @@ public function testLoadClassMetadata() $expected->addConstraint(new ConstraintWithNamedArguments(['foo', 'bar'])); $expected->addConstraint(new ConstraintWithoutValueWithNamedArguments(['foo'])); $expected->addPropertyConstraint('firstName', new NotNull()); - $expected->addPropertyConstraint('firstName', new Range(min: 3)); - $expected->addPropertyConstraint('firstName', new Choice(['A', 'B'])); $expected->addPropertyConstraint('firstName', new All(constraints: [new NotNull(), new Range(min: 3)])); $expected->addPropertyConstraint('firstName', new All(constraints: [new NotNull(), new Range(min: 3)])); $expected->addPropertyConstraint('firstName', new Collection(fields: [ @@ -95,6 +94,23 @@ public function testLoadClassMetadata() $this->assertEquals($expected, $metadata); } + /** + * @group legacy + */ + public function testLoadClassMetadataValueOption() + { + $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-value-option.xml'); + $metadata = new ClassMetadata(Entity::class); + + $loader->loadClassMetadata($metadata); + + $expected = new ClassMetadata(Entity::class); + $expected->addPropertyConstraint('firstName', new Type(type: 'string')); + $expected->addPropertyConstraint('firstName', new Choice(choices: ['A', 'B'])); + + $this->assertEquals($expected, $metadata); + } + public function testLoadClassMetadataWithNonStrings() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-non-strings.xml'); diff --git a/Tests/Mapping/Loader/YamlFileLoaderTest.php b/Tests/Mapping/Loader/YamlFileLoaderTest.php index c3bbcb18e..9cf77fc38 100644 --- a/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -20,6 +20,7 @@ use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Range; +use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; use Symfony\Component\Validator\Tests\Dummy\DummyGroupProvider; @@ -120,8 +121,6 @@ public function testLoadClassMetadata() $expected->addConstraint(new ConstraintWithNamedArguments('foo')); $expected->addConstraint(new ConstraintWithNamedArguments(['foo', 'bar'])); $expected->addPropertyConstraint('firstName', new NotNull()); - $expected->addPropertyConstraint('firstName', new Range(min: 3)); - $expected->addPropertyConstraint('firstName', new Choice(['A', 'B'])); $expected->addPropertyConstraint('firstName', new All(constraints: [new NotNull(), new Range(min: 3)])); $expected->addPropertyConstraint('firstName', new All(constraints: [new NotNull(), new Range(min: 3)])); $expected->addPropertyConstraint('firstName', new Collection(fields: [ @@ -139,6 +138,23 @@ public function testLoadClassMetadata() $this->assertEquals($expected, $metadata); } + /** + * @group legacy + */ + public function testLoadClassMetadataValueOption() + { + $loader = new YamlFileLoader(__DIR__.'/constraint-mapping-value-option.yml'); + $metadata = new ClassMetadata(Entity::class); + + $loader->loadClassMetadata($metadata); + + $expected = new ClassMetadata(Entity::class); + $expected->addPropertyConstraint('firstName', new Type(type: 'string')); + $expected->addPropertyConstraint('firstName', new Choice(choices: ['A', 'B'])); + + $this->assertEquals($expected, $metadata); + } + public function testLoadClassMetadataWithConstants() { $loader = new YamlFileLoader(__DIR__.'/mapping-with-constants.yml'); diff --git a/Tests/Mapping/Loader/constraint-mapping-value-option.xml b/Tests/Mapping/Loader/constraint-mapping-value-option.xml new file mode 100644 index 000000000..d0fea931d --- /dev/null +++ b/Tests/Mapping/Loader/constraint-mapping-value-option.xml @@ -0,0 +1,27 @@ + + + + + Symfony\Component\Validator\Tests\Fixtures\ + + + + + + + + + string + + + + A + B + + + + + + diff --git a/Tests/Mapping/Loader/constraint-mapping-value-option.yml b/Tests/Mapping/Loader/constraint-mapping-value-option.yml new file mode 100644 index 000000000..149497ad1 --- /dev/null +++ b/Tests/Mapping/Loader/constraint-mapping-value-option.yml @@ -0,0 +1,10 @@ +namespaces: + custom: Symfony\Component\Validator\Tests\Fixtures\ + +Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: + properties: + firstName: + # Constraint with single value + - Type: string + # Constraint with multiple values + - Choice: [A, B] diff --git a/Tests/Mapping/Loader/constraint-mapping.xml b/Tests/Mapping/Loader/constraint-mapping.xml index 8a7975f11..3666d3a75 100644 --- a/Tests/Mapping/Loader/constraint-mapping.xml +++ b/Tests/Mapping/Loader/constraint-mapping.xml @@ -59,17 +59,6 @@ - - - - - - - - A - B - - diff --git a/Tests/Mapping/Loader/constraint-mapping.yml b/Tests/Mapping/Loader/constraint-mapping.yml index af091a89f..06b0bd44f 100644 --- a/Tests/Mapping/Loader/constraint-mapping.yml +++ b/Tests/Mapping/Loader/constraint-mapping.yml @@ -26,11 +26,6 @@ Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: firstName: # Constraint without value - NotNull: ~ - # Constraint with single value - - Range: - min: 3 - # Constraint with multiple values - - Choice: [A, B] # Constraint with child constraints - All: - NotNull: ~ From 1d7117a57add22f42edef20a8219012f837caf10 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 21 Jun 2025 14:07:11 +0200 Subject: [PATCH 18/57] remove support for generic constraint option handling --- CHANGELOG.md | 114 ++++++- Constraint.php | 140 +-------- Constraints/AbstractComparison.php | 34 +- Constraints/All.php | 38 +-- Constraints/AtLeastOneOf.php | 37 +-- Constraints/Bic.php | 18 +- Constraints/Blank.php | 9 +- Constraints/Callback.php | 41 +-- Constraints/CardScheme.php | 45 +-- Constraints/Cascade.php | 28 +- Constraints/Charset.php | 2 - Constraints/Choice.php | 33 +- Constraints/Cidr.php | 18 +- Constraints/Collection.php | 55 +--- Constraints/Composite.php | 7 +- Constraints/Compound.php | 10 +- Constraints/Count.php | 34 +- Constraints/Country.php | 9 +- Constraints/CssColor.php | 34 +- Constraints/Currency.php | 9 +- Constraints/Date.php | 9 +- Constraints/DateTime.php | 30 +- Constraints/DisableAutoMapping.php | 14 +- Constraints/Email.php | 16 +- Constraints/EnableAutoMapping.php | 14 +- Constraints/Existence.php | 22 +- Constraints/Expression.php | 48 +-- Constraints/ExpressionSyntax.php | 13 +- Constraints/File.php | 16 +- Constraints/GroupSequence.php | 3 - Constraints/GroupSequenceProvider.php | 3 - Constraints/Hostname.php | 9 +- Constraints/Iban.php | 9 +- Constraints/Image.php | 25 +- Constraints/Ip.php | 10 +- Constraints/IsFalse.php | 9 +- Constraints/IsNull.php | 9 +- Constraints/IsTrue.php | 9 +- Constraints/Isbn.php | 32 +- Constraints/Isin.php | 9 +- Constraints/Issn.php | 9 +- Constraints/Json.php | 9 +- Constraints/Language.php | 9 +- Constraints/Length.php | 23 +- Constraints/Locale.php | 9 +- Constraints/Luhn.php | 9 +- Constraints/MacAddress.php | 2 - Constraints/NoSuspiciousCharacters.php | 13 +- Constraints/NotBlank.php | 10 +- Constraints/NotCompromisedPassword.php | 9 +- Constraints/NotNull.php | 9 +- Constraints/PasswordStrength.php | 17 +- Constraints/Range.php | 19 +- Constraints/Regex.php | 48 +-- Constraints/Sequentially.php | 37 +-- Constraints/Time.php | 9 +- Constraints/Timezone.php | 33 +- Constraints/Traverse.php | 29 +- Constraints/Type.php | 49 +-- Constraints/Ulid.php | 9 +- Constraints/Unique.php | 12 +- Constraints/Url.php | 12 +- Constraints/Uuid.php | 10 +- Constraints/Valid.php | 9 +- Constraints/Week.php | 2 - Constraints/When.php | 50 +-- Constraints/WordCount.php | 2 - Constraints/Yaml.php | 2 - Constraints/ZeroComparisonConstraintTrait.php | 16 +- Mapping/Loader/AbstractLoader.php | 36 +-- Tests/ConstraintTest.php | 297 ------------------ Tests/Constraints/CallbackValidatorTest.php | 19 +- Tests/Constraints/CardSchemeTest.php | 10 - Tests/Constraints/CascadeTest.php | 10 - Tests/Constraints/ChoiceTest.php | 11 - Tests/Constraints/ChoiceValidatorTest.php | 143 --------- Tests/Constraints/CollectionTest.php | 31 -- Tests/Constraints/CompositeTest.php | 5 - Tests/Constraints/CompoundTest.php | 52 --- Tests/Constraints/CountValidatorTestCase.php | 109 ------- Tests/Constraints/DisableAutoMappingTest.php | 12 - Tests/Constraints/EmailTest.php | 20 -- Tests/Constraints/EnableAutoMappingTest.php | 12 - Tests/Constraints/ExpressionSyntaxTest.php | 10 - Tests/Constraints/ExpressionTest.php | 33 -- Tests/Constraints/FileValidatorTestCase.php | 50 --- ...idatorWithPositiveOrZeroConstraintTest.php | 23 -- ...hanValidatorWithPositiveConstraintTest.php | 23 -- Tests/Constraints/ImageValidatorTest.php | 254 --------------- Tests/Constraints/IpTest.php | 21 -- Tests/Constraints/IsFalseValidatorTest.php | 17 - Tests/Constraints/IsTrueValidatorTest.php | 15 - Tests/Constraints/IsbnValidatorTest.php | 40 --- Tests/Constraints/LengthTest.php | 20 -- ...idatorWithNegativeOrZeroConstraintTest.php | 23 -- ...hanValidatorWithNegativeConstraintTest.php | 23 -- Tests/Constraints/NotBlankTest.php | 21 -- .../NotCompromisedPasswordValidatorTest.php | 20 -- Tests/Constraints/NotNullValidatorTest.php | 15 - Tests/Constraints/RangeTest.php | 69 ---- Tests/Constraints/RangeValidatorTest.php | 197 ------------ Tests/Constraints/RegexTest.php | 42 --- Tests/Constraints/RegexValidatorTest.php | 34 -- Tests/Constraints/TypeTest.php | 10 - Tests/Constraints/TypeValidatorTest.php | 17 - Tests/Constraints/UniqueTest.php | 21 -- Tests/Constraints/UrlTest.php | 31 -- Tests/Constraints/UuidTest.php | 21 -- Tests/Constraints/WhenTest.php | 25 -- Tests/Fixtures/ConstraintC.php | 29 -- Tests/Fixtures/ConstraintChoiceWithPreset.php | 35 --- .../ConstraintWithRequiredArgument.php | 2 - .../Fixtures/ConstraintWithStaticProperty.php | 10 - .../Fixtures/ConstraintWithTypedProperty.php | 10 - Tests/Fixtures/ConstraintWithValue.php | 30 -- .../Fixtures/ConstraintWithValueAsDefault.php | 30 -- ...yEntityConstraintWithoutNamedArguments.php | 16 - Tests/Fixtures/LegacyConstraintA.php | 31 -- .../Fixtures/ConstraintWithNamedArguments.php | 2 - .../ConstraintWithoutNamedArguments.php | 22 -- ...nstraintWithoutValueWithNamedArguments.php | 2 - Tests/Mapping/Loader/XmlFileLoaderTest.php | 32 -- Tests/Mapping/Loader/YamlFileLoaderTest.php | 32 -- .../constraint-mapping-value-option.xml | 27 -- .../constraint-mapping-value-option.yml | 10 - ...traint-without-named-arguments-support.xml | 10 - ...traint-without-named-arguments-support.yml | 4 - 127 files changed, 407 insertions(+), 3269 deletions(-) delete mode 100644 Tests/Fixtures/ConstraintC.php delete mode 100644 Tests/Fixtures/ConstraintChoiceWithPreset.php delete mode 100644 Tests/Fixtures/ConstraintWithStaticProperty.php delete mode 100644 Tests/Fixtures/ConstraintWithTypedProperty.php delete mode 100644 Tests/Fixtures/ConstraintWithValue.php delete mode 100644 Tests/Fixtures/ConstraintWithValueAsDefault.php delete mode 100644 Tests/Fixtures/DummyEntityConstraintWithoutNamedArguments.php delete mode 100644 Tests/Fixtures/LegacyConstraintA.php delete mode 100644 Tests/Mapping/Loader/Fixtures/ConstraintWithoutNamedArguments.php delete mode 100644 Tests/Mapping/Loader/constraint-mapping-value-option.xml delete mode 100644 Tests/Mapping/Loader/constraint-mapping-value-option.yml delete mode 100644 Tests/Mapping/Loader/constraint-without-named-arguments-support.xml delete mode 100644 Tests/Mapping/Loader/constraint-without-named-arguments-support.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index d1f8aac24..d89833318 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,118 @@ CHANGELOG 8.0 --- - * Remove `Bic::INVALID_BANK_CODE_ERROR` constant. This error code was not used in the Bic constraint validator anymore. + * Remove the `getRequiredOptions()` and `getDefaultOption()` methods from the `All`, `AtLeastOneOf`, `CardScheme`, `Collection`, + `CssColor`, `Expression`, `Regex`, `Sequentially`, `Type`, and `When` constraints + * Remove support for evaluating options in the base `Constraint` class. Initialize properties in the constructor of the concrete constraint + class instead. + + Before: + + ```php + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + public function __construct(?array $options = null) + { + parent::__construct($options); + } + } + ``` + + After: + + ```php + class CustomConstraint extends Constraint + { + public function __construct( + public $option1 = null, + public $option2 = null, + ?array $groups = null, + mixed $payload = null, + ) { + parent::__construct(null, $groups, $payload); + } + } + ``` + + * Remove the `getRequiredOptions()` method from the base `Constraint` class. Use mandatory constructor arguments instead. + + Before: + + ```php + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + public function __construct(?array $options = null) + { + parent::__construct($options); + } + + public function getRequiredOptions() + { + return ['option1']; + } + } + ``` + + After: + + ```php + class CustomConstraint extends Constraint + { + public function __construct( + public $option1, + public $option2 = null, + ?array $groups = null, + mixed $payload = null, + ) { + parent::__construct(null, $groups, $payload); + } + } + ``` + * Remove the `normalizeOptions()` and `getDefaultOption()` methods of the base `Constraint` class without replacements. + Overriding them in child constraint does not have any effects. + * Remove support for passing an array of options to the `Composite` constraint class. Initialize the properties referenced with `getNestedConstraints()` + in child classes before calling the constructor of `Composite`. + + Before: + + ```php + class CustomCompositeConstraint extends Composite + { + public array $constraints = []; + + public function __construct(?array $options = null) + { + parent::__construct($options); + } + + protected function getCompositeOption(): string + { + return 'constraints'; + } + } + ``` + + After: + + ```php + class CustomCompositeConstraint extends Composite + { + public function __construct( + public array $constraints, + ?array $groups = null, + mixed $payload = null, + ) { + parent::__construct(null, $groups, $payload); + } + } + ``` + * Remove `Bic::INVALID_BANK_CODE_ERROR` constant. This error code was not used in the Bic constraint validator anymore 7.4 --- @@ -131,7 +242,6 @@ CHANGELOG } } ``` ->>>>>>> 7.4 7.3 --- diff --git a/Constraint.php b/Constraint.php index 5563500eb..ea7927531 100644 --- a/Constraint.php +++ b/Constraint.php @@ -11,10 +11,8 @@ namespace Symfony\Component\Validator; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\InvalidOptionsException; -use Symfony\Component\Validator\Exception\MissingOptionsException; /** * Contains the properties of a constraint definition. @@ -78,116 +76,20 @@ public static function getErrorName(string $errorCode): string } /** - * Initializes the constraint with options. + * Initializes the constraint with the groups and payload options. * - * You should pass an associative array. The keys should be the names of - * existing properties in this class. The values should be the value for these - * properties. - * - * Alternatively you can override the method getDefaultOption() to return the - * name of an existing property. If no associative array is passed, this - * property is set instead. - * - * You can force that certain options are set by overriding - * getRequiredOptions() to return the names of these options. If any - * option is not set here, an exception is thrown. - * - * @param mixed $options The options (as associative array) - * or the value for the default - * option (any other type) * @param string[] $groups An array of validation groups * @param mixed $payload Domain-specific data attached to a constraint - * - * @throws InvalidOptionsException When you pass the names of non-existing - * options - * @throws MissingOptionsException When you don't pass any of the options - * returned by getRequiredOptions() - * @throws ConstraintDefinitionException When you don't pass an associative - * array, but getDefaultOption() returns - * null */ public function __construct(mixed $options = null, ?array $groups = null, mixed $payload = null) { unset($this->groups); // enable lazy initialization - if (null === $options && (\func_num_args() > 0 || self::class === (new \ReflectionMethod($this, 'getRequiredOptions'))->getDeclaringClass()->getName())) { - if (null !== $groups) { - $this->groups = $groups; - } - $this->payload = $payload; - - return; - } - - trigger_deprecation('symfony/validator', '7.4', 'Support for evaluating options in the base Constraint class is deprecated. Initialize properties in the constructor of %s instead.', static::class); - - $options = $this->normalizeOptions($options); if (null !== $groups) { - $options['groups'] = $groups; + $this->groups = $groups; } - $options['payload'] = $payload ?? $options['payload'] ?? null; - foreach ($options as $name => $value) { - $this->$name = $value; - } - } - - /** - * @deprecated since Symfony 7.4 - * - * @return array - */ - protected function normalizeOptions(mixed $options): array - { - $normalizedOptions = []; - $defaultOption = $this->getDefaultOption(false); - $invalidOptions = []; - $missingOptions = array_flip($this->getRequiredOptions(false)); - $knownOptions = get_class_vars(static::class); - - if (\is_array($options) && isset($options['value']) && !property_exists($this, 'value')) { - if (null === $defaultOption) { - throw new ConstraintDefinitionException(\sprintf('No default option is configured for constraint "%s".', static::class)); - } - - $options[$defaultOption] = $options['value']; - unset($options['value']); - } - - if (\is_array($options)) { - reset($options); - } - if ($options && \is_array($options) && \is_string(key($options))) { - foreach ($options as $option => $value) { - if (\array_key_exists($option, $knownOptions)) { - $normalizedOptions[$option] = $value; - unset($missingOptions[$option]); - } else { - $invalidOptions[] = $option; - } - } - } elseif (null !== $options && !(\is_array($options) && 0 === \count($options))) { - if (null === $defaultOption) { - throw new ConstraintDefinitionException(\sprintf('No default option is configured for constraint "%s".', static::class)); - } - - if (\array_key_exists($defaultOption, $knownOptions)) { - $normalizedOptions[$defaultOption] = $options; - unset($missingOptions[$defaultOption]); - } else { - $invalidOptions[] = $defaultOption; - } - } - - if (\count($invalidOptions) > 0) { - throw new InvalidOptionsException(\sprintf('The options "%s" do not exist in constraint "%s".', implode('", "', $invalidOptions), static::class), $invalidOptions); - } - - if (\count($missingOptions) > 0) { - throw new MissingOptionsException(\sprintf('The options "%s" must be set for constraint "%s".', implode('", "', array_keys($missingOptions)), static::class), array_keys($missingOptions)); - } - - return $normalizedOptions; + $this->payload = $payload; } /** @@ -249,42 +151,6 @@ public function addImplicitGroupName(string $group): void } } - /** - * Returns the name of the default option. - * - * Override this method to define a default option. - * - * @deprecated since Symfony 7.4 - * @see __construct() - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return null; - } - - /** - * Returns the name of the required options. - * - * Override this method if you want to define required options. - * - * @return string[] - * - * @deprecated since Symfony 7.4 - * @see __construct() - */ - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return []; - } - /** * Returns the name of the class that validates this constraint. * diff --git a/Constraints/AbstractComparison.php b/Constraints/AbstractComparison.php index 586a23ef4..fe1a66725 100644 --- a/Constraints/AbstractComparison.php +++ b/Constraints/AbstractComparison.php @@ -12,7 +12,6 @@ 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; @@ -29,26 +28,13 @@ 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 = null) + public function __construct(mixed $value = null, ?string $propertyPath = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($value)) { - trigger_deprecation('symfony/validator', '7.3', '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) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options['value'] = $value; - } - } - - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; - $this->value = $value ?? $this->value; - $this->propertyPath = $propertyPath ?? $this->propertyPath; + $this->value = $value; + $this->propertyPath = $propertyPath; if (null === $this->value && null === $this->propertyPath) { throw new ConstraintDefinitionException(\sprintf('The "%s" constraint requires either the "value" or "propertyPath" option to be set.', static::class)); @@ -62,16 +48,4 @@ public function __construct(mixed $value = null, ?string $propertyPath = null, ? throw new LogicException(\sprintf('The "%s" constraint requires the Symfony PropertyAccess component to use the "propertyPath" option. Try running "composer require symfony/property-access".', static::class)); } } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'value'; - } } diff --git a/Constraints/All.php b/Constraints/All.php index 533599ad0..967b57c85 100644 --- a/Constraints/All.php +++ b/Constraints/All.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -30,46 +29,15 @@ class All extends Composite * @param array|Constraint|null $constraints * @param string[]|null $groups */ - #[HasNamedArguments] - public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null) + public function __construct(array|Constraint|null $constraints = null, ?array $groups = null, mixed $payload = null) { if (null === $constraints || [] === $constraints) { throw new MissingOptionsException(\sprintf('The options "constraints" must be set for constraint "%s".', self::class), ['constraints']); } - if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + $this->constraints = $constraints; - parent::__construct($constraints, $groups, $payload); - } else { - $this->constraints = $constraints; - - parent::__construct(null, $groups, $payload); - } - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'constraints'; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return ['constraints']; + parent::__construct(null, $groups, $payload); } protected function getCompositeOption(): string diff --git a/Constraints/AtLeastOneOf.php b/Constraints/AtLeastOneOf.php index bc99b3385..ea1dfe881 100644 --- a/Constraints/AtLeastOneOf.php +++ b/Constraints/AtLeastOneOf.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -41,51 +40,21 @@ class AtLeastOneOf extends Composite * @param string|null $messageCollection Failure message for All and Collection inner constraints * @param bool|null $includeInternalMessages Whether to include inner constraint messages (defaults to true) */ - #[HasNamedArguments] - public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null, ?string $message = null, ?string $messageCollection = null, ?bool $includeInternalMessages = null) + public function __construct(array|Constraint|null $constraints = null, ?array $groups = null, mixed $payload = null, ?string $message = null, ?string $messageCollection = null, ?bool $includeInternalMessages = null) { if (null === $constraints || [] === $constraints) { throw new MissingOptionsException(\sprintf('The options "constraints" must be set for constraint "%s".', self::class), ['constraints']); } - if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - $options = $constraints; - } else { - $this->constraints = $constraints; - } + $this->constraints = $constraints; - parent::__construct($options ?? null, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->messageCollection = $messageCollection ?? $this->messageCollection; $this->includeInternalMessages = $includeInternalMessages ?? $this->includeInternalMessages; } - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'constraints'; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return ['constraints']; - } - protected function getCompositeOption(): string { return 'constraints'; diff --git a/Constraints/Bic.php b/Constraints/Bic.php index 66b03287c..fb0be3526 100644 --- a/Constraints/Bic.php +++ b/Constraints/Bic.php @@ -13,7 +13,6 @@ 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\InvalidArgumentException; @@ -65,7 +64,6 @@ class Bic extends Constraint * @param string[]|null $groups * @param self::VALIDATION_MODE_*|null $mode The mode used to validate the BIC; pass null to use the default mode (strict) */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -79,23 +77,21 @@ public function __construct( 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 (\is_array($options) && \array_key_exists('mode', $options) && !\in_array($options['mode'], self::VALIDATION_MODES, true)) { - throw new InvalidArgumentException('The "mode" parameter value is not valid.'); + + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } + if (null !== $mode && !\in_array($mode, self::VALIDATION_MODES, true)) { throw new InvalidArgumentException('The "mode" parameter value is not valid.'); } - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->ibanMessage = $ibanMessage ?? $this->ibanMessage; - $this->iban = $iban ?? $this->iban; - $this->ibanPropertyPath = $ibanPropertyPath ?? $this->ibanPropertyPath; + $this->iban = $iban; + $this->ibanPropertyPath = $ibanPropertyPath; $this->mode = $mode ?? $this->mode; if (null !== $this->iban && null !== $this->ibanPropertyPath) { diff --git a/Constraints/Blank.php b/Constraints/Blank.php index b03586933..7b3d08e59 100644 --- a/Constraints/Blank.php +++ b/Constraints/Blank.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is blank, i.e. an empty string or null. @@ -33,14 +33,13 @@ class Blank extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/Callback.php b/Constraints/Callback.php index f38aa9899..7c5f33c7f 100644 --- a/Constraints/Callback.php +++ b/Constraints/Callback.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; /** @@ -28,44 +27,14 @@ class Callback extends Constraint public $callback; /** - * @param string|string[]|callable|null $callback The callback definition - * @param string[]|null $groups + * @param string|callable|null $callback The callback definition + * @param string[]|null $groups */ - #[HasNamedArguments] - public function __construct(array|string|callable|null $callback = null, ?array $groups = null, mixed $payload = null, ?array $options = null) + public function __construct(string|callable|null $callback = null, ?array $groups = null, mixed $payload = null) { - // Invocation through attributes with an array parameter only - if (\is_array($callback) && 1 === \count($callback) && isset($callback['value'])) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + parent::__construct(null, $groups, $payload); - $callback = $callback['value']; - } - - if (!\is_array($callback) || (!isset($callback['callback']) && !isset($callback['groups']) && !isset($callback['payload']))) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - } else { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options = array_merge($callback, $options ?? []); - } - - parent::__construct($options, $groups, $payload); - - $this->callback = $callback ?? $this->callback; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'callback'; + $this->callback = $callback; } public function getTargets(): string|array diff --git a/Constraints/CardScheme.php b/Constraints/CardScheme.php index 706969796..281796ef8 100644 --- a/Constraints/CardScheme.php +++ b/Constraints/CardScheme.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -52,51 +51,15 @@ class CardScheme extends Constraint * @param non-empty-string|non-empty-string[]|null $schemes Name(s) of the number scheme(s) used to validate the credit card number * @param string[]|null $groups */ - #[HasNamedArguments] - public function __construct(array|string|null $schemes, ?string $message = null, ?array $groups = null, mixed $payload = null, ?array $options = null) + public function __construct(array|string|null $schemes, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (null === $schemes && !isset($options['schemes'])) { + if (null === $schemes) { throw new MissingOptionsException(\sprintf('The options "schemes" must be set for constraint "%s".', self::class), ['schemes']); } - if (\is_array($schemes) && \is_string(key($schemes))) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + parent::__construct(null, $groups, $payload); - $options = array_merge($schemes, $options ?? []); - $schemes = null; - } else { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - } - - parent::__construct($options, $groups, $payload); - - $this->schemes = $schemes ?? $this->schemes; + $this->schemes = $schemes; $this->message = $message ?? $this->message; } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'schemes'; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return ['schemes']; - } } diff --git a/Constraints/Cascade.php b/Constraints/Cascade.php index 86419d7e6..e65e21b5b 100644 --- a/Constraints/Cascade.php +++ b/Constraints/Cascade.php @@ -11,9 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Validates a whole class, including nested objects in properties. @@ -28,31 +26,11 @@ class Cascade extends Constraint /** * @param non-empty-string[]|non-empty-string|null $exclude Properties excluded from validation */ - #[HasNamedArguments] - public function __construct(array|string|null $exclude = null, ?array $options = null) + public function __construct(array|string|null $exclude = null) { - if (\is_array($exclude) && !array_is_list($exclude)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + parent::__construct(); - $options = array_merge($exclude, $options ?? []); - $options['exclude'] = array_flip((array) ($options['exclude'] ?? [])); - $exclude = $options['exclude'] ?? null; - } else { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - - $exclude = array_flip((array) $exclude); - $this->exclude = $exclude; - } - - if (\is_array($options) && \array_key_exists('groups', $options)) { - throw new ConstraintDefinitionException(\sprintf('The option "groups" is not supported by the constraint "%s".', __CLASS__)); - } - - parent::__construct($options, null, $options['payload'] ?? null); - - $this->exclude = $exclude ?? $this->exclude; + $this->exclude = array_flip((array) $exclude); } public function getTargets(): string|array diff --git a/Constraints/Charset.php b/Constraints/Charset.php index aa22c503a..59597efc0 100644 --- a/Constraints/Charset.php +++ b/Constraints/Charset.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -27,7 +26,6 @@ final class Charset extends Constraint self::BAD_ENCODING_ERROR => 'BAD_ENCODING_ERROR', ]; - #[HasNamedArguments] public function __construct( public array|string $encodings = [], public string $message = 'The detected character encoding is invalid ({{ detected }}). Allowed encodings are {{ encodings }}.', diff --git a/Constraints/Choice.php b/Constraints/Choice.php index cf353907d..8d6746870 100644 --- a/Constraints/Choice.php +++ b/Constraints/Choice.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is one of a given set of valid choices. @@ -45,18 +45,6 @@ class Choice extends Constraint public string $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.'; public bool $match = true; - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'choices'; - } - /** * @param array|null $choices An array of choices (required unless a callback is specified) * @param callable|string|null $callback Callback method to use instead of the choice option to get the choices @@ -67,7 +55,6 @@ public function getDefaultOption(): ?string * @param string[]|null $groups * @param bool|null $match Whether to validate the values are part of the choices or not (defaults to true) */ - #[HasNamedArguments] public function __construct( string|array|null $options = null, ?array $choices = null, @@ -84,22 +71,18 @@ public function __construct( mixed $payload = null, ?bool $match = null, ) { - if (\is_array($options) && $options && array_is_list($options)) { - trigger_deprecation('symfony/validator', '7.4', 'Support for passing the choices as the first argument to %s is deprecated.', static::class); - $choices ??= $options; - $options = null; - } elseif (\is_array($options) && [] !== $options) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); - $this->choices = $choices ?? $this->choices; - $this->callback = $callback ?? $this->callback; + $this->choices = $choices; + $this->callback = $callback; $this->multiple = $multiple ?? $this->multiple; $this->strict = $strict ?? $this->strict; - $this->min = $min ?? $this->min; - $this->max = $max ?? $this->max; + $this->min = $min; + $this->max = $max; $this->message = $message ?? $this->message; $this->multipleMessage = $multipleMessage ?? $this->multipleMessage; $this->minMessage = $minMessage ?? $this->minMessage; diff --git a/Constraints/Cidr.php b/Constraints/Cidr.php index a6e470177..e0b13831f 100644 --- a/Constraints/Cidr.php +++ b/Constraints/Cidr.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -75,7 +74,6 @@ class Cidr extends Constraint /** @var callable|null */ public $normalizer; - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $version = null, @@ -86,22 +84,20 @@ public function __construct( $payload = null, ?callable $normalizer = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - $this->version = $version ?? $options['version'] ?? $this->version; + $this->version = $version ?? $this->version; if (!\array_key_exists($this->version, self::NET_MAXES)) { throw new ConstraintDefinitionException(\sprintf('The option "version" must be one of "%s".', implode('", "', array_keys(self::NET_MAXES)))); } - $this->netmaskMin = $netmaskMin ?? $options['netmaskMin'] ?? $this->netmaskMin; - $this->netmaskMax = $netmaskMax ?? $options['netmaskMax'] ?? self::NET_MAXES[$this->version]; + $this->netmaskMin = $netmaskMin ?? $this->netmaskMin; + $this->netmaskMax = $netmaskMax ?? self::NET_MAXES[$this->version]; $this->message = $message ?? $this->message; - $this->normalizer = $normalizer ?? $this->normalizer; - - unset($options['netmaskMin'], $options['netmaskMax'], $options['version']); + $this->normalizer = $normalizer; if ($this->netmaskMin < 0 || $this->netmaskMax > self::NET_MAXES[$this->version] || $this->netmaskMin > $this->netmaskMax) { throw new ConstraintDefinitionException(\sprintf('The netmask range must be between 0 and %d.', self::NET_MAXES[$this->version])); @@ -111,6 +107,6 @@ public function __construct( throw new InvalidArgumentException(\sprintf('The "normalizer" option must be a valid callable ("%s" given).', get_debug_type($this->normalizer))); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); } } diff --git a/Constraints/Collection.php b/Constraints/Collection.php index cfd3bef55..9f91f33ad 100644 --- a/Constraints/Collection.php +++ b/Constraints/Collection.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -43,22 +42,15 @@ class Collection extends Composite * @param bool|null $allowExtraFields Whether to allow additional keys not declared in the configured fields (defaults to false) * @param bool|null $allowMissingFields Whether to allow the collection to lack some fields declared in the configured fields (defaults to false) */ - #[HasNamedArguments] - public function __construct(mixed $fields = null, ?array $groups = null, mixed $payload = null, ?bool $allowExtraFields = null, ?bool $allowMissingFields = null, ?string $extraFieldsMessage = null, ?string $missingFieldsMessage = null) + public function __construct(?array $fields = null, ?array $groups = null, mixed $payload = null, ?bool $allowExtraFields = null, ?bool $allowMissingFields = null, ?string $extraFieldsMessage = null, ?string $missingFieldsMessage = null) { if (null === $fields) { throw new MissingOptionsException(\sprintf('The options "fields" must be set for constraint "%s".', self::class), ['fields']); } - if (self::isFieldsOption($fields)) { - $this->fields = $fields; - } else { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + $this->fields = $fields; - $options = $fields; - } - - parent::__construct($options ?? null, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->allowExtraFields = $allowExtraFields ?? $this->allowExtraFields; $this->allowMissingFields = $allowMissingFields ?? $this->allowMissingFields; @@ -78,52 +70,13 @@ protected function initializeNestedConstraints(): void } if (!$field instanceof Optional && !$field instanceof Required) { - $this->fields[$fieldName] = new Required($field); + $this->fields[$fieldName] = new Required($field ?? []); } } } - /** - * @deprecated since Symfony 7.4 - */ - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return ['fields']; - } - protected function getCompositeOption(): string { return 'fields'; } - - private static function isFieldsOption($options): bool - { - if (!\is_array($options)) { - return false; - } - - foreach ($options as $optionOrField) { - if ($optionOrField instanceof Constraint) { - return true; - } - - if (null === $optionOrField) { - continue; - } - - if (!\is_array($optionOrField)) { - return false; - } - - if ($optionOrField && !($optionOrField[0] ?? null) instanceof Constraint) { - return false; - } - } - - return true; - } } diff --git a/Constraints/Composite.php b/Constraints/Composite.php index fdfaacc2e..a6d285033 100644 --- a/Constraints/Composite.php +++ b/Constraints/Composite.php @@ -11,9 +11,9 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * A constraint that is composed of other constraints. @@ -50,14 +50,13 @@ abstract class Composite extends Constraint * cached. When constraints are loaded from the cache, no more group * checks need to be done. */ - #[HasNamedArguments] public function __construct(mixed $options = null, ?array $groups = null, mixed $payload = null) { if (null !== $options) { - trigger_deprecation('symfony/validator', '7.4', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->initializeNestedConstraints(); diff --git a/Constraints/Compound.php b/Constraints/Compound.php index 261871533..981cc6e6d 100644 --- a/Constraints/Compound.php +++ b/Constraints/Compound.php @@ -11,9 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Extend this class to create a reusable set of constraints. @@ -25,14 +24,13 @@ abstract class Compound extends Composite /** @var Constraint[] */ public array $constraints = []; - #[HasNamedArguments] public function __construct(mixed $options = null, ?array $groups = null, mixed $payload = null) { - if (isset($options[$this->getCompositeOption()])) { - throw new ConstraintDefinitionException(\sprintf('You can\'t redefine the "%s" option. Use the "%s::getConstraints()" method instead.', $this->getCompositeOption(), __CLASS__)); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - $this->constraints = $this->getConstraints($this->normalizeOptions($options)); + $this->constraints = $this->getConstraints([]); parent::__construct($options, $groups, $payload); } diff --git a/Constraints/Count.php b/Constraints/Count.php index c947c9225..54d3b6a1a 100644 --- a/Constraints/Count.php +++ b/Constraints/Count.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -44,16 +43,14 @@ class Count extends Constraint public ?int $divisibleBy = null; /** - * @param int<0, max>|null $exactly The exact expected number of elements - * @param int<0, max>|null $min Minimum expected number of elements - * @param int<0, max>|null $max Maximum expected number of elements - * @param positive-int|null $divisibleBy The number the collection count should be divisible by - * @param string[]|null $groups - * @param array|null $options + * @param int<0, max>|null $exactly The exact expected number of elements + * @param int<0, max>|null $min Minimum expected number of elements + * @param int<0, max>|null $max Maximum expected number of elements + * @param positive-int|null $divisibleBy The number the collection count should be divisible by + * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( - int|array|null $exactly = null, + ?int $exactly = null, ?int $min = null, ?int $max = null, ?int $divisibleBy = null, @@ -63,31 +60,16 @@ public function __construct( ?string $divisibleByMessage = null, ?array $groups = null, mixed $payload = null, - ?array $options = null, ) { - if (\is_array($exactly)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options = array_merge($exactly, $options ?? []); - $exactly = $options['value'] ?? null; - } elseif (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - - $min ??= $options['min'] ?? null; - $max ??= $options['max'] ?? null; - - unset($options['value'], $options['min'], $options['max']); - if (null !== $exactly && null === $min && null === $max) { $min = $max = $exactly; } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->min = $min; $this->max = $max; - $this->divisibleBy = $divisibleBy ?? $this->divisibleBy; + $this->divisibleBy = $divisibleBy; $this->exactMessage = $exactMessage ?? $this->exactMessage; $this->minMessage = $minMessage ?? $this->minMessage; $this->maxMessage = $maxMessage ?? $this->maxMessage; diff --git a/Constraints/Country.php b/Constraints/Country.php index 89d4717b4..1b3a24740 100644 --- a/Constraints/Country.php +++ b/Constraints/Country.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Countries; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\LogicException; /** @@ -41,7 +41,6 @@ class Country extends Constraint * * @see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3#Current_codes */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -53,11 +52,11 @@ public function __construct( throw new LogicException('The Intl component is required to use the Country constraint. Try running "composer require symfony/intl".'); } - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->alpha3 = $alpha3 ?? $this->alpha3; diff --git a/Constraints/CssColor.php b/Constraints/CssColor.php index 0e87e20db..110e54ae0 100644 --- a/Constraints/CssColor.php +++ b/Constraints/CssColor.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -66,17 +65,12 @@ class CssColor extends Constraint * @param non-empty-string[]|non-empty-string $formats The types of CSS colors allowed ({@see https://symfony.com/doc/current/reference/constraints/CssColor.html#formats}) * @param string[]|null $groups */ - #[HasNamedArguments] - public function __construct(array|string $formats = [], ?string $message = null, ?array $groups = null, $payload = null, ?array $options = null) + public function __construct(array|string $formats = [], ?string $message = null, ?array $groups = null, $payload = null) { $validationModesAsString = implode(', ', self::$validationModes); if (!$formats) { $formats = self::$validationModes; - } elseif (\is_array($formats) && \is_string(key($formats))) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options = array_merge($formats, $options ?? []); } elseif (\is_array($formats)) { if ([] === array_intersect(self::$validationModes, $formats)) { throw new InvalidArgumentException(\sprintf('The "formats" parameter value is not valid. It must contain one or more of the following values: "%s".', $validationModesAsString)); @@ -91,33 +85,9 @@ public function __construct(array|string $formats = [], ?string $message = null, throw new InvalidArgumentException('The "formats" parameter type is not valid. It should be a string or an array.'); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->formats = $formats ?? $this->formats; $this->message = $message ?? $this->message; } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'formats'; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return ['formats']; - } } diff --git a/Constraints/Currency.php b/Constraints/Currency.php index 678538a8a..56b70bb53 100644 --- a/Constraints/Currency.php +++ b/Constraints/Currency.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Currencies; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\LogicException; /** @@ -38,18 +38,17 @@ class Currency extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { if (!class_exists(Currencies::class)) { throw new LogicException('The Intl component is required to use the Currency constraint. Try running "composer require symfony/intl".'); } - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/Date.php b/Constraints/Date.php index f2ae75691..567c27fa5 100644 --- a/Constraints/Date.php +++ b/Constraints/Date.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is a valid date, i.e. its string representation follows the Y-m-d format. @@ -37,14 +37,13 @@ class Date extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/DateTime.php b/Constraints/DateTime.php index f9e94f0c2..1996e90e0 100644 --- a/Constraints/DateTime.php +++ b/Constraints/DateTime.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; /** @@ -41,36 +40,11 @@ class DateTime extends Constraint * @param non-empty-string|null $format The datetime format to match (defaults to 'Y-m-d H:i:s') * @param string[]|null $groups */ - #[HasNamedArguments] - public function __construct(string|array|null $format = null, ?string $message = null, ?array $groups = null, mixed $payload = null, ?array $options = null) + public function __construct(?string $format = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($format)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options = array_merge($format, $options ?? []); - } elseif (null !== $format) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options['value'] = $format; - } - } - - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->format = $format ?? $this->format; $this->message = $message ?? $this->message; } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'format'; - } } diff --git a/Constraints/DisableAutoMapping.php b/Constraints/DisableAutoMapping.php index 926d8be25..9d499e7d2 100644 --- a/Constraints/DisableAutoMapping.php +++ b/Constraints/DisableAutoMapping.php @@ -11,9 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Disables auto mapping. @@ -26,18 +25,13 @@ #[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::TARGET_CLASS)] class DisableAutoMapping extends Constraint { - #[HasNamedArguments] public function __construct(?array $options = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - if (\is_array($options) && \array_key_exists('groups', $options)) { - throw new ConstraintDefinitionException(\sprintf('The option "groups" is not supported by the constraint "%s".', __CLASS__)); - } - - parent::__construct($options, null, $payload); + parent::__construct(null, null, $payload); } public function getTargets(): string|array diff --git a/Constraints/Email.php b/Constraints/Email.php index 193384019..17613a59e 100644 --- a/Constraints/Email.php +++ b/Constraints/Email.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Validator\Constraints; use Egulias\EmailValidator\EmailValidator as StrictEmailValidator; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\LogicException; @@ -50,7 +49,6 @@ class Email extends Constraint * @param self::VALIDATION_MODE_*|null $mode The pattern used to validate the email address; pass null to use the default mode configured for the EmailValidator * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -59,23 +57,19 @@ public function __construct( ?array $groups = null, mixed $payload = null, ) { - if (\is_array($options) && \array_key_exists('mode', $options) && !\in_array($options['mode'], self::VALIDATION_MODES, true)) { - throw new InvalidArgumentException('The "mode" parameter value is not valid.'); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } if (null !== $mode && !\in_array($mode, self::VALIDATION_MODES, true)) { throw new InvalidArgumentException('The "mode" parameter value is not valid.'); } - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; - $this->mode = $mode ?? $this->mode; - $this->normalizer = $normalizer ?? $this->normalizer; + $this->mode = $mode; + $this->normalizer = $normalizer; if (self::VALIDATION_MODE_STRICT === $this->mode && !class_exists(StrictEmailValidator::class)) { throw new LogicException(\sprintf('The "egulias/email-validator" component is required to use the "%s" constraint in strict mode. Try running "composer require egulias/email-validator".', __CLASS__)); diff --git a/Constraints/EnableAutoMapping.php b/Constraints/EnableAutoMapping.php index 58e77805a..8ec3ccad2 100644 --- a/Constraints/EnableAutoMapping.php +++ b/Constraints/EnableAutoMapping.php @@ -11,9 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Enables auto mapping. @@ -26,18 +25,13 @@ #[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::TARGET_CLASS)] class EnableAutoMapping extends Constraint { - #[HasNamedArguments] public function __construct(?array $options = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - if (\is_array($options) && \array_key_exists('groups', $options)) { - throw new ConstraintDefinitionException(\sprintf('The option "groups" is not supported by the constraint "%s".', __CLASS__)); - } - - parent::__construct($options, null, $payload); + parent::__construct(null, null, $payload); } public function getTargets(): string|array diff --git a/Constraints/Existence.php b/Constraints/Existence.php index a867f09e5..1835151cf 100644 --- a/Constraints/Existence.php +++ b/Constraints/Existence.php @@ -20,27 +20,11 @@ abstract class Existence extends Composite { public array|Constraint $constraints = []; - public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null) + public function __construct(array|Constraint $constraints = [], ?array $groups = null, mixed $payload = null) { - if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { - parent::__construct($constraints, $groups, $payload); - } else { - $this->constraints = $constraints; + $this->constraints = $constraints; - parent::__construct(null, $groups, $payload); - } - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'constraints'; + parent::__construct(null, $groups, $payload); } protected function getCompositeOption(): string diff --git a/Constraints/Expression.php b/Constraints/Expression.php index ee3c2dd93..3aeb943f6 100644 --- a/Constraints/Expression.php +++ b/Constraints/Expression.php @@ -13,8 +13,8 @@ use Symfony\Component\ExpressionLanguage\Expression as ExpressionObject; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\LogicException; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -46,9 +46,8 @@ class Expression extends Constraint * @param string[]|null $groups * @param bool|null $negate Whether to fail if the expression evaluates to true (defaults to false) */ - #[HasNamedArguments] public function __construct( - string|ExpressionObject|array|null $expression, + string|ExpressionObject|null $expression, ?string $message = null, ?array $values = null, ?array $groups = null, @@ -60,53 +59,22 @@ public function __construct( throw new LogicException(\sprintf('The "symfony/expression-language" component is required to use the "%s" constraint. Try running "composer require symfony/expression-language".', __CLASS__)); } - if (null === $expression && !isset($options['expression'])) { - throw new MissingOptionsException(\sprintf('The options "expression" must be set for constraint "%s".', self::class), ['expression']); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - if (\is_array($expression)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options = array_merge($expression, $options ?? []); - $expression = null; - } else { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } + if (null === $expression) { + throw new MissingOptionsException(\sprintf('The options "expression" must be set for constraint "%s".', self::class), ['expression']); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; - $this->expression = $expression ?? $this->expression; + $this->expression = $expression; $this->values = $values ?? $this->values; $this->negate = $negate ?? $this->negate; } - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'expression'; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return ['expression']; - } - public function getTargets(): string|array { return [self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT]; diff --git a/Constraints/ExpressionSyntax.php b/Constraints/ExpressionSyntax.php index 55ed3c542..78130f59b 100644 --- a/Constraints/ExpressionSyntax.php +++ b/Constraints/ExpressionSyntax.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is valid as an ExpressionLanguage expression. @@ -37,18 +37,17 @@ class ExpressionSyntax extends Constraint * @param string[]|null $allowedVariables Restrict the available variables in the expression to these values (defaults to null that allows any variable) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?string $service = null, ?array $allowedVariables = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; - $this->service = $service ?? $this->service; - $this->allowedVariables = $allowedVariables ?? $this->allowedVariables; + $this->service = $service; + $this->allowedVariables = $allowedVariables; } public function validatedBy(): string diff --git a/Constraints/File.php b/Constraints/File.php index 0e436dc9e..b24c1ab44 100644 --- a/Constraints/File.php +++ b/Constraints/File.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -109,7 +108,6 @@ class File extends Constraint * * @see https://www.iana.org/assignments/media-types/media-types.xhtml Existing media types */ - #[HasNamedArguments] public function __construct( ?array $options = null, int|string|null $maxSize = null, @@ -139,17 +137,17 @@ public function __construct( ?string $filenameCountUnit = null, ?string $filenameCharsetMessage = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); - $this->maxSize = $maxSize ?? $this->maxSize; - $this->binaryFormat = $binaryFormat ?? $this->binaryFormat; + $this->maxSize = $maxSize; + $this->binaryFormat = $binaryFormat; $this->mimeTypes = $mimeTypes ?? $this->mimeTypes; - $this->filenameMaxLength = $filenameMaxLength ?? $this->filenameMaxLength; - $this->filenameCharset = $filenameCharset ?? $this->filenameCharset; + $this->filenameMaxLength = $filenameMaxLength; + $this->filenameCharset = $filenameCharset; $this->filenameCountUnit = $filenameCountUnit ?? $this->filenameCountUnit; $this->extensions = $extensions ?? $this->extensions; $this->notFoundMessage = $notFoundMessage ?? $this->notFoundMessage; diff --git a/Constraints/GroupSequence.php b/Constraints/GroupSequence.php index e3e4f47f9..3c2cc48ba 100644 --- a/Constraints/GroupSequence.php +++ b/Constraints/GroupSequence.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; - /** * A sequence of validation groups. * @@ -77,7 +75,6 @@ class GroupSequence * * @param array $groups The groups in the sequence */ - #[HasNamedArguments] public function __construct(array $groups) { $this->groups = $groups['value'] ?? $groups; diff --git a/Constraints/GroupSequenceProvider.php b/Constraints/GroupSequenceProvider.php index b72dd0c4c..7b063d6b1 100644 --- a/Constraints/GroupSequenceProvider.php +++ b/Constraints/GroupSequenceProvider.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; - /** * Attribute to define a group sequence provider. * @@ -21,7 +19,6 @@ #[\Attribute(\Attribute::TARGET_CLASS)] class GroupSequenceProvider { - #[HasNamedArguments] public function __construct(public ?string $provider = null) { } diff --git a/Constraints/Hostname.php b/Constraints/Hostname.php index f388c950c..c18d0086f 100644 --- a/Constraints/Hostname.php +++ b/Constraints/Hostname.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is a valid host name. @@ -35,7 +35,6 @@ class Hostname extends Constraint * @param bool|null $requireTld Whether to require the hostname to include its top-level domain (defaults to true) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -43,11 +42,11 @@ public function __construct( ?array $groups = null, mixed $payload = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->requireTld = $requireTld ?? $this->requireTld; diff --git a/Constraints/Iban.php b/Constraints/Iban.php index 4898155c1..2414688ef 100644 --- a/Constraints/Iban.php +++ b/Constraints/Iban.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is a valid bank account number according to the IBAN format. @@ -45,14 +45,13 @@ class Iban extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/Image.php b/Constraints/Image.php index b47dc8ba6..90a7be1f9 100644 --- a/Constraints/Image.php +++ b/Constraints/Image.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a file (or a path to a file) is a valid image. @@ -119,7 +119,6 @@ class Image extends File * * @see https://www.iana.org/assignments/media-types/media-types.xhtml Existing media types */ - #[HasNamedArguments] public function __construct( ?array $options = null, int|string|null $maxSize = null, @@ -173,6 +172,10 @@ public function __construct( ?string $filenameCountUnit = null, ?string $filenameCharsetMessage = null, ) { + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); + } + parent::__construct( $options, $maxSize, @@ -202,14 +205,14 @@ public function __construct( $filenameCharsetMessage, ); - $this->minWidth = $minWidth ?? $this->minWidth; - $this->maxWidth = $maxWidth ?? $this->maxWidth; - $this->maxHeight = $maxHeight ?? $this->maxHeight; - $this->minHeight = $minHeight ?? $this->minHeight; - $this->maxRatio = $maxRatio ?? $this->maxRatio; - $this->minRatio = $minRatio ?? $this->minRatio; - $this->minPixels = $minPixels ?? $this->minPixels; - $this->maxPixels = $maxPixels ?? $this->maxPixels; + $this->minWidth = $minWidth; + $this->maxWidth = $maxWidth; + $this->maxHeight = $maxHeight; + $this->minHeight = $minHeight; + $this->maxRatio = $maxRatio; + $this->minRatio = $minRatio; + $this->minPixels = $minPixels; + $this->maxPixels = $maxPixels; $this->allowSquare = $allowSquare ?? $this->allowSquare; $this->allowLandscape = $allowLandscape ?? $this->allowLandscape; $this->allowPortrait = $allowPortrait ?? $this->allowPortrait; @@ -232,7 +235,7 @@ public function __construct( $this->mimeTypes = 'image/*'; } - if (!\in_array('image/*', (array) $this->mimeTypes, true) && !\array_key_exists('mimeTypesMessage', $options ?? []) && null === $mimeTypesMessage) { + if (!\in_array('image/*', (array) $this->mimeTypes, true) && null === $mimeTypesMessage) { $this->mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.'; } } diff --git a/Constraints/Ip.php b/Constraints/Ip.php index 91f247156..5a08a9ade 100644 --- a/Constraints/Ip.php +++ b/Constraints/Ip.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -111,7 +110,6 @@ class Ip extends Constraint * @param self::V4*|self::V6*|self::ALL*|null $version The IP version to validate (defaults to {@see self::V4}) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $version = null, @@ -120,15 +118,15 @@ public function __construct( ?array $groups = null, mixed $payload = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->version = $version ?? $this->version; $this->message = $message ?? $this->message; - $this->normalizer = $normalizer ?? $this->normalizer; + $this->normalizer = $normalizer; if (!\in_array($this->version, static::VERSIONS, true)) { throw new ConstraintDefinitionException(\sprintf('The option "version" must be one of "%s".', implode('", "', static::VERSIONS))); diff --git a/Constraints/IsFalse.php b/Constraints/IsFalse.php index 722f2a247..5dc2f51d7 100644 --- a/Constraints/IsFalse.php +++ b/Constraints/IsFalse.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is false. @@ -33,14 +33,13 @@ class IsFalse extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/IsNull.php b/Constraints/IsNull.php index 7447aed9f..45a8fffa1 100644 --- a/Constraints/IsNull.php +++ b/Constraints/IsNull.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is exactly equal to null. @@ -33,14 +33,13 @@ class IsNull extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/IsTrue.php b/Constraints/IsTrue.php index 58d25b594..1af39a704 100644 --- a/Constraints/IsTrue.php +++ b/Constraints/IsTrue.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is true. @@ -33,14 +33,13 @@ class IsTrue extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/Isbn.php b/Constraints/Isbn.php index 5251150f3..d32c39429 100644 --- a/Constraints/Isbn.php +++ b/Constraints/Isbn.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; /** @@ -54,44 +53,21 @@ class Isbn extends Constraint * @param string|null $message If defined, this message has priority over the others * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( - string|array|null $type = null, + ?string $type = null, ?string $message = null, ?string $isbn10Message = null, ?string $isbn13Message = null, ?string $bothIsbnMessage = null, ?array $groups = null, mixed $payload = null, - ?array $options = null, ) { - if (\is_array($type)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + parent::__construct(null, $groups, $payload); - $options = array_merge($type, $options ?? []); - $type = $options['type'] ?? null; - } elseif (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', '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; + $this->message = $message; $this->isbn10Message = $isbn10Message ?? $this->isbn10Message; $this->isbn13Message = $isbn13Message ?? $this->isbn13Message; $this->bothIsbnMessage = $bothIsbnMessage ?? $this->bothIsbnMessage; - $this->type = $type ?? $this->type; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'type'; + $this->type = $type; } } diff --git a/Constraints/Isin.php b/Constraints/Isin.php index 821ec62d5..4dc65a5c9 100644 --- a/Constraints/Isin.php +++ b/Constraints/Isin.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is a valid International Securities Identification Number (ISIN). @@ -42,14 +42,13 @@ class Isin extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/Issn.php b/Constraints/Issn.php index 1c4ba88d0..5f7d144af 100644 --- a/Constraints/Issn.php +++ b/Constraints/Issn.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is a valid International Standard Serial Number (ISSN). @@ -50,7 +50,6 @@ class Issn extends Constraint * @param bool|null $requireHyphen Whether to require a hyphenated ISSN value (defaults to false) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -59,11 +58,11 @@ public function __construct( ?array $groups = null, mixed $payload = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->caseSensitive = $caseSensitive ?? $this->caseSensitive; diff --git a/Constraints/Json.php b/Constraints/Json.php index 8798c94aa..7078705a9 100644 --- a/Constraints/Json.php +++ b/Constraints/Json.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value has valid JSON syntax. @@ -33,14 +33,13 @@ class Json extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/Language.php b/Constraints/Language.php index dfa91b4f7..778d1eef7 100644 --- a/Constraints/Language.php +++ b/Constraints/Language.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Languages; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\LogicException; /** @@ -39,7 +39,6 @@ class Language extends Constraint * @param bool|null $alpha3 Pass true to validate the language with three-letter code (ISO 639-2 (2T)) or false with two-letter code (ISO 639-1) (defaults to false) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -51,11 +50,11 @@ public function __construct( throw new LogicException('The Intl component is required to use the Language constraint. Try running "composer require symfony/intl".'); } - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->alpha3 = $alpha3 ?? $this->alpha3; diff --git a/Constraints/Length.php b/Constraints/Length.php index 3c7f93ae6..60f1e78bb 100644 --- a/Constraints/Length.php +++ b/Constraints/Length.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -67,9 +66,8 @@ class Length extends Constraint * @param self::COUNT_*|null $countUnit The character count unit for the length check (defaults to {@see Length::COUNT_CODEPOINTS}) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( - int|array|null $exactly = null, + ?int $exactly = null, ?int $min = null, ?int $max = null, ?string $charset = null, @@ -81,32 +79,17 @@ public function __construct( ?string $charsetMessage = null, ?array $groups = null, mixed $payload = null, - ?array $options = null, ) { - if (\is_array($exactly)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options = array_merge($exactly, $options ?? []); - $exactly = $options['value'] ?? null; - } elseif (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - - $min ??= $options['min'] ?? null; - $max ??= $options['max'] ?? null; - - unset($options['value'], $options['min'], $options['max']); - if (null !== $exactly && null === $min && null === $max) { $min = $max = $exactly; } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->min = $min; $this->max = $max; $this->charset = $charset ?? $this->charset; - $this->normalizer = $normalizer ?? $this->normalizer; + $this->normalizer = $normalizer; $this->countUnit = $countUnit ?? $this->countUnit; $this->exactMessage = $exactMessage ?? $this->exactMessage; $this->minMessage = $minMessage ?? $this->minMessage; diff --git a/Constraints/Locale.php b/Constraints/Locale.php index d309fecee..9a9dec201 100644 --- a/Constraints/Locale.php +++ b/Constraints/Locale.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Locales; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\LogicException; /** @@ -39,7 +39,6 @@ class Locale extends Constraint * @param bool|null $canonicalize Whether to canonicalize the value before validation (defaults to true) (see {@see https://www.php.net/manual/en/locale.canonicalize.php}) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -51,11 +50,11 @@ public function __construct( throw new LogicException('The Intl component is required to use the Locale constraint. Try running "composer require symfony/intl".'); } - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->canonicalize = $canonicalize ?? $this->canonicalize; diff --git a/Constraints/Luhn.php b/Constraints/Luhn.php index f2e93a867..1452d1aa0 100644 --- a/Constraints/Luhn.php +++ b/Constraints/Luhn.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value (typically a credit card number) passes the Luhn algorithm. @@ -39,18 +39,17 @@ class Luhn extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/MacAddress.php b/Constraints/MacAddress.php index 566495b38..ed0617ccf 100644 --- a/Constraints/MacAddress.php +++ b/Constraints/MacAddress.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -66,7 +65,6 @@ class MacAddress extends Constraint /** * @param self::ALL*|self::LOCAL_*|self::UNIVERSAL_*|self::UNICAST_*|self::MULTICAST_*|self::BROADCAST $type A mac address type to validate (defaults to {@see self::ALL}) */ - #[HasNamedArguments] public function __construct( public string $message = 'This value is not a valid MAC address.', public string $type = self::ALL, diff --git a/Constraints/NoSuspiciousCharacters.php b/Constraints/NoSuspiciousCharacters.php index 2a5ba530c..82b2164a2 100644 --- a/Constraints/NoSuspiciousCharacters.php +++ b/Constraints/NoSuspiciousCharacters.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\LogicException; /** @@ -89,7 +89,6 @@ class NoSuspiciousCharacters extends Constraint * @param string[]|null $locales Restrict the string's characters to those normally used with these locales. Pass null to use the default locales configured for the NoSuspiciousCharactersValidator. (defaults to null) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $restrictionLevelMessage = null, @@ -106,18 +105,18 @@ public function __construct( throw new LogicException('The intl extension is required to use the NoSuspiciousCharacters constraint.'); } - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->restrictionLevelMessage = $restrictionLevelMessage ?? $this->restrictionLevelMessage; $this->invisibleMessage = $invisibleMessage ?? $this->invisibleMessage; $this->mixedNumbersMessage = $mixedNumbersMessage ?? $this->mixedNumbersMessage; $this->hiddenOverlayMessage = $hiddenOverlayMessage ?? $this->hiddenOverlayMessage; $this->checks = $checks ?? $this->checks; - $this->restrictionLevel = $restrictionLevel ?? $this->restrictionLevel; - $this->locales = $locales ?? $this->locales; + $this->restrictionLevel = $restrictionLevel; + $this->locales = $locales; } } diff --git a/Constraints/NotBlank.php b/Constraints/NotBlank.php index f26f6aff8..81674cc3a 100644 --- a/Constraints/NotBlank.php +++ b/Constraints/NotBlank.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -39,18 +38,17 @@ class NotBlank extends Constraint * @param bool|null $allowNull Whether to allow null values (defaults to false) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?bool $allowNull = null, ?callable $normalizer = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->allowNull = $allowNull ?? $this->allowNull; - $this->normalizer = $normalizer ?? $this->normalizer; + $this->normalizer = $normalizer; 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))); diff --git a/Constraints/NotCompromisedPassword.php b/Constraints/NotCompromisedPassword.php index 8a6219580..9e251e023 100644 --- a/Constraints/NotCompromisedPassword.php +++ b/Constraints/NotCompromisedPassword.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Checks if a password has been leaked in a data breach. @@ -37,7 +37,6 @@ class NotCompromisedPassword extends Constraint * @param bool|null $skipOnError Whether to ignore HTTP errors while requesting the API and thus consider the password valid (defaults to false) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -46,11 +45,11 @@ public function __construct( ?array $groups = null, mixed $payload = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->threshold = $threshold ?? $this->threshold; diff --git a/Constraints/NotNull.php b/Constraints/NotNull.php index b00c72bed..5e217e9e3 100644 --- a/Constraints/NotNull.php +++ b/Constraints/NotNull.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is not strictly equal to null. @@ -33,14 +33,13 @@ class NotNull extends Constraint /** * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/Constraints/PasswordStrength.php b/Constraints/PasswordStrength.php index 7ad2b13fd..1a642b4cf 100644 --- a/Constraints/PasswordStrength.php +++ b/Constraints/PasswordStrength.php @@ -11,9 +11,9 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that the given password has reached a minimum strength. @@ -43,20 +43,17 @@ final class PasswordStrength extends Constraint * @param self::STRENGTH_*|null $minScore The minimum required strength of the password (defaults to {@see PasswordStrength::STRENGTH_MEDIUM}) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct(?array $options = null, ?int $minScore = null, ?array $groups = null, mixed $payload = null, ?string $message = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options['minScore'] ??= self::STRENGTH_MEDIUM; - } else { - $minScore ??= self::STRENGTH_MEDIUM; + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + $minScore ??= self::STRENGTH_MEDIUM; + + parent::__construct(null, $groups, $payload); - $this->minScore = $minScore ?? $this->minScore; + $this->minScore = $minScore; $this->message = $message ?? $this->message; if ($this->minScore < 1 || 4 < $this->minScore) { diff --git a/Constraints/Range.php b/Constraints/Range.php index dff5bf06d..553f3f3cc 100644 --- a/Constraints/Range.php +++ b/Constraints/Range.php @@ -12,9 +12,9 @@ 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\InvalidArgumentException; use Symfony\Component\Validator\Exception\LogicException; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -57,7 +57,6 @@ class Range extends Constraint * @param non-empty-string|null $maxPropertyPath Property path to the max value * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $notInRangeMessage = null, @@ -72,21 +71,21 @@ public function __construct( ?array $groups = null, mixed $payload = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->notInRangeMessage = $notInRangeMessage ?? $this->notInRangeMessage; $this->minMessage = $minMessage ?? $this->minMessage; $this->maxMessage = $maxMessage ?? $this->maxMessage; $this->invalidMessage = $invalidMessage ?? $this->invalidMessage; $this->invalidDateTimeMessage = $invalidDateTimeMessage ?? $this->invalidDateTimeMessage; - $this->min = $min ?? $this->min; - $this->minPropertyPath = $minPropertyPath ?? $this->minPropertyPath; - $this->max = $max ?? $this->max; - $this->maxPropertyPath = $maxPropertyPath ?? $this->maxPropertyPath; + $this->min = $min; + $this->minPropertyPath = $minPropertyPath; + $this->max = $max; + $this->maxPropertyPath = $maxPropertyPath; if (null === $this->min && null === $this->minPropertyPath && null === $this->max && null === $this->maxPropertyPath) { throw new MissingOptionsException(\sprintf('Either option "min", "minPropertyPath", "max" or "maxPropertyPath" must be given for constraint "%s".', __CLASS__), ['min', 'minPropertyPath', 'max', 'maxPropertyPath']); @@ -104,7 +103,7 @@ public function __construct( throw new LogicException(\sprintf('The "%s" constraint requires the Symfony PropertyAccess component to use the "minPropertyPath" or "maxPropertyPath" option. Try running "composer require symfony/property-access".', static::class)); } - if (null !== $this->min && null !== $this->max && ($minMessage || $maxMessage || isset($options['minMessage']) || isset($options['maxMessage']))) { + if (null !== $this->min && null !== $this->max && ($minMessage || $maxMessage)) { throw new ConstraintDefinitionException(\sprintf('The "%s" constraint can not use "minMessage" and "maxMessage" when the "min" and "max" options are both set. Use "notInRangeMessage" instead.', static::class)); } } diff --git a/Constraints/Regex.php b/Constraints/Regex.php index 8ab6d0619..79f24a6a5 100644 --- a/Constraints/Regex.php +++ b/Constraints/Regex.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -43,67 +42,32 @@ class Regex extends Constraint * @param bool|null $match Whether to validate the value matches the configured pattern or not (defaults to true) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( - string|array|null $pattern, + ?string $pattern, ?string $message = null, ?string $htmlPattern = null, ?bool $match = null, ?callable $normalizer = null, ?array $groups = null, mixed $payload = null, - ?array $options = null, ) { - if (null === $pattern && !isset($options['pattern'])) { + if (null === $pattern) { throw new MissingOptionsException(\sprintf('The options "pattern" must be set for constraint "%s".', self::class), ['pattern']); } - if (\is_array($pattern)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + parent::__construct(null, $groups, $payload); - $options = array_merge($pattern, $options ?? []); - $pattern = $options['pattern'] ?? null; - } elseif (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - - parent::__construct($options, $groups, $payload); - - $this->pattern = $pattern ?? $this->pattern; + $this->pattern = $pattern; $this->message = $message ?? $this->message; - $this->htmlPattern = $htmlPattern ?? $this->htmlPattern; + $this->htmlPattern = $htmlPattern; $this->match = $match ?? $this->match; - $this->normalizer = $normalizer ?? $this->normalizer; + $this->normalizer = $normalizer; 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))); } } - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'pattern'; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return ['pattern']; - } - /** * Converts the htmlPattern to a suitable format for HTML5 pattern. * Example: /^[a-z]+$/ would be converted to [a-z]+ diff --git a/Constraints/Sequentially.php b/Constraints/Sequentially.php index ff53be7af..adf8d5c09 100644 --- a/Constraints/Sequentially.php +++ b/Constraints/Sequentially.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -30,45 +29,15 @@ class Sequentially extends Composite * @param Constraint[]|null $constraints An array of validation constraints * @param string[]|null $groups */ - #[HasNamedArguments] - public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null) + public function __construct(array|Constraint|null $constraints = null, ?array $groups = null, mixed $payload = null) { if (null === $constraints || [] === $constraints) { throw new MissingOptionsException(\sprintf('The options "constraints" must be set for constraint "%s".', self::class), ['constraints']); } - if (!$constraints instanceof Constraint && !\is_array($constraints) || \is_array($constraints) && !array_is_list($constraints)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - $options = $constraints; - } else { - $this->constraints = $constraints; - } - - parent::__construct($options ?? null, $groups, $payload); - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'constraints'; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } + $this->constraints = $constraints; - return ['constraints']; + parent::__construct(null, $groups, $payload); } protected function getCompositeOption(): string diff --git a/Constraints/Time.php b/Constraints/Time.php index e166ec0ff..1e602541b 100644 --- a/Constraints/Time.php +++ b/Constraints/Time.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is a valid time that follows the H:i:s format. @@ -37,7 +37,6 @@ class Time extends Constraint * @param string[]|null $groups * @param bool|null $withSeconds Whether to allow seconds in the given value (defaults to true) */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -45,11 +44,11 @@ public function __construct( mixed $payload = null, ?bool $withSeconds = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->withSeconds = $withSeconds ?? $this->withSeconds; $this->message = $message ?? $this->message; diff --git a/Constraints/Timezone.php b/Constraints/Timezone.php index 7c8297652..abfa5a6ec 100644 --- a/Constraints/Timezone.php +++ b/Constraints/Timezone.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -49,33 +48,19 @@ class Timezone extends Constraint * * @see \DateTimeZone */ - #[HasNamedArguments] public function __construct( - int|array|null $zone = null, + ?int $zone = null, ?string $message = null, ?string $countryCode = null, ?bool $intlCompatible = null, ?array $groups = null, mixed $payload = null, - ?array $options = null, ) { - if (\is_array($zone)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options = array_merge($zone, $options ?? []); - } elseif (null !== $zone) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options['value'] = $zone; - } - } - - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->zone = $zone ?? $this->zone; $this->message = $message ?? $this->message; - $this->countryCode = $countryCode ?? $this->countryCode; + $this->countryCode = $countryCode; $this->intlCompatible = $intlCompatible ?? $this->intlCompatible; if (null === $this->countryCode) { @@ -89,16 +74,4 @@ public function __construct( throw new ConstraintDefinitionException('The option "intlCompatible" can only be used when the PHP intl extension is available.'); } } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'zone'; - } } diff --git a/Constraints/Traverse.php b/Constraints/Traverse.php index 6571b31f1..ecb62781c 100644 --- a/Constraints/Traverse.php +++ b/Constraints/Traverse.php @@ -11,9 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Validates an object that needs to be traversed. @@ -28,36 +26,13 @@ class Traverse extends Constraint /** * @param bool|null $traverse Whether to traverse the given object or not (defaults to true). Pass an associative array to configure the constraint's options (e.g. payload). */ - #[HasNamedArguments] - public function __construct(bool|array|null $traverse = null, mixed $payload = null) + public function __construct(?bool $traverse = null, mixed $payload = null) { - if (\is_array($traverse) && \array_key_exists('groups', $traverse)) { - throw new ConstraintDefinitionException(\sprintf('The option "groups" is not supported by the constraint "%s".', __CLASS__)); - } - - if (\is_array($traverse)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - $options = $traverse; - $traverse = $options['traverse'] ?? null; - } - - parent::__construct($options ?? null, $payload); + parent::__construct(null, $payload); $this->traverse = $traverse ?? $this->traverse; } - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'traverse'; - } - public function getTargets(): string|array { return self::CLASS_CONSTRAINT; diff --git a/Constraints/Type.php b/Constraints/Type.php index 4c119a8c7..d97ee52fb 100644 --- a/Constraints/Type.php +++ b/Constraints/Type.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -33,56 +32,18 @@ class Type extends Constraint public string|array|null $type = null; /** - * @param string|list|null $type The type(s) to enforce on the value + * @param string|list|null $type The type(s) to enforce on the value * @param string[]|null $groups */ - #[HasNamedArguments] - public function __construct(string|array|null $type, ?string $message = null, ?array $groups = null, mixed $payload = null, ?array $options = null) + public function __construct(string|array|null $type, ?string $message = null, ?array $groups = null, mixed $payload = null) { - if (null === $type && !isset($options['type'])) { + if (null === $type) { throw new MissingOptionsException(\sprintf('The options "type" must be set for constraint "%s".', self::class), ['type']); } - if (\is_array($type) && \is_string(key($type))) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options = array_merge($type, $options ?? []); - $type = $options['type'] ?? null; - } elseif (null !== $type) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - } elseif (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - } - - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; - $this->type = $type ?? $this->type; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getDefaultOption(): ?string - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return 'type'; - } - - /** - * @deprecated since Symfony 7.4 - */ - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return ['type']; + $this->type = $type; } } diff --git a/Constraints/Ulid.php b/Constraints/Ulid.php index c9f9dbaf6..c415afae6 100644 --- a/Constraints/Ulid.php +++ b/Constraints/Ulid.php @@ -11,9 +11,9 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates that a value is a valid Universally Unique Lexicographically Sortable Identifier (ULID). @@ -50,7 +50,6 @@ class Ulid extends Constraint * @param string[]|null $groups * @param self::FORMAT_*|null $format */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -58,11 +57,11 @@ public function __construct( mixed $payload = null, ?string $format = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->format = $format ?? $this->format; diff --git a/Constraints/Unique.php b/Constraints/Unique.php index 3794b192c..25fa6c3c2 100644 --- a/Constraints/Unique.php +++ b/Constraints/Unique.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -41,7 +40,6 @@ class Unique extends Constraint * @param string[]|null $groups * @param string[]|string|null $fields Defines the key or keys in the collection that should be checked for uniqueness (defaults to null, which ensure uniqueness for all keys) */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -52,16 +50,16 @@ public function __construct( ?string $errorPath = null, ?bool $stopOnFirstError = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; - $this->normalizer = $normalizer ?? $this->normalizer; + $this->normalizer = $normalizer; $this->fields = $fields ?? $this->fields; - $this->errorPath = $errorPath ?? $this->errorPath; + $this->errorPath = $errorPath; $this->stopOnFirstError = $stopOnFirstError ?? $this->stopOnFirstError; if (null !== $this->normalizer && !\is_callable($this->normalizer)) { diff --git a/Constraints/Url.php b/Constraints/Url.php index 8a7549cb9..8cdcf54c6 100644 --- a/Constraints/Url.php +++ b/Constraints/Url.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -45,7 +44,6 @@ class Url extends Constraint * @param string[]|null $groups * @param bool|null $requireTld Whether to require the URL to include a top-level domain (defaults to false) */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -57,20 +55,20 @@ public function __construct( ?bool $requireTld = null, ?string $tldMessage = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); - if (null === ($options['requireTld'] ?? $requireTld)) { + if (null === $requireTld) { trigger_deprecation('symfony/validator', '7.1', 'Not passing a value for the "requireTld" option to the Url constraint is deprecated. Its default value will change to "true".'); } $this->message = $message ?? $this->message; $this->protocols = $protocols ?? $this->protocols; $this->relativeProtocol = $relativeProtocol ?? $this->relativeProtocol; - $this->normalizer = $normalizer ?? $this->normalizer; + $this->normalizer = $normalizer; $this->requireTld = $requireTld ?? $this->requireTld; $this->tldMessage = $tldMessage ?? $this->tldMessage; diff --git a/Constraints/Uuid.php b/Constraints/Uuid.php index 3602c2fb8..1173ab939 100644 --- a/Constraints/Uuid.php +++ b/Constraints/Uuid.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -100,7 +99,6 @@ class Uuid extends Constraint * @param bool|null $strict Whether to force the value to follow the RFC's input format rules; pass false to allow alternate formats (defaults to true) * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, @@ -110,16 +108,16 @@ public function __construct( ?array $groups = null, mixed $payload = null, ) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; $this->versions = (array) ($versions ?? $this->versions); $this->strict = $strict ?? $this->strict; - $this->normalizer = $normalizer ?? $this->normalizer; + $this->normalizer = $normalizer; 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))); diff --git a/Constraints/Valid.php b/Constraints/Valid.php index 6106627c6..fab3c96cd 100644 --- a/Constraints/Valid.php +++ b/Constraints/Valid.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Validates an object embedded in an object's property. @@ -28,14 +28,13 @@ class Valid extends Constraint * @param string[]|null $groups * @param bool|null $traverse Whether to validate {@see \Traversable} objects (defaults to true) */ - #[HasNamedArguments] public function __construct(?array $options = null, ?array $groups = null, $payload = null, ?bool $traverse = null) { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->traverse = $traverse ?? $this->traverse; } diff --git a/Constraints/Week.php b/Constraints/Week.php index f40f3462a..db9fbe6ba 100644 --- a/Constraints/Week.php +++ b/Constraints/Week.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -37,7 +36,6 @@ final class Week extends Constraint * @param non-empty-string|null $min * @param non-empty-string|null $max */ - #[HasNamedArguments] public function __construct( public ?string $min = null, public ?string $max = null, diff --git a/Constraints/When.php b/Constraints/When.php index b7482f938..34c2f4942 100644 --- a/Constraints/When.php +++ b/Constraints/When.php @@ -13,8 +13,8 @@ use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\LogicException; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -38,59 +38,29 @@ class When extends Composite * @param string[]|null $groups * @param Constraint[]|Constraint $otherwise One or multiple constraints that are applied if the expression returns false */ - #[HasNamedArguments] - public function __construct(string|Expression|array|\Closure $expression, array|Constraint|null $constraints = null, ?array $values = null, ?array $groups = null, $payload = null, ?array $options = null, array|Constraint $otherwise = []) + public function __construct(string|Expression|\Closure $expression, array|Constraint|null $constraints = null, ?array $values = null, ?array $groups = null, $payload = null, ?array $options = null, array|Constraint $otherwise = []) { if (!class_exists(ExpressionLanguage::class)) { throw new LogicException(\sprintf('The "symfony/expression-language" component is required to use the "%s" constraint. Try running "composer require symfony/expression-language".', __CLASS__)); } - if (\is_array($expression)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options = array_merge($expression, $options ?? []); - } else { - if (\is_array($options)) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); - - $options['expression'] = $expression; - if (null !== $constraints) { - $options['constraints'] = $constraints; - } - $options['otherwise'] = $otherwise; - } else { - if (null === $constraints) { - throw new MissingOptionsException(\sprintf('The options "constraints" must be set for constraint "%s".', self::class), ['constraints']); - } - - $this->expression = $expression; - $this->constraints = $constraints; - $this->otherwise = $otherwise; - } + if (null !== $options) { + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - if (!\is_array($options['constraints'] ?? [])) { - $options['constraints'] = [$options['constraints']]; + if (null === $constraints) { + throw new MissingOptionsException(\sprintf('The options "constraints" must be set for constraint "%s".', self::class), ['constraints']); } - if (!\is_array($options['otherwise'] ?? [])) { - $options['otherwise'] = [$options['otherwise']]; - } + $this->expression = $expression; + $this->constraints = $constraints; + $this->otherwise = $otherwise; - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->values = $values ?? $this->values; } - public function getRequiredOptions(): array - { - if (0 === \func_num_args() || func_get_arg(0)) { - trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__); - } - - return ['expression', 'constraints']; - } - public function getTargets(): string|array { return [self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT]; diff --git a/Constraints/WordCount.php b/Constraints/WordCount.php index 6b889aa4a..adb3184b5 100644 --- a/Constraints/WordCount.php +++ b/Constraints/WordCount.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -34,7 +33,6 @@ final class WordCount extends Constraint * @param int<0, max>|null $min * @param positive-int|null $max */ - #[HasNamedArguments] public function __construct( public ?int $min = null, public ?int $max = null, diff --git a/Constraints/Yaml.php b/Constraints/Yaml.php index 99f2092d1..a48d01207 100644 --- a/Constraints/Yaml.php +++ b/Constraints/Yaml.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\LogicException; use Symfony\Component\Yaml\Parser; @@ -32,7 +31,6 @@ class Yaml extends Constraint * @param int-mask-of<\Symfony\Component\Yaml\Yaml::PARSE_*> $flags * @param string[]|null $groups */ - #[HasNamedArguments] public function __construct( public string $message = 'This value is not valid YAML.', public int $flags = 0, diff --git a/Constraints/ZeroComparisonConstraintTrait.php b/Constraints/ZeroComparisonConstraintTrait.php index d0841adea..a1db7789a 100644 --- a/Constraints/ZeroComparisonConstraintTrait.php +++ b/Constraints/ZeroComparisonConstraintTrait.php @@ -11,8 +11,7 @@ namespace Symfony\Component\Validator\Constraints; -use Symfony\Component\Validator\Attribute\HasNamedArguments; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * @internal @@ -22,22 +21,13 @@ */ trait ZeroComparisonConstraintTrait { - #[HasNamedArguments] public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) { if (null !== $options) { - trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + throw new InvalidArgumentException(\sprintf('Passing an array of options to configure the "%s" constraint is no longer supported.', static::class)); } - if (\is_array($options) && isset($options['propertyPath'])) { - throw new ConstraintDefinitionException(\sprintf('The "propertyPath" option of the "%s" constraint cannot be set.', static::class)); - } - - if (\is_array($options) && isset($options['value'])) { - throw new ConstraintDefinitionException(\sprintf('The "value" option of the "%s" constraint cannot be set.', static::class)); - } - - parent::__construct(0, null, $message, $groups, $payload, $options); + parent::__construct(0, null, $message, $groups, $payload); } public function validatedBy(): string diff --git a/Mapping/Loader/AbstractLoader.php b/Mapping/Loader/AbstractLoader.php index 67b7b2010..52c46993b 100644 --- a/Mapping/Loader/AbstractLoader.php +++ b/Mapping/Loader/AbstractLoader.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Mapping\Loader; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MappingException; @@ -35,11 +34,6 @@ abstract class AbstractLoader implements LoaderInterface protected array $namespaces = []; - /** - * @var array - */ - private array $namedArgumentsCache = []; - /** * Adds a namespace alias. * @@ -84,32 +78,22 @@ protected function newConstraint(string $name, mixed $options = null): Constrain $className = self::DEFAULT_NAMESPACE.$name; } - if ($this->namedArgumentsCache[$className] ??= (bool) (new \ReflectionMethod($className, '__construct'))->getAttributes(HasNamedArguments::class)) { - if (null === $options) { - return new $className(); - } - - if (!\is_array($options)) { - return new $className($options); - } - - if (1 === \count($options) && isset($options['value'])) { - return new $className($options['value']); - } - - if (array_is_list($options)) { - return new $className($options); - } + if (null === $options) { + return new $className(); + } - return new $className(...$options); + if (!\is_array($options)) { + return new $className($options); } - if ($options) { - trigger_deprecation('symfony/validator', '7.3', 'Using constraints not supporting named arguments is deprecated. Try adding the HasNamedArguments attribute to %s.', $className); + if (1 === \count($options) && isset($options['value'])) { + return new $className($options['value']); + } + if (array_is_list($options)) { return new $className($options); } - return new $className(); + return new $className(...$options); } } diff --git a/Tests/ConstraintTest.php b/Tests/ConstraintTest.php index 441850977..38d08f644 100644 --- a/Tests/ConstraintTest.php +++ b/Tests/ConstraintTest.php @@ -13,166 +13,12 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\InvalidArgumentException; -use Symfony\Component\Validator\Exception\InvalidOptionsException; -use Symfony\Component\Validator\Exception\MissingOptionsException; use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; -use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; -use Symfony\Component\Validator\Tests\Fixtures\ConstraintC; -use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithStaticProperty; -use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithTypedProperty; -use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValue; -use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValueAsDefault; -use Symfony\Component\Validator\Tests\Fixtures\LegacyConstraintA; class ConstraintTest extends TestCase { - /** - * @group legacy - */ - public function testSetProperties() - { - $constraint = new LegacyConstraintA([ - 'property1' => 'foo', - 'property2' => 'bar', - ]); - - $this->assertEquals('foo', $constraint->property1); - $this->assertEquals('bar', $constraint->property2); - } - - /** - * @group legacy - */ - public function testSetNotExistingPropertyThrowsException() - { - $this->expectException(InvalidOptionsException::class); - - new LegacyConstraintA([ - 'foo' => 'bar', - ]); - } - - /** - * @group legacy - */ - public function testMagicPropertiesAreNotAllowed() - { - $constraint = new LegacyConstraintA(); - - $this->expectException(InvalidOptionsException::class); - - $constraint->foo = 'bar'; - } - - /** - * @group legacy - */ - public function testInvalidAndRequiredOptionsPassed() - { - $this->expectException(InvalidOptionsException::class); - - new ConstraintC([ - 'option1' => 'default', - 'foo' => 'bar', - ]); - } - - /** - * @group legacy - */ - public function testSetDefaultProperty() - { - $constraint = new LegacyConstraintA('foo'); - - $this->assertEquals('foo', $constraint->property2); - } - - /** - * @group legacy - */ - public function testSetDefaultPropertyDoctrineStyle() - { - $constraint = new LegacyConstraintA(['value' => 'foo']); - - $this->assertEquals('foo', $constraint->property2); - } - - /** - * @group legacy - */ - public function testSetDefaultPropertyDoctrineStylePlusOtherProperty() - { - $constraint = new LegacyConstraintA(['value' => 'foo', 'property1' => 'bar']); - - $this->assertEquals('foo', $constraint->property2); - $this->assertEquals('bar', $constraint->property1); - } - - /** - * @group legacy - */ - public function testSetDefaultPropertyDoctrineStyleWhenDefaultPropertyIsNamedValue() - { - $constraint = new ConstraintWithValueAsDefault(['value' => 'foo']); - - $this->assertEquals('foo', $constraint->value); - $this->assertNull($constraint->property); - } - - /** - * @group legacy - */ - public function testDontSetDefaultPropertyIfValuePropertyExists() - { - $constraint = new ConstraintWithValue(['value' => 'foo']); - - $this->assertEquals('foo', $constraint->value); - $this->assertNull($constraint->property); - } - - /** - * @group legacy - */ - public function testSetUndefinedDefaultProperty() - { - $this->expectException(ConstraintDefinitionException::class); - - new ConstraintB('foo'); - } - - /** - * @group legacy - */ - public function testRequiredOptionsMustBeDefined() - { - $this->expectException(MissingOptionsException::class); - - new ConstraintC(); - } - - /** - * @group legacy - */ - public function testRequiredOptionsPassed() - { - $constraint = new ConstraintC(['option1' => 'default']); - - $this->assertSame('default', $constraint->option1); - } - - /** - * @group legacy - */ - public function testGroupsAreConvertedToArray() - { - $constraint = new LegacyConstraintA(['groups' => 'Foo']); - - $this->assertEquals(['Foo'], $constraint->groups); - } - public function testAddDefaultGroupAddsGroup() { $constraint = new ConstraintA(null, null, ['Default']); @@ -180,25 +26,6 @@ public function testAddDefaultGroupAddsGroup() $this->assertEquals(['Default', 'Foo'], $constraint->groups); } - /** - * @group legacy - */ - public function testAllowsSettingZeroRequiredPropertyValue() - { - $constraint = new LegacyConstraintA(0); - $this->assertEquals(0, $constraint->property2); - } - - /** - * @group legacy - */ - public function testCanCreateConstraintWithNoDefaultOptionAndEmptyArray() - { - $constraint = new ConstraintB([]); - - $this->assertSame([Constraint::PROPERTY_CONSTRAINT, Constraint::CLASS_CONSTRAINT], $constraint->getTargets()); - } - public function testGetTargetsCanBeString() { $constraint = new ClassConstraint(); @@ -222,21 +49,6 @@ public function testSerialize() $this->assertEquals($constraint, $restoredConstraint); } - /** - * @group legacy - */ - public function testSerializeDoctrineStyle() - { - $constraint = new LegacyConstraintA([ - 'property1' => 'foo', - 'property2' => 'bar', - ]); - - $restoredConstraint = unserialize(serialize($constraint)); - - $this->assertEquals($constraint, $restoredConstraint); - } - public function testSerializeInitializesGroupsOptionToDefault() { $constraint = new ConstraintA('foo', 'bar'); @@ -248,27 +60,6 @@ public function testSerializeInitializesGroupsOptionToDefault() $this->assertEquals($expected, $constraint); } - /** - * @group legacy - */ - public function testSerializeInitializesGroupsOptionToDefaultDoctrineStyle() - { - $constraint = new LegacyConstraintA([ - 'property1' => 'foo', - 'property2' => 'bar', - ]); - - $constraint = unserialize(serialize($constraint)); - - $expected = new LegacyConstraintA([ - 'property1' => 'foo', - 'property2' => 'bar', - 'groups' => 'Default', - ]); - - $this->assertEquals($expected, $constraint); - } - public function testSerializeKeepsCustomGroups() { $constraint = new ConstraintA('foo', 'bar', ['MyGroup']); @@ -278,97 +69,9 @@ public function testSerializeKeepsCustomGroups() $this->assertSame(['MyGroup'], $constraint->groups); } - /** - * @group legacy - */ - public function testSerializeKeepsCustomGroupsDoctrineStyle() - { - $constraint = new LegacyConstraintA([ - 'property1' => 'foo', - 'property2' => 'bar', - 'groups' => 'MyGroup', - ]); - - $constraint = unserialize(serialize($constraint)); - - $this->assertSame(['MyGroup'], $constraint->groups); - } - public function testGetErrorNameForUnknownCode() { $this->expectException(InvalidArgumentException::class); Constraint::getErrorName(1); } - - /** - * @group legacy - */ - public function testOptionsAsDefaultOption() - { - $constraint = new LegacyConstraintA($options = ['value1']); - - $this->assertEquals($options, $constraint->property2); - - $constraint = new LegacyConstraintA($options = ['value1', 'property1' => 'value2']); - - $this->assertEquals($options, $constraint->property2); - } - - /** - * @group legacy - */ - public function testInvalidOptions() - { - $this->expectException(InvalidOptionsException::class); - $this->expectExceptionMessage('The options "0", "5" do not exist in constraint "Symfony\Component\Validator\Tests\Fixtures\LegacyConstraintA".'); - new LegacyConstraintA(['property2' => 'foo', 'bar', 5 => 'baz']); - } - - /** - * @group legacy - */ - public function testOptionsWithInvalidInternalPointer() - { - $options = ['property1' => 'foo']; - next($options); - next($options); - - $constraint = new LegacyConstraintA($options); - - $this->assertEquals('foo', $constraint->property1); - } - - /** - * @group legacy - */ - public function testAttributeSetUndefinedDefaultOption() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('No default option is configured for constraint "Symfony\Component\Validator\Tests\Fixtures\ConstraintB".'); - new ConstraintB(['value' => 1]); - } - - /** - * @group legacy - */ - public function testStaticPropertiesAreNoOptions() - { - $this->expectException(InvalidOptionsException::class); - - new ConstraintWithStaticProperty([ - 'foo' => 'bar', - ]); - } - - /** - * @group legacy - */ - public function testSetTypedProperty() - { - $constraint = new ConstraintWithTypedProperty([ - 'foo' => 'bar', - ]); - - $this->assertSame('bar', $constraint->foo); - } } diff --git a/Tests/Constraints/CallbackValidatorTest.php b/Tests/Constraints/CallbackValidatorTest.php index 7fbcd2714..11ab8f860 100644 --- a/Tests/Constraints/CallbackValidatorTest.php +++ b/Tests/Constraints/CallbackValidatorTest.php @@ -15,7 +15,6 @@ use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\CallbackValidator; use Symfony\Component\Validator\Context\ExecutionContextInterface; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; class CallbackValidatorTest_Class @@ -177,25 +176,9 @@ public function testArrayCallableExplicitName() ->assertRaised(); } - public function testExpectValidMethods() - { - $this->expectException(ConstraintDefinitionException::class); - $object = new CallbackValidatorTest_Object(); - - $this->validator->validate($object, new Callback(callback: ['foobar'])); - } - - public function testExpectValidCallbacks() - { - $this->expectException(ConstraintDefinitionException::class); - $object = new CallbackValidatorTest_Object(); - - $this->validator->validate($object, new Callback(callback: ['foo', 'bar'])); - } - public function testConstraintGetTargets() { - $constraint = new Callback(callback: []); + $constraint = new Callback(callback: 'strtolower'); $targets = [Constraint::CLASS_CONSTRAINT, Constraint::PROPERTY_CONSTRAINT]; $this->assertEquals($targets, $constraint->getTargets()); diff --git a/Tests/Constraints/CardSchemeTest.php b/Tests/Constraints/CardSchemeTest.php index 154d35a25..a50930b9b 100644 --- a/Tests/Constraints/CardSchemeTest.php +++ b/Tests/Constraints/CardSchemeTest.php @@ -46,16 +46,6 @@ public function testMissingSchemes() new CardScheme(null); } - - /** - * @group legacy - */ - public function testSchemesInOptionsArray() - { - $constraint = new CardScheme(null, options: ['schemes' => [CardScheme::MASTERCARD]]); - - $this->assertSame([CardScheme::MASTERCARD], $constraint->schemes); - } } class CardSchemeDummy diff --git a/Tests/Constraints/CascadeTest.php b/Tests/Constraints/CascadeTest.php index fc4d7ce0f..a472609fd 100644 --- a/Tests/Constraints/CascadeTest.php +++ b/Tests/Constraints/CascadeTest.php @@ -34,16 +34,6 @@ public function testExcludeProperties() self::assertSame(['foo' => 0, 'bar' => 1], $constraint->exclude); } - - /** - * @group legacy - */ - public function testExcludePropertiesDoctrineStyle() - { - $constraint = new Cascade(['exclude' => ['foo', 'bar']]); - - self::assertSame(['foo' => 0, 'bar' => 1], $constraint->exclude); - } } #[Cascade] diff --git a/Tests/Constraints/ChoiceTest.php b/Tests/Constraints/ChoiceTest.php index ddfb31b11..5cecf3a9a 100644 --- a/Tests/Constraints/ChoiceTest.php +++ b/Tests/Constraints/ChoiceTest.php @@ -15,20 +15,9 @@ use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; -use Symfony\Component\Validator\Tests\Fixtures\ConstraintChoiceWithPreset; class ChoiceTest extends TestCase { - /** - * @group legacy - */ - public function testSetDefaultPropertyChoice() - { - $constraint = new ConstraintChoiceWithPreset('A'); - - self::assertEquals(['A', 'B', 'C'], $constraint->choices); - } - public function testAttributes() { $metadata = new ClassMetadata(ChoiceDummy::class); diff --git a/Tests/Constraints/ChoiceValidatorTest.php b/Tests/Constraints/ChoiceValidatorTest.php index acfbb8419..74533a850 100644 --- a/Tests/Constraints/ChoiceValidatorTest.php +++ b/Tests/Constraints/ChoiceValidatorTest.php @@ -81,34 +81,6 @@ public function testValidChoiceArray() $this->assertNoViolation(); } - /** - * @group legacy - */ - public function testValidChoiceArrayFirstArgument() - { - $this->validator->validate('bar', new Choice(['foo', 'bar'])); - - $this->assertNoViolation(); - } - - /** - * @group legacy - * - * @dataProvider provideLegacyConstraintsWithChoicesArrayDoctrineStyle - */ - public function testValidChoiceArrayDoctrineStyle(Choice $constraint) - { - $this->validator->validate('bar', $constraint); - - $this->assertNoViolation(); - } - - public static function provideLegacyConstraintsWithChoicesArrayDoctrineStyle(): iterable - { - yield 'Doctrine style' => [new Choice(['choices' => ['foo', 'bar']])]; - yield 'Doctrine default option' => [new Choice(['value' => ['foo', 'bar']])]; - } - /** * @dataProvider provideConstraintsWithCallbackFunction */ @@ -126,27 +98,6 @@ public static function provideConstraintsWithCallbackFunction(): iterable yield 'named arguments, static method' => [new Choice(callback: [__CLASS__, 'staticCallback'])]; } - /** - * @group legacy - * - * @dataProvider provideLegacyConstraintsWithCallbackFunctionDoctrineStyle - */ - public function testValidChoiceCallbackFunctionDoctrineStyle(Choice $constraint) - { - $this->validator->validate('bar', $constraint); - - $this->assertNoViolation(); - } - - public static function provideLegacyConstraintsWithCallbackFunctionDoctrineStyle(): iterable - { - yield 'doctrine style, namespaced function' => [new Choice(['callback' => __NAMESPACE__.'\choice_callback'])]; - yield 'doctrine style, closure' => [new Choice([ - 'callback' => fn () => ['foo', 'bar'], - ])]; - yield 'doctrine style, static method' => [new Choice(['callback' => [__CLASS__, 'staticCallback']])]; - } - public function testValidChoiceCallbackContextMethod() { // search $this for "staticCallback" @@ -194,19 +145,6 @@ public function testMultipleChoices() $this->assertNoViolation(); } - /** - * @group legacy - */ - public function testMultipleChoicesDoctrineStyle() - { - $this->validator->validate(['baz', 'bar'], new Choice([ - 'choices' => ['foo', 'bar', 'baz'], - 'multiple' => true, - ])); - - $this->assertNoViolation(); - } - public function testInvalidChoice() { $this->validator->validate('baz', new Choice(choices: ['foo', 'bar'], message: 'myMessage')); @@ -218,20 +156,6 @@ public function testInvalidChoice() ->assertRaised(); } - /** - * @group legacy - */ - public function testInvalidChoiceDoctrineStyle() - { - $this->validator->validate('baz', new Choice(['choices' => ['foo', 'bar'], 'message' => 'myMessage'])); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', '"baz"') - ->setParameter('{{ choices }}', '"foo", "bar"') - ->setCode(Choice::NO_SUCH_CHOICE_ERROR) - ->assertRaised(); - } - public function testInvalidChoiceEmptyChoices() { $constraint = new Choice( @@ -266,25 +190,6 @@ public function testInvalidChoiceMultiple() ->assertRaised(); } - /** - * @group legacy - */ - public function testInvalidChoiceMultipleDoctrineStyle() - { - $this->validator->validate(['foo', 'baz'], new Choice([ - 'choices' => ['foo', 'bar'], - 'multipleMessage' => 'myMessage', - 'multiple' => true, - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', '"baz"') - ->setParameter('{{ choices }}', '"foo", "bar"') - ->setInvalidValue('baz') - ->setCode(Choice::NO_SUCH_CHOICE_ERROR) - ->assertRaised(); - } - public function testTooFewChoices() { $value = ['foo']; @@ -306,30 +211,6 @@ public function testTooFewChoices() ->assertRaised(); } - /** - * @group legacy - */ - public function testTooFewChoicesDoctrineStyle() - { - $value = ['foo']; - - $this->setValue($value); - - $this->validator->validate($value, new Choice([ - 'choices' => ['foo', 'bar', 'moo', 'maa'], - 'multiple' => true, - 'min' => 2, - 'minMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ limit }}', 2) - ->setInvalidValue($value) - ->setPlural(2) - ->setCode(Choice::TOO_FEW_ERROR) - ->assertRaised(); - } - public function testTooManyChoices() { $value = ['foo', 'bar', 'moo']; @@ -351,30 +232,6 @@ public function testTooManyChoices() ->assertRaised(); } - /** - * @group legacy - */ - public function testTooManyChoicesDoctrineStyle() - { - $value = ['foo', 'bar', 'moo']; - - $this->setValue($value); - - $this->validator->validate($value, new Choice([ - 'choices' => ['foo', 'bar', 'moo', 'maa'], - 'multiple' => true, - 'max' => 2, - 'maxMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ limit }}', 2) - ->setInvalidValue($value) - ->setPlural(2) - ->setCode(Choice::TOO_MANY_ERROR) - ->assertRaised(); - } - public function testStrictAllowsExactValue() { $constraint = new Choice(choices: [1, 2]); diff --git a/Tests/Constraints/CollectionTest.php b/Tests/Constraints/CollectionTest.php index c1c32f90a..2aed332a3 100644 --- a/Tests/Constraints/CollectionTest.php +++ b/Tests/Constraints/CollectionTest.php @@ -18,7 +18,6 @@ use Symfony\Component\Validator\Constraints\Required; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; -use Symfony\Component\Validator\Exception\InvalidOptionsException; use Symfony\Component\Validator\Exception\MissingOptionsException; /** @@ -26,17 +25,6 @@ */ class CollectionTest extends TestCase { - /** - * @group legacy - */ - public function testRejectNonConstraints() - { - $this->expectException(InvalidOptionsException::class); - new Collection([ - 'foo' => 'bar', - ]); - } - public function testRejectValidConstraint() { $this->expectException(ConstraintDefinitionException::class); @@ -103,25 +91,6 @@ public function testConstraintHasDefaultGroupWithOptionalValues() $this->assertEquals(['Default'], $constraint->fields['bar']->groups); } - /** - * @group legacy - */ - public function testOnlySomeKeysAreKnowOptions() - { - $constraint = new Collection([ - 'fields' => [new Required()], - 'properties' => [new Required()], - 'catalog' => [new Optional()], - ]); - - $this->assertArrayHasKey('fields', $constraint->fields); - $this->assertInstanceOf(Required::class, $constraint->fields['fields']); - $this->assertArrayHasKey('properties', $constraint->fields); - $this->assertInstanceOf(Required::class, $constraint->fields['properties']); - $this->assertArrayHasKey('catalog', $constraint->fields); - $this->assertInstanceOf(Optional::class, $constraint->fields['catalog']); - } - public function testAllKeysAreKnowOptions() { $constraint = new Collection( diff --git a/Tests/Constraints/CompositeTest.php b/Tests/Constraints/CompositeTest.php index f2670dded..d079d23a8 100644 --- a/Tests/Constraints/CompositeTest.php +++ b/Tests/Constraints/CompositeTest.php @@ -35,11 +35,6 @@ protected function getCompositeOption(): array { return ['constraints', 'otherNested']; } - - public function getDefaultOption(): ?string - { - return 'constraints'; - } } /** diff --git a/Tests/Constraints/CompoundTest.php b/Tests/Constraints/CompoundTest.php index c3c55eb3e..7886d4e68 100644 --- a/Tests/Constraints/CompoundTest.php +++ b/Tests/Constraints/CompoundTest.php @@ -13,22 +13,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Compound; -use Symfony\Component\Validator\Constraints\Length; -use Symfony\Component\Validator\Constraints\NotBlank; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; class CompoundTest extends TestCase { - /** - * @group legacy - */ - public function testItCannotRedefineConstraintsOption() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('You can\'t redefine the "constraints" option. Use the "Symfony\Component\Validator\Constraints\Compound::getConstraints()" method instead.'); - new EmptyCompound(['constraints' => [new NotBlank()]]); - } - public function testGroupsAndPayload() { $payload = new \stdClass(); @@ -37,28 +24,6 @@ public function testGroupsAndPayload() $this->assertSame(['my-group', 'my-other-group'], $compound->groups); $this->assertSame($payload, $compound->payload); } - - /** - * @group legacy - */ - public function testGroupsAndPayloadInOptionsArray() - { - $payload = new \stdClass(); - $compound = new EmptyCompound(['groups' => ['my-group', 'my-other-group'], 'payload' => $payload]); - - $this->assertSame(['my-group', 'my-other-group'], $compound->groups); - $this->assertSame($payload, $compound->payload); - } - - /** - * @group legacy - */ - public function testCanDependOnNormalizedOptions() - { - $constraint = new ForwardingOptionCompound($min = 3); - - $this->assertSame($min, $constraint->constraints[0]->min); - } } class EmptyCompound extends Compound @@ -68,20 +33,3 @@ protected function getConstraints(array $options): array return []; } } - -class ForwardingOptionCompound extends Compound -{ - public $min; - - public function getDefaultOption(): ?string - { - return 'min'; - } - - protected function getConstraints(array $options): array - { - return [ - new Length(min: $options['min'] ?? null), - ]; - } -} diff --git a/Tests/Constraints/CountValidatorTestCase.php b/Tests/Constraints/CountValidatorTestCase.php index da319cd8b..649471c2e 100644 --- a/Tests/Constraints/CountValidatorTestCase.php +++ b/Tests/Constraints/CountValidatorTestCase.php @@ -69,19 +69,6 @@ public static function getFiveOrMoreElements() ]; } - /** - * @group legacy - * - * @dataProvider getThreeOrLessElements - */ - public function testValidValuesMax($value) - { - $constraint = new Count(['max' => 3]); - $this->validator->validate($value, $constraint); - - $this->assertNoViolation(); - } - /** * @dataProvider getThreeOrLessElements */ @@ -93,19 +80,6 @@ public function testValidValuesMaxNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getFiveOrMoreElements - */ - public function testValidValuesMin($value) - { - $constraint = new Count(['min' => 5]); - $this->validator->validate($value, $constraint); - - $this->assertNoViolation(); - } - /** * @dataProvider getFiveOrMoreElements */ @@ -117,19 +91,6 @@ public function testValidValuesMinNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getFourElements - */ - public function testValidValuesExact($value) - { - $constraint = new Count(4); - $this->validator->validate($value, $constraint); - - $this->assertNoViolation(); - } - /** * @dataProvider getFourElements */ @@ -141,29 +102,6 @@ public function testValidValuesExactNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getFiveOrMoreElements - */ - public function testTooManyValues($value) - { - $constraint = new Count([ - 'max' => 4, - 'maxMessage' => 'myMessage', - ]); - - $this->validator->validate($value, $constraint); - - $this->buildViolation('myMessage') - ->setParameter('{{ count }}', \count($value)) - ->setParameter('{{ limit }}', 4) - ->setInvalidValue($value) - ->setPlural(4) - ->setCode(Count::TOO_MANY_ERROR) - ->assertRaised(); - } - /** * @dataProvider getFiveOrMoreElements */ @@ -182,29 +120,6 @@ public function testTooManyValuesNamed($value) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getThreeOrLessElements - */ - public function testTooFewValues($value) - { - $constraint = new Count([ - 'min' => 4, - 'minMessage' => 'myMessage', - ]); - - $this->validator->validate($value, $constraint); - - $this->buildViolation('myMessage') - ->setParameter('{{ count }}', \count($value)) - ->setParameter('{{ limit }}', 4) - ->setInvalidValue($value) - ->setPlural(4) - ->setCode(Count::TOO_FEW_ERROR) - ->assertRaised(); - } - /** * @dataProvider getThreeOrLessElements */ @@ -223,30 +138,6 @@ public function testTooFewValuesNamed($value) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getFiveOrMoreElements - */ - public function testTooManyValuesExact($value) - { - $constraint = new Count([ - 'min' => 4, - 'max' => 4, - 'exactMessage' => 'myMessage', - ]); - - $this->validator->validate($value, $constraint); - - $this->buildViolation('myMessage') - ->setParameter('{{ count }}', \count($value)) - ->setParameter('{{ limit }}', 4) - ->setInvalidValue($value) - ->setPlural(4) - ->setCode(Count::NOT_EQUAL_COUNT_ERROR) - ->assertRaised(); - } - /** * @dataProvider getFiveOrMoreElements */ diff --git a/Tests/Constraints/DisableAutoMappingTest.php b/Tests/Constraints/DisableAutoMappingTest.php index e7b6a8db7..dc045f5d9 100644 --- a/Tests/Constraints/DisableAutoMappingTest.php +++ b/Tests/Constraints/DisableAutoMappingTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\DisableAutoMapping; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Mapping\AutoMappingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -23,17 +22,6 @@ */ class DisableAutoMappingTest extends TestCase { - /** - * @group legacy - */ - public function testGroups() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage(\sprintf('The option "groups" is not supported by the constraint "%s".', DisableAutoMapping::class)); - - new DisableAutoMapping(['groups' => 'foo']); - } - public function testDisableAutoMappingAttribute() { $metadata = new ClassMetadata(DisableAutoMappingDummy::class); diff --git a/Tests/Constraints/EmailTest.php b/Tests/Constraints/EmailTest.php index 9436b4bd6..6efaac01a 100644 --- a/Tests/Constraints/EmailTest.php +++ b/Tests/Constraints/EmailTest.php @@ -54,26 +54,6 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $email->normalizer); } - /** - * @group legacy - */ - public function testInvalidNormalizerThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("string" given).'); - new Email(['normalizer' => 'Unknown Callable']); - } - - /** - * @group legacy - */ - public function testInvalidNormalizerObjectThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("stdClass" given).'); - new Email(['normalizer' => new \stdClass()]); - } - public function testAttribute() { $metadata = new ClassMetadata(EmailDummy::class); diff --git a/Tests/Constraints/EnableAutoMappingTest.php b/Tests/Constraints/EnableAutoMappingTest.php index 525a62ed5..1f0ceb7ee 100644 --- a/Tests/Constraints/EnableAutoMappingTest.php +++ b/Tests/Constraints/EnableAutoMappingTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\EnableAutoMapping; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Mapping\AutoMappingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -23,17 +22,6 @@ */ class EnableAutoMappingTest extends TestCase { - /** - * @group legacy - */ - public function testGroups() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage(\sprintf('The option "groups" is not supported by the constraint "%s".', EnableAutoMapping::class)); - - new EnableAutoMapping(['groups' => 'foo']); - } - public function testDisableAutoMappingAttribute() { $metadata = new ClassMetadata(EnableAutoMappingDummy::class); diff --git a/Tests/Constraints/ExpressionSyntaxTest.php b/Tests/Constraints/ExpressionSyntaxTest.php index 8731a5d85..c0d3aef35 100644 --- a/Tests/Constraints/ExpressionSyntaxTest.php +++ b/Tests/Constraints/ExpressionSyntaxTest.php @@ -44,16 +44,6 @@ public static function provideServiceValidatedConstraints(): iterable yield 'attribute' => [$metadata->properties['b']->constraints[0]]; } - /** - * @group legacy - */ - public function testValidatedByServiceDoctrineStyle() - { - $constraint = new ExpressionSyntax(['service' => 'my_service']); - - self::assertSame('my_service', $constraint->validatedBy()); - } - public function testAttributes() { $metadata = new ClassMetadata(ExpressionSyntaxDummy::class); diff --git a/Tests/Constraints/ExpressionTest.php b/Tests/Constraints/ExpressionTest.php index 22e5c624e..d5711a80e 100644 --- a/Tests/Constraints/ExpressionTest.php +++ b/Tests/Constraints/ExpressionTest.php @@ -50,39 +50,6 @@ public function testMissingPattern() new Expression(null); } - - /** - * @group legacy - */ - public function testMissingPatternDoctrineStyle() - { - $this->expectException(MissingOptionsException::class); - $this->expectExceptionMessage(\sprintf('The options "expression" must be set for constraint "%s".', Expression::class)); - - new Expression([]); - } - - /** - * @group legacy - */ - public function testInitializeWithOptionsArray() - { - $constraint = new Expression([ - 'expression' => '!this.getParent().get("field2").getData()', - ]); - - $this->assertSame('!this.getParent().get("field2").getData()', $constraint->expression); - } - - /** - * @group legacy - */ - public function testExpressionInOptionsArray() - { - $constraint = new Expression(null, options: ['expression' => '!this.getParent().get("field2").getData()']); - - $this->assertSame('!this.getParent().get("field2").getData()', $constraint->expression); - } } class ExpressionDummy diff --git a/Tests/Constraints/FileValidatorTestCase.php b/Tests/Constraints/FileValidatorTestCase.php index 585e56b87..9bc035d56 100644 --- a/Tests/Constraints/FileValidatorTestCase.php +++ b/Tests/Constraints/FileValidatorTestCase.php @@ -375,38 +375,6 @@ public function testInvalidMimeType() ->assertRaised(); } - /** - * @group legacy - */ - public function testInvalidMimeTypeDoctrineStyle() - { - $file = $this - ->getMockBuilder(\Symfony\Component\HttpFoundation\File\File::class) - ->setConstructorArgs([__DIR__.'/Fixtures/foo']) - ->getMock(); - $file - ->expects($this->once()) - ->method('getPathname') - ->willReturn($this->path); - $file - ->expects($this->once()) - ->method('getMimeType') - ->willReturn('application/pdf'); - - $this->validator->validate($file, new File([ - 'mimeTypes' => ['image/png', 'image/jpg'], - 'mimeTypesMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ type }}', '"application/pdf"') - ->setParameter('{{ types }}', '"image/png", "image/jpg"') - ->setParameter('{{ file }}', '"'.$this->path.'"') - ->setParameter('{{ name }}', '"'.basename($this->path).'"') - ->setCode(File::INVALID_MIME_TYPE_ERROR) - ->assertRaised(); - } - public function testInvalidWildcardMimeType() { $file = $this @@ -451,24 +419,6 @@ public function testDisallowEmpty() ->assertRaised(); } - /** - * @group legacy - */ - public function testDisallowEmptyDoctrineStyle() - { - ftruncate($this->file, 0); - - $this->validator->validate($this->getFile($this->path), new File([ - 'disallowEmptyMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ file }}', '"'.$this->path.'"') - ->setParameter('{{ name }}', '"'.basename($this->path).'"') - ->setCode(File::EMPTY_ERROR) - ->assertRaised(); - } - /** * @dataProvider uploadedFileErrorProvider */ diff --git a/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php b/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php index 47f190851..05756c5d1 100644 --- a/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php +++ b/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php @@ -14,7 +14,6 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\GreaterThanOrEqualValidator; use Symfony\Component\Validator\Constraints\PositiveOrZero; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @author Jan Schädlich @@ -61,28 +60,6 @@ public static function provideInvalidComparisons(): array ]; } - /** - * @group legacy - */ - public function testThrowsConstraintExceptionIfPropertyPath() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('The "propertyPath" option of the "Symfony\Component\Validator\Constraints\PositiveOrZero" constraint cannot be set.'); - - return new PositiveOrZero(['propertyPath' => 'field']); - } - - /** - * @group legacy - */ - public function testThrowsConstraintExceptionIfValue() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('The "value" option of the "Symfony\Component\Validator\Constraints\PositiveOrZero" constraint cannot be set.'); - - return new PositiveOrZero(['value' => 0]); - } - /** * @dataProvider provideInvalidConstraintOptions */ diff --git a/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php b/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php index 6b58bff85..d8388c643 100644 --- a/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php +++ b/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php @@ -14,7 +14,6 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\GreaterThanValidator; use Symfony\Component\Validator\Constraints\Positive; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @author Jan Schädlich @@ -58,28 +57,6 @@ public static function provideInvalidComparisons(): array ]; } - /** - * @group legacy - */ - public function testThrowsConstraintExceptionIfPropertyPath() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('The "propertyPath" option of the "Symfony\Component\Validator\Constraints\Positive" constraint cannot be set.'); - - return new Positive(['propertyPath' => 'field']); - } - - /** - * @group legacy - */ - public function testThrowsConstraintExceptionIfValue() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('The "value" option of the "Symfony\Component\Validator\Constraints\Positive" constraint cannot be set.'); - - return new Positive(['value' => 0]); - } - /** * @dataProvider provideInvalidConstraintOptions */ diff --git a/Tests/Constraints/ImageValidatorTest.php b/Tests/Constraints/ImageValidatorTest.php index f5d712208..5bfa1c6c8 100644 --- a/Tests/Constraints/ImageValidatorTest.php +++ b/Tests/Constraints/ImageValidatorTest.php @@ -84,23 +84,6 @@ public function testFileNotFound() ->assertRaised(); } - /** - * Checks that the logic from FileValidator still works. - * - * @group legacy - */ - public function testFileNotFoundDoctrineStyle() - { - $this->validator->validate('foobar', new Image([ - 'notFoundMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ file }}', '"foobar"') - ->setCode(Image::NOT_FOUND_ERROR) - ->assertRaised(); - } - public function testValidSize() { $constraint = new Image( @@ -126,23 +109,6 @@ public function testWidthTooSmall() ->assertRaised(); } - /** - * @group legacy - */ - public function testWidthTooSmallDoctrineStyle() - { - $this->validator->validate($this->image, new Image([ - 'minWidth' => 3, - 'minWidthMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ width }}', '2') - ->setParameter('{{ min_width }}', '3') - ->setCode(Image::TOO_NARROW_ERROR) - ->assertRaised(); - } - public function testWidthTooBig() { $this->validator->validate($this->image, new Image(maxWidth: 1, maxWidthMessage: 'myMessage')); @@ -154,23 +120,6 @@ public function testWidthTooBig() ->assertRaised(); } - /** - * @group legacy - */ - public function testWidthTooBigDoctrineStyle() - { - $this->validator->validate($this->image, new Image([ - 'maxWidth' => 1, - 'maxWidthMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ width }}', '2') - ->setParameter('{{ max_width }}', '1') - ->setCode(Image::TOO_WIDE_ERROR) - ->assertRaised(); - } - public function testHeightTooSmall() { $this->validator->validate($this->image, new Image(minHeight: 3, minHeightMessage: 'myMessage')); @@ -182,23 +131,6 @@ public function testHeightTooSmall() ->assertRaised(); } - /** - * @group legacy - */ - public function testHeightTooSmallDoctrineStyle() - { - $this->validator->validate($this->image, new Image([ - 'minHeight' => 3, - 'minHeightMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ height }}', '2') - ->setParameter('{{ min_height }}', '3') - ->setCode(Image::TOO_LOW_ERROR) - ->assertRaised(); - } - public function testHeightTooBig() { $this->validator->validate($this->image, new Image(maxHeight: 1, maxHeightMessage: 'myMessage')); @@ -210,23 +142,6 @@ public function testHeightTooBig() ->assertRaised(); } - /** - * @group legacy - */ - public function testHeightTooBigDoctrineStyle() - { - $this->validator->validate($this->image, new Image([ - 'maxHeight' => 1, - 'maxHeightMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ height }}', '2') - ->setParameter('{{ max_height }}', '1') - ->setCode(Image::TOO_HIGH_ERROR) - ->assertRaised(); - } - public function testPixelsTooFew() { $this->validator->validate($this->image, new Image(minPixels: 5, minPixelsMessage: 'myMessage')); @@ -240,25 +155,6 @@ public function testPixelsTooFew() ->assertRaised(); } - /** - * @group legacy - */ - public function testPixelsTooFewDoctrineStyle() - { - $this->validator->validate($this->image, new Image([ - 'minPixels' => 5, - 'minPixelsMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ pixels }}', '4') - ->setParameter('{{ min_pixels }}', '5') - ->setParameter('{{ height }}', '2') - ->setParameter('{{ width }}', '2') - ->setCode(Image::TOO_FEW_PIXEL_ERROR) - ->assertRaised(); - } - public function testPixelsTooMany() { $this->validator->validate($this->image, new Image(maxPixels: 3, maxPixelsMessage: 'myMessage')); @@ -272,25 +168,6 @@ public function testPixelsTooMany() ->assertRaised(); } - /** - * @group legacy - */ - public function testPixelsTooManyDoctrineStyle() - { - $this->validator->validate($this->image, new Image([ - 'maxPixels' => 3, - 'maxPixelsMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ pixels }}', '4') - ->setParameter('{{ max_pixels }}', '3') - ->setParameter('{{ height }}', '2') - ->setParameter('{{ width }}', '2') - ->setCode(Image::TOO_MANY_PIXEL_ERROR) - ->assertRaised(); - } - public function testRatioTooSmall() { $this->validator->validate($this->image, new Image(minRatio: 2, minRatioMessage: 'myMessage')); @@ -302,23 +179,6 @@ public function testRatioTooSmall() ->assertRaised(); } - /** - * @group legacy - */ - public function testRatioTooSmallDoctrineStyle() - { - $this->validator->validate($this->image, new Image([ - 'minRatio' => 2, - 'minRatioMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ ratio }}', 1) - ->setParameter('{{ min_ratio }}', 2) - ->setCode(Image::RATIO_TOO_SMALL_ERROR) - ->assertRaised(); - } - public function testRatioTooBig() { $this->validator->validate($this->image, new Image(maxRatio: 0.5, maxRatioMessage: 'myMessage')); @@ -330,23 +190,6 @@ public function testRatioTooBig() ->assertRaised(); } - /** - * @group legacy - */ - public function testRatioTooBigDoctrineStyle() - { - $this->validator->validate($this->image, new Image([ - 'maxRatio' => 0.5, - 'maxRatioMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ ratio }}', 1) - ->setParameter('{{ max_ratio }}', 0.5) - ->setCode(Image::RATIO_TOO_BIG_ERROR) - ->assertRaised(); - } - public function testMaxRatioUsesTwoDecimalsOnly() { $constraint = new Image(maxRatio: 1.33); @@ -385,23 +228,6 @@ public function testSquareNotAllowed() ->assertRaised(); } - /** - * @group legacy - */ - public function testSquareNotAllowedDoctrineStyle() - { - $this->validator->validate($this->image, new Image([ - 'allowSquare' => false, - 'allowSquareMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ width }}', 2) - ->setParameter('{{ height }}', 2) - ->setCode(Image::SQUARE_NOT_ALLOWED_ERROR) - ->assertRaised(); - } - public function testLandscapeNotAllowed() { $this->validator->validate($this->imageLandscape, new Image(allowLandscape: false, allowLandscapeMessage: 'myMessage')); @@ -413,23 +239,6 @@ public function testLandscapeNotAllowed() ->assertRaised(); } - /** - * @group legacy - */ - public function testLandscapeNotAllowedDoctrineStyle() - { - $this->validator->validate($this->imageLandscape, new Image([ - 'allowLandscape' => false, - 'allowLandscapeMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ width }}', 2) - ->setParameter('{{ height }}', 1) - ->setCode(Image::LANDSCAPE_NOT_ALLOWED_ERROR) - ->assertRaised(); - } - public function testPortraitNotAllowed() { $this->validator->validate($this->imagePortrait, new Image(allowPortrait: false, allowPortraitMessage: 'myMessage')); @@ -441,23 +250,6 @@ public function testPortraitNotAllowed() ->assertRaised(); } - /** - * @group legacy - */ - public function testPortraitNotAllowedDoctrineStyle() - { - $this->validator->validate($this->imagePortrait, new Image([ - 'allowPortrait' => false, - 'allowPortraitMessage' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ width }}', 1) - ->setParameter('{{ height }}', 2) - ->setCode(Image::PORTRAIT_NOT_ALLOWED_ERROR) - ->assertRaised(); - } - public function testCorrupted() { if (!\function_exists('imagecreatefromstring')) { @@ -477,31 +269,6 @@ public function testCorrupted() ->assertRaised(); } - /** - * @group legacy - */ - public function testCorruptedDoctrineStyle() - { - if (!\function_exists('imagecreatefromstring')) { - $this->markTestSkipped('This test require GD extension'); - } - - $constraint = new Image([ - 'detectCorrupted' => true, - 'corruptedMessage' => 'myMessage', - ]); - - $this->validator->validate($this->image, $constraint); - - $this->assertNoViolation(); - - $this->validator->validate($this->imageCorrupted, $constraint); - - $this->buildViolation('myMessage') - ->setCode(Image::CORRUPTED_IMAGE_ERROR) - ->assertRaised(); - } - public function testInvalidMimeType() { $this->validator->validate($this->notAnImage, $constraint = new Image()); @@ -533,27 +300,6 @@ public function testInvalidMimeTypeWithNarrowedSet() ->assertRaised(); } - /** - * @group legacy - */ - public function testInvalidMimeTypeWithNarrowedSetDoctrineStyle() - { - $this->validator->validate($this->image, new Image([ - 'mimeTypes' => [ - 'image/jpeg', - 'image/png', - ], - ])); - - $this->buildViolation('The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.') - ->setParameter('{{ file }}', \sprintf('"%s"', $this->image)) - ->setParameter('{{ type }}', '"image/gif"') - ->setParameter('{{ types }}', '"image/jpeg", "image/png"') - ->setParameter('{{ name }}', '"test.gif"') - ->setCode(Image::INVALID_MIME_TYPE_ERROR) - ->assertRaised(); - } - /** @dataProvider provideSvgWithViolation */ public function testSvgWithViolation(string $image, Image $constraint, string $violation, array $parameters = []) { diff --git a/Tests/Constraints/IpTest.php b/Tests/Constraints/IpTest.php index 2d740ae88..a1c70499e 100644 --- a/Tests/Constraints/IpTest.php +++ b/Tests/Constraints/IpTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Ip; -use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -29,26 +28,6 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $ip->normalizer); } - /** - * @group legacy - */ - public function testInvalidNormalizerThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("string" given).'); - new Ip(['normalizer' => 'Unknown Callable']); - } - - /** - * @group legacy - */ - public function testInvalidNormalizerObjectThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("stdClass" given).'); - new Ip(['normalizer' => new \stdClass()]); - } - public function testAttributes() { $metadata = new ClassMetadata(IpDummy::class); diff --git a/Tests/Constraints/IsFalseValidatorTest.php b/Tests/Constraints/IsFalseValidatorTest.php index c6e2ccef6..01e6f1ba9 100644 --- a/Tests/Constraints/IsFalseValidatorTest.php +++ b/Tests/Constraints/IsFalseValidatorTest.php @@ -45,21 +45,4 @@ public function testTrueIsInvalid() ->setCode(IsFalse::NOT_FALSE_ERROR) ->assertRaised(); } - - /** - * @group legacy - */ - public function testTrueIsInvalidDoctrineStyle() - { - $constraint = new IsFalse([ - 'message' => 'myMessage', - ]); - - $this->validator->validate(true, $constraint); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', 'true') - ->setCode(IsFalse::NOT_FALSE_ERROR) - ->assertRaised(); - } } diff --git a/Tests/Constraints/IsTrueValidatorTest.php b/Tests/Constraints/IsTrueValidatorTest.php index 4a9eb7702..81cab4051 100644 --- a/Tests/Constraints/IsTrueValidatorTest.php +++ b/Tests/Constraints/IsTrueValidatorTest.php @@ -45,19 +45,4 @@ public function testFalseIsInvalid() ->setCode(IsTrue::NOT_TRUE_ERROR) ->assertRaised(); } - - /** - * @group legacy - */ - public function testFalseIsInvalidDoctrineStyle() - { - $this->validator->validate(false, new IsTrue([ - 'message' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', 'false') - ->setCode(IsTrue::NOT_TRUE_ERROR) - ->assertRaised(); - } } diff --git a/Tests/Constraints/IsbnValidatorTest.php b/Tests/Constraints/IsbnValidatorTest.php index 3ae3864d5..3e9538f3b 100644 --- a/Tests/Constraints/IsbnValidatorTest.php +++ b/Tests/Constraints/IsbnValidatorTest.php @@ -157,26 +157,6 @@ public function testValidIsbn10($isbn) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getInvalidIsbn10 - */ - public function testInvalidIsbn10($isbn, $code) - { - $constraint = new Isbn([ - 'type' => 'isbn10', - 'isbn10Message' => 'myMessage', - ]); - - $this->validator->validate($isbn, $constraint); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', '"'.$isbn.'"') - ->setCode($code) - ->assertRaised(); - } - public function testInvalidIsbn10Named() { $this->validator->validate( @@ -202,26 +182,6 @@ public function testValidIsbn13($isbn) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getInvalidIsbn13 - */ - public function testInvalidIsbn13($isbn, $code) - { - $constraint = new Isbn([ - 'type' => 'isbn13', - 'isbn13Message' => 'myMessage', - ]); - - $this->validator->validate($isbn, $constraint); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', '"'.$isbn.'"') - ->setCode($code) - ->assertRaised(); - } - /** * @dataProvider getInvalidIsbn13 */ diff --git a/Tests/Constraints/LengthTest.php b/Tests/Constraints/LengthTest.php index 6e292cb35..ec753a969 100644 --- a/Tests/Constraints/LengthTest.php +++ b/Tests/Constraints/LengthTest.php @@ -33,26 +33,6 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $length->normalizer); } - /** - * @group legacy - */ - public function testInvalidNormalizerThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("string" given).'); - new Length(['min' => 0, 'max' => 10, 'normalizer' => 'Unknown Callable']); - } - - /** - * @group legacy - */ - public function testInvalidNormalizerObjectThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("stdClass" given).'); - new Length(['min' => 0, 'max' => 10, 'normalizer' => new \stdClass()]); - } - public function testDefaultCountUnitIsUsed() { $length = new Length(min: 0, max: 10); diff --git a/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php b/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php index 685bb58a6..ef7afa530 100644 --- a/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php +++ b/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php @@ -14,7 +14,6 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\LessThanOrEqualValidator; use Symfony\Component\Validator\Constraints\NegativeOrZero; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @author Jan Schädlich @@ -59,28 +58,6 @@ public static function provideInvalidComparisons(): array ]; } - /** - * @group legacy - */ - public function testThrowsConstraintExceptionIfPropertyPath() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('The "propertyPath" option of the "Symfony\Component\Validator\Constraints\NegativeOrZero" constraint cannot be set.'); - - return new NegativeOrZero(['propertyPath' => 'field']); - } - - /** - * @group legacy - */ - public function testThrowsConstraintExceptionIfValue() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('The "value" option of the "Symfony\Component\Validator\Constraints\NegativeOrZero" constraint cannot be set.'); - - return new NegativeOrZero(['value' => 0]); - } - /** * @dataProvider provideInvalidConstraintOptions */ diff --git a/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php b/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php index 5174a951d..1ac7b1516 100644 --- a/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php +++ b/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php @@ -14,7 +14,6 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\LessThanValidator; use Symfony\Component\Validator\Constraints\Negative; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @author Jan Schädlich @@ -58,28 +57,6 @@ public static function provideInvalidComparisons(): array ]; } - /** - * @group legacy - */ - public function testThrowsConstraintExceptionIfPropertyPath() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('The "propertyPath" option of the "Symfony\Component\Validator\Constraints\Negative" constraint cannot be set.'); - - return new Negative(['propertyPath' => 'field']); - } - - /** - * @group legacy - */ - public function testThrowsConstraintExceptionIfValue() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('The "value" option of the "Symfony\Component\Validator\Constraints\Negative" constraint cannot be set.'); - - return new Negative(['value' => 0]); - } - /** * @dataProvider provideInvalidConstraintOptions */ diff --git a/Tests/Constraints/NotBlankTest.php b/Tests/Constraints/NotBlankTest.php index d04a65f1c..80eeaaadd 100644 --- a/Tests/Constraints/NotBlankTest.php +++ b/Tests/Constraints/NotBlankTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\NotBlank; -use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -44,26 +43,6 @@ public function testAttributes() self::assertSame('trim', $bConstraint->normalizer); self::assertSame('myMessage', $bConstraint->message); } - - /** - * @group legacy - */ - public function testInvalidNormalizerThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("string" given).'); - new NotBlank(['normalizer' => 'Unknown Callable']); - } - - /** - * @group legacy - */ - public function testInvalidNormalizerObjectThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("stdClass" given).'); - new NotBlank(['normalizer' => new \stdClass()]); - } } class NotBlankDummy diff --git a/Tests/Constraints/NotCompromisedPasswordValidatorTest.php b/Tests/Constraints/NotCompromisedPasswordValidatorTest.php index 11c325d53..db9ced0e6 100644 --- a/Tests/Constraints/NotCompromisedPasswordValidatorTest.php +++ b/Tests/Constraints/NotCompromisedPasswordValidatorTest.php @@ -102,16 +102,6 @@ public function testThresholdNotReached() $this->assertNoViolation(); } - /** - * @group legacy - */ - public function testThresholdNotReachedDoctrineStyle() - { - $this->validator->validate(self::PASSWORD_LEAKED, new NotCompromisedPassword(['threshold' => 10])); - - $this->assertNoViolation(); - } - public function testValidPassword() { $this->validator->validate(self::PASSWORD_NOT_LEAKED, new NotCompromisedPassword()); @@ -216,16 +206,6 @@ public function testApiErrorSkipped() $this->validator->validate(self::PASSWORD_TRIGGERING_AN_ERROR, new NotCompromisedPassword(skipOnError: true)); } - /** - * @group legacy - */ - public function testApiErrorSkippedDoctrineStyle() - { - $this->expectNotToPerformAssertions(); - - $this->validator->validate(self::PASSWORD_TRIGGERING_AN_ERROR, new NotCompromisedPassword(['skipOnError' => true])); - } - private function createHttpClientStub(?string $returnValue = null): HttpClientInterface { $httpClientStub = $this->createMock(HttpClientInterface::class); diff --git a/Tests/Constraints/NotNullValidatorTest.php b/Tests/Constraints/NotNullValidatorTest.php index fec2ec12a..a999da6fb 100644 --- a/Tests/Constraints/NotNullValidatorTest.php +++ b/Tests/Constraints/NotNullValidatorTest.php @@ -51,19 +51,4 @@ public function testNullIsInvalid() ->setCode(NotNull::IS_NULL_ERROR) ->assertRaised(); } - - /** - * @group legacy - */ - public function testNullIsInvalidDoctrineStyle() - { - $this->validator->validate(null, new NotNull([ - 'message' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', 'null') - ->setCode(NotNull::IS_NULL_ERROR) - ->assertRaised(); - } } diff --git a/Tests/Constraints/RangeTest.php b/Tests/Constraints/RangeTest.php index 01481e8bc..fd102911d 100644 --- a/Tests/Constraints/RangeTest.php +++ b/Tests/Constraints/RangeTest.php @@ -18,19 +18,6 @@ class RangeTest extends TestCase { - /** - * @group legacy - */ - public function testThrowsConstraintExceptionIfBothMinLimitAndPropertyPath() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('requires only one of the "min" or "minPropertyPath" options to be set, not both.'); - new Range([ - 'min' => 'min', - 'minPropertyPath' => 'minPropertyPath', - ]); - } - public function testThrowsConstraintExceptionIfBothMinLimitAndPropertyPathNamed() { $this->expectException(ConstraintDefinitionException::class); @@ -38,19 +25,6 @@ public function testThrowsConstraintExceptionIfBothMinLimitAndPropertyPathNamed( new Range(min: 'min', minPropertyPath: 'minPropertyPath'); } - /** - * @group legacy - */ - public function testThrowsConstraintExceptionIfBothMaxLimitAndPropertyPath() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('requires only one of the "max" or "maxPropertyPath" options to be set, not both.'); - new Range([ - 'max' => 'max', - 'maxPropertyPath' => 'maxPropertyPath', - ]); - } - public function testThrowsConstraintExceptionIfBothMaxLimitAndPropertyPathNamed() { $this->expectException(ConstraintDefinitionException::class); @@ -91,47 +65,4 @@ public function testThrowsConstraintDefinitionExceptionIfBothMinAndMaxAndMaxMess $this->expectExceptionMessage('can not use "minMessage" and "maxMessage" when the "min" and "max" options are both set. Use "notInRangeMessage" instead.'); new Range(min: 'min', max: 'max', maxMessage: 'maxMessage'); } - - /** - * @group legacy - */ - public function testThrowsConstraintDefinitionExceptionIfBothMinAndMaxAndMinMessageAndMaxMessageOptions() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('can not use "minMessage" and "maxMessage" when the "min" and "max" options are both set. Use "notInRangeMessage" instead.'); - new Range([ - 'min' => 'min', - 'minMessage' => 'minMessage', - 'max' => 'max', - 'maxMessage' => 'maxMessage', - ]); - } - - /** - * @group legacy - */ - public function testThrowsConstraintDefinitionExceptionIfBothMinAndMaxAndMinMessageOptions() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('can not use "minMessage" and "maxMessage" when the "min" and "max" options are both set. Use "notInRangeMessage" instead.'); - new Range([ - 'min' => 'min', - 'minMessage' => 'minMessage', - 'max' => 'max', - ]); - } - - /** - * @group legacy - */ - public function testThrowsConstraintDefinitionExceptionIfBothMinAndMaxAndMaxMessageOptions() - { - $this->expectException(ConstraintDefinitionException::class); - $this->expectExceptionMessage('can not use "minMessage" and "maxMessage" when the "min" and "max" options are both set. Use "notInRangeMessage" instead.'); - new Range([ - 'min' => 'min', - 'max' => 'max', - 'maxMessage' => 'maxMessage', - ]); - } } diff --git a/Tests/Constraints/RangeValidatorTest.php b/Tests/Constraints/RangeValidatorTest.php index 423c8d460..772471e67 100644 --- a/Tests/Constraints/RangeValidatorTest.php +++ b/Tests/Constraints/RangeValidatorTest.php @@ -69,19 +69,6 @@ public static function getMoreThanTwenty(): array ]; } - /** - * @group legacy - * - * @dataProvider getTenToTwenty - */ - public function testValidValuesMin($value) - { - $constraint = new Range(['min' => 10]); - $this->validator->validate($value, $constraint); - - $this->assertNoViolation(); - } - /** * @dataProvider getTenToTwenty */ @@ -93,19 +80,6 @@ public function testValidValuesMinNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getTenToTwenty - */ - public function testValidValuesMax($value) - { - $constraint = new Range(['max' => 20]); - $this->validator->validate($value, $constraint); - - $this->assertNoViolation(); - } - /** * @dataProvider getTenToTwenty */ @@ -117,19 +91,6 @@ public function testValidValuesMaxNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getTenToTwenty - */ - public function testValidValuesMinMax($value) - { - $constraint = new Range(['min' => 10, 'max' => 20]); - $this->validator->validate($value, $constraint); - - $this->assertNoViolation(); - } - /** * @dataProvider getTenToTwenty */ @@ -141,27 +102,6 @@ public function testValidValuesMinMaxNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getLessThanTen - */ - public function testInvalidValuesMin($value, $formattedValue) - { - $constraint = new Range([ - 'min' => 10, - 'minMessage' => 'myMessage', - ]); - - $this->validator->validate($value, $constraint); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', $formattedValue) - ->setParameter('{{ limit }}', 10) - ->setCode(Range::TOO_LOW_ERROR) - ->assertRaised(); - } - /** * @dataProvider getLessThanTen */ @@ -178,27 +118,6 @@ public function testInvalidValuesMinNamed($value, $formattedValue) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getMoreThanTwenty - */ - public function testInvalidValuesMax($value, $formattedValue) - { - $constraint = new Range([ - 'max' => 20, - 'maxMessage' => 'myMessage', - ]); - - $this->validator->validate($value, $constraint); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', $formattedValue) - ->setParameter('{{ limit }}', 20) - ->setCode(Range::TOO_HIGH_ERROR) - ->assertRaised(); - } - /** * @dataProvider getMoreThanTwenty */ @@ -215,29 +134,6 @@ public function testInvalidValuesMaxNamed($value, $formattedValue) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getMoreThanTwenty - */ - public function testInvalidValuesCombinedMax($value, $formattedValue) - { - $constraint = new Range([ - 'min' => 10, - 'max' => 20, - 'notInRangeMessage' => 'myNotInRangeMessage', - ]); - - $this->validator->validate($value, $constraint); - - $this->buildViolation('myNotInRangeMessage') - ->setParameter('{{ value }}', $formattedValue) - ->setParameter('{{ min }}', 10) - ->setParameter('{{ max }}', 20) - ->setCode(Range::NOT_IN_RANGE_ERROR) - ->assertRaised(); - } - /** * @dataProvider getMoreThanTwenty */ @@ -255,29 +151,6 @@ public function testInvalidValuesCombinedMaxNamed($value, $formattedValue) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getLessThanTen - */ - public function testInvalidValuesCombinedMin($value, $formattedValue) - { - $constraint = new Range([ - 'min' => 10, - 'max' => 20, - 'notInRangeMessage' => 'myNotInRangeMessage', - ]); - - $this->validator->validate($value, $constraint); - - $this->buildViolation('myNotInRangeMessage') - ->setParameter('{{ value }}', $formattedValue) - ->setParameter('{{ min }}', 10) - ->setParameter('{{ max }}', 20) - ->setCode(Range::NOT_IN_RANGE_ERROR) - ->assertRaised(); - } - /** * @dataProvider getLessThanTen */ @@ -634,22 +507,6 @@ public function testNoViolationOnNullObjectWithPropertyPaths() $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getTenToTwenty - */ - public function testValidValuesMinPropertyPath($value) - { - $this->setObject(new Limit(10)); - - $this->validator->validate($value, new Range([ - 'minPropertyPath' => 'value', - ])); - - $this->assertNoViolation(); - } - /** * @dataProvider getTenToTwenty */ @@ -747,33 +604,6 @@ public function testInvalidValuesMaxPropertyPath($value, $formattedValue) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getMoreThanTwenty - */ - public function testInvalidValuesCombinedMaxPropertyPath($value, $formattedValue) - { - $this->setObject(new MinMax(10, 20)); - - $constraint = new Range([ - 'minPropertyPath' => 'min', - 'maxPropertyPath' => 'max', - 'notInRangeMessage' => 'myNotInRangeMessage', - ]); - - $this->validator->validate($value, $constraint); - - $this->buildViolation('myNotInRangeMessage') - ->setParameter('{{ value }}', $formattedValue) - ->setParameter('{{ min }}', 10) - ->setParameter('{{ max }}', 20) - ->setParameter('{{ max_limit_path }}', 'max') - ->setParameter('{{ min_limit_path }}', 'min') - ->setCode(Range::NOT_IN_RANGE_ERROR) - ->assertRaised(); - } - /** * @dataProvider getMoreThanTwenty */ @@ -799,33 +629,6 @@ public function testInvalidValuesCombinedMaxPropertyPathNamed($value, $formatted ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getLessThanTen - */ - public function testInvalidValuesCombinedMinPropertyPath($value, $formattedValue) - { - $this->setObject(new MinMax(10, 20)); - - $constraint = new Range([ - 'minPropertyPath' => 'min', - 'maxPropertyPath' => 'max', - 'notInRangeMessage' => 'myNotInRangeMessage', - ]); - - $this->validator->validate($value, $constraint); - - $this->buildViolation('myNotInRangeMessage') - ->setParameter('{{ value }}', $formattedValue) - ->setParameter('{{ min }}', 10) - ->setParameter('{{ max }}', 20) - ->setParameter('{{ max_limit_path }}', 'max') - ->setParameter('{{ min_limit_path }}', 'min') - ->setCode(Range::NOT_IN_RANGE_ERROR) - ->assertRaised(); - } - /** * @dataProvider getLessThanTen */ diff --git a/Tests/Constraints/RegexTest.php b/Tests/Constraints/RegexTest.php index 5d3919ab8..4ebadc48d 100644 --- a/Tests/Constraints/RegexTest.php +++ b/Tests/Constraints/RegexTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Regex; -use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\MissingOptionsException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -97,26 +96,6 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $regex->normalizer); } - /** - * @group legacy - */ - public function testInvalidNormalizerThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("string" given).'); - new Regex(['pattern' => '/^[0-9]+$/', 'normalizer' => 'Unknown Callable']); - } - - /** - * @group legacy - */ - public function testInvalidNormalizerObjectThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("stdClass" given).'); - new Regex(['pattern' => '/^[0-9]+$/', 'normalizer' => new \stdClass()]); - } - public function testAttributes() { $metadata = new ClassMetadata(RegexDummy::class); @@ -147,27 +126,6 @@ public function testMissingPattern() new Regex(null); } - - /** - * @group legacy - */ - public function testMissingPatternDoctrineStyle() - { - $this->expectException(MissingOptionsException::class); - $this->expectExceptionMessage(\sprintf('The options "pattern" must be set for constraint "%s".', Regex::class)); - - new Regex([]); - } - - /** - * @group legacy - */ - public function testPatternInOptionsArray() - { - $constraint = new Regex(null, options: ['pattern' => '/^[0-9]+$/']); - - $this->assertSame('/^[0-9]+$/', $constraint->pattern); - } } class RegexDummy diff --git a/Tests/Constraints/RegexValidatorTest.php b/Tests/Constraints/RegexValidatorTest.php index bafc752c3..fb8f84035 100644 --- a/Tests/Constraints/RegexValidatorTest.php +++ b/Tests/Constraints/RegexValidatorTest.php @@ -54,19 +54,6 @@ public function testValidValues($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getValidValuesWithWhitespaces - */ - public function testValidValuesWithWhitespaces($value) - { - $constraint = new Regex(['pattern' => '/^[0-9]+$/', 'normalizer' => 'trim']); - $this->validator->validate($value, $constraint); - - $this->assertNoViolation(); - } - /** * @dataProvider getValidValuesWithWhitespaces */ @@ -106,27 +93,6 @@ public static function getValidValuesWithWhitespaces() ]; } - /** - * @group legacy - * - * @dataProvider getInvalidValues - */ - public function testInvalidValues($value) - { - $constraint = new Regex([ - 'pattern' => '/^[0-9]+$/', - 'message' => 'myMessage', - ]); - - $this->validator->validate($value, $constraint); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', '"'.$value.'"') - ->setParameter('{{ pattern }}', '/^[0-9]+$/') - ->setCode(Regex::REGEX_FAILED_ERROR) - ->assertRaised(); - } - /** * @dataProvider getInvalidValues */ diff --git a/Tests/Constraints/TypeTest.php b/Tests/Constraints/TypeTest.php index a56cc514c..73acddd43 100644 --- a/Tests/Constraints/TypeTest.php +++ b/Tests/Constraints/TypeTest.php @@ -45,16 +45,6 @@ public function testMissingType() new Type(null); } - - /** - * @group legacy - */ - public function testTypeInOptionsArray() - { - $constraint = new Type(null, options: ['type' => 'digit']); - - $this->assertSame('digit', $constraint->type); - } } class TypeDummy diff --git a/Tests/Constraints/TypeValidatorTest.php b/Tests/Constraints/TypeValidatorTest.php index 8e9e1aa3b..eaa1a4675 100644 --- a/Tests/Constraints/TypeValidatorTest.php +++ b/Tests/Constraints/TypeValidatorTest.php @@ -221,23 +221,6 @@ public function testInvalidValuesMultipleTypes() ->assertRaised(); } - /** - * @group legacy - */ - public function testInvalidValuesMultipleTypesDoctrineStyle() - { - $this->validator->validate('12345', new Type([ - 'type' => ['boolean', 'array'], - 'message' => 'myMessage', - ])); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', '"12345"') - ->setParameter('{{ type }}', implode('|', ['boolean', 'array'])) - ->setCode(Type::INVALID_TYPE_ERROR) - ->assertRaised(); - } - protected static function createFile() { if (!self::$file) { diff --git a/Tests/Constraints/UniqueTest.php b/Tests/Constraints/UniqueTest.php index 9fe2599fd..acd53d49e 100644 --- a/Tests/Constraints/UniqueTest.php +++ b/Tests/Constraints/UniqueTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Unique; -use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -36,26 +35,6 @@ public function testAttributes() [$dConstraint] = $metadata->properties['d']->getConstraints(); self::assertSame('intval', $dConstraint->normalizer); } - - /** - * @group legacy - */ - public function testInvalidNormalizerThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("string" given).'); - new Unique(['normalizer' => 'Unknown Callable']); - } - - /** - * @group legacy - */ - public function testInvalidNormalizerObjectThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("stdClass" given).'); - new Unique(['normalizer' => new \stdClass()]); - } } class UniqueDummy diff --git a/Tests/Constraints/UrlTest.php b/Tests/Constraints/UrlTest.php index cbc9bc18c..b839f9409 100644 --- a/Tests/Constraints/UrlTest.php +++ b/Tests/Constraints/UrlTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Url; -use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -29,26 +28,6 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $url->normalizer); } - /** - * @group legacy - */ - public function testInvalidNormalizerThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("string" given).'); - new Url(['normalizer' => 'Unknown Callable', 'requireTld' => true]); - } - - /** - * @group legacy - */ - public function testInvalidNormalizerObjectThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("stdClass" given).'); - new Url(['normalizer' => new \stdClass(), 'requireTld' => true]); - } - public function testAttributes() { $metadata = new ClassMetadata(UrlDummy::class); @@ -79,16 +58,6 @@ public function testAttributes() self::assertNull($dConstraint->normalizer); self::assertTrue($dConstraint->requireTld); } - - /** - * @group legacy - */ - public function testRequireTldDefaultsToFalse() - { - $constraint = new Url(); - - $this->assertFalse($constraint->requireTld); - } } class UrlDummy diff --git a/Tests/Constraints/UuidTest.php b/Tests/Constraints/UuidTest.php index 22901a9db..d080dbd96 100644 --- a/Tests/Constraints/UuidTest.php +++ b/Tests/Constraints/UuidTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Uuid; -use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -29,26 +28,6 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $uuid->normalizer); } - /** - * @group legacy - */ - public function testInvalidNormalizerThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("string" given).'); - new Uuid(['normalizer' => 'Unknown Callable']); - } - - /** - * @group legacy - */ - public function testInvalidNormalizerObjectThrowsException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "normalizer" option must be a valid callable ("stdClass" given).'); - new Uuid(['normalizer' => new \stdClass()]); - } - public function testAttributes() { $metadata = new ClassMetadata(UuidDummy::class); diff --git a/Tests/Constraints/WhenTest.php b/Tests/Constraints/WhenTest.php index 21d606701..5ca98d079 100644 --- a/Tests/Constraints/WhenTest.php +++ b/Tests/Constraints/WhenTest.php @@ -26,17 +26,6 @@ final class WhenTest extends TestCase { - /** - * @group legacy - */ - public function testMissingOptionsExceptionIsThrown() - { - $this->expectException(MissingOptionsException::class); - $this->expectExceptionMessage('The options "expression", "constraints" must be set for constraint "Symfony\Component\Validator\Constraints\When".'); - - new When([]); - } - public function testMissingConstraints() { $this->expectException(MissingOptionsException::class); @@ -154,18 +143,4 @@ public function testAttributesWithClosure() self::assertSame([], $fooConstraint->otherwise); self::assertSame(['Default', 'WhenTestWithClosure'], $fooConstraint->groups); } - - /** - * @group legacy - */ - public function testConstraintsInOptionsArray() - { - $constraints = [ - new NotNull(), - new Length(min: 10), - ]; - $constraint = new When('true', options: ['constraints' => $constraints]); - - $this->assertSame($constraints, $constraint->constraints); - } } diff --git a/Tests/Fixtures/ConstraintC.php b/Tests/Fixtures/ConstraintC.php deleted file mode 100644 index 8143420ac..000000000 --- a/Tests/Fixtures/ConstraintC.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Fixtures; - -use Symfony\Component\Validator\Constraint; - -class ConstraintC extends Constraint -{ - public $option1; - - public function getRequiredOptions(): array - { - return ['option1']; - } - - public function getTargets(): string|array - { - return [self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT]; - } -} diff --git a/Tests/Fixtures/ConstraintChoiceWithPreset.php b/Tests/Fixtures/ConstraintChoiceWithPreset.php deleted file mode 100644 index e4154e8c8..000000000 --- a/Tests/Fixtures/ConstraintChoiceWithPreset.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Fixtures; - -use Symfony\Component\Validator\Constraints\Choice; - -class ConstraintChoiceWithPreset extends Choice -{ - public $type; - - public function __construct(string $type) - { - parent::__construct($type); - - if ('A' === $this->type) { - $this->choices = ['A', 'B', 'C']; - } else { - $this->choices = ['D', 'E', 'F']; - } - } - - public function getDefaultOption(): ?string - { - return 'type'; - } -} diff --git a/Tests/Fixtures/ConstraintWithRequiredArgument.php b/Tests/Fixtures/ConstraintWithRequiredArgument.php index 93123677a..6d8213567 100644 --- a/Tests/Fixtures/ConstraintWithRequiredArgument.php +++ b/Tests/Fixtures/ConstraintWithRequiredArgument.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Tests\Fixtures; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; #[\Attribute] @@ -19,7 +18,6 @@ final class ConstraintWithRequiredArgument extends Constraint { public string $requiredArg; - #[HasNamedArguments] public function __construct(string $requiredArg, ?array $groups = null, mixed $payload = null) { parent::__construct(null, $groups, $payload); diff --git a/Tests/Fixtures/ConstraintWithStaticProperty.php b/Tests/Fixtures/ConstraintWithStaticProperty.php deleted file mode 100644 index f8b216940..000000000 --- a/Tests/Fixtures/ConstraintWithStaticProperty.php +++ /dev/null @@ -1,10 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Fixtures; - -use Symfony\Component\Validator\Constraint; - -class ConstraintWithValue extends Constraint -{ - public $property; - public $value; - - public function getDefaultOption(): ?string - { - return 'property'; - } - - public function getTargets(): string|array - { - return [self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT]; - } -} diff --git a/Tests/Fixtures/ConstraintWithValueAsDefault.php b/Tests/Fixtures/ConstraintWithValueAsDefault.php deleted file mode 100644 index 8a4944c46..000000000 --- a/Tests/Fixtures/ConstraintWithValueAsDefault.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Fixtures; - -use Symfony\Component\Validator\Constraint; - -class ConstraintWithValueAsDefault extends Constraint -{ - public $property; - public $value; - - public function getDefaultOption(): ?string - { - return 'value'; - } - - public function getTargets(): string|array - { - return [self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT]; - } -} diff --git a/Tests/Fixtures/DummyEntityConstraintWithoutNamedArguments.php b/Tests/Fixtures/DummyEntityConstraintWithoutNamedArguments.php deleted file mode 100644 index 880f73cae..000000000 --- a/Tests/Fixtures/DummyEntityConstraintWithoutNamedArguments.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Fixtures; - -class DummyEntityConstraintWithoutNamedArguments -{ -} diff --git a/Tests/Fixtures/LegacyConstraintA.php b/Tests/Fixtures/LegacyConstraintA.php deleted file mode 100644 index b115608de..000000000 --- a/Tests/Fixtures/LegacyConstraintA.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Fixtures; - -use Symfony\Component\Validator\Constraint; - -#[\Attribute] -class LegacyConstraintA extends Constraint -{ - public $property1; - public $property2; - - public function getDefaultOption(): ?string - { - return 'property2'; - } - - public function getTargets(): string|array - { - return [self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT]; - } -} diff --git a/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php b/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php index 8dfc6dd1b..167d7bee1 100644 --- a/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php +++ b/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php @@ -11,14 +11,12 @@ namespace Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; class ConstraintWithNamedArguments extends Constraint { public $choices; - #[HasNamedArguments] public function __construct(array|string|null $choices = [], ?array $groups = null) { parent::__construct(null, $groups); diff --git a/Tests/Mapping/Loader/Fixtures/ConstraintWithoutNamedArguments.php b/Tests/Mapping/Loader/Fixtures/ConstraintWithoutNamedArguments.php deleted file mode 100644 index 035a1a837..000000000 --- a/Tests/Mapping/Loader/Fixtures/ConstraintWithoutNamedArguments.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures; - -use Symfony\Component\Validator\Constraint; - -class ConstraintWithoutNamedArguments extends Constraint -{ - public function getTargets(): string - { - return self::CLASS_CONSTRAINT; - } -} diff --git a/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php b/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php index 48b67362c..58a408c0c 100644 --- a/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php +++ b/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php @@ -11,12 +11,10 @@ namespace Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures; -use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; class ConstraintWithoutValueWithNamedArguments extends Constraint { - #[HasNamedArguments] public function __construct(?array $groups = null) { parent::__construct(null, $groups); diff --git a/Tests/Mapping/Loader/XmlFileLoaderTest.php b/Tests/Mapping/Loader/XmlFileLoaderTest.php index 3b0872df2..83cf79902 100644 --- a/Tests/Mapping/Loader/XmlFileLoaderTest.php +++ b/Tests/Mapping/Loader/XmlFileLoaderTest.php @@ -22,7 +22,6 @@ use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Regex; use Symfony\Component\Validator\Constraints\Traverse; -use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; @@ -31,7 +30,6 @@ use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithRequiredArgument; -use Symfony\Component\Validator\Tests\Fixtures\DummyEntityConstraintWithoutNamedArguments; use Symfony\Component\Validator\Tests\Fixtures\Entity_81; use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity; use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\GroupSequenceProviderEntity; @@ -94,23 +92,6 @@ public function testLoadClassMetadata() $this->assertEquals($expected, $metadata); } - /** - * @group legacy - */ - public function testLoadClassMetadataValueOption() - { - $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-value-option.xml'); - $metadata = new ClassMetadata(Entity::class); - - $loader->loadClassMetadata($metadata); - - $expected = new ClassMetadata(Entity::class); - $expected->addPropertyConstraint('firstName', new Type(type: 'string')); - $expected->addPropertyConstraint('firstName', new Choice(choices: ['A', 'B'])); - - $this->assertEquals($expected, $metadata); - } - public function testLoadClassMetadataWithNonStrings() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-non-strings.xml'); @@ -191,17 +172,4 @@ public function testDoNotModifyStateIfExceptionIsThrown() $loader->loadClassMetadata($metadata); } } - - /** - * @group legacy - */ - public function testLoadConstraintWithoutNamedArgumentsSupport() - { - $loader = new XmlFileLoader(__DIR__.'/constraint-without-named-arguments-support.xml'); - $metadata = new ClassMetadata(DummyEntityConstraintWithoutNamedArguments::class); - - $this->expectUserDeprecationMessage('Since symfony/validator 7.3: Using constraints not supporting named arguments is deprecated. Try adding the HasNamedArguments attribute to Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithoutNamedArguments.'); - - $loader->loadClassMetadata($metadata); - } } diff --git a/Tests/Mapping/Loader/YamlFileLoaderTest.php b/Tests/Mapping/Loader/YamlFileLoaderTest.php index 9cf77fc38..e02272953 100644 --- a/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -20,7 +20,6 @@ use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Range; -use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; use Symfony\Component\Validator\Tests\Dummy\DummyGroupProvider; @@ -28,7 +27,6 @@ use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithRequiredArgument; -use Symfony\Component\Validator\Tests\Fixtures\DummyEntityConstraintWithoutNamedArguments; use Symfony\Component\Validator\Tests\Fixtures\Entity_81; use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity; use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\GroupSequenceProviderEntity; @@ -138,23 +136,6 @@ public function testLoadClassMetadata() $this->assertEquals($expected, $metadata); } - /** - * @group legacy - */ - public function testLoadClassMetadataValueOption() - { - $loader = new YamlFileLoader(__DIR__.'/constraint-mapping-value-option.yml'); - $metadata = new ClassMetadata(Entity::class); - - $loader->loadClassMetadata($metadata); - - $expected = new ClassMetadata(Entity::class); - $expected->addPropertyConstraint('firstName', new Type(type: 'string')); - $expected->addPropertyConstraint('firstName', new Choice(choices: ['A', 'B'])); - - $this->assertEquals($expected, $metadata); - } - public function testLoadClassMetadataWithConstants() { $loader = new YamlFileLoader(__DIR__.'/mapping-with-constants.yml'); @@ -207,17 +188,4 @@ public function testLoadGroupProvider() $this->assertEquals($expected, $metadata); } - - /** - * @group legacy - */ - public function testLoadConstraintWithoutNamedArgumentsSupport() - { - $loader = new YamlFileLoader(__DIR__.'/constraint-without-named-arguments-support.yml'); - $metadata = new ClassMetadata(DummyEntityConstraintWithoutNamedArguments::class); - - $this->expectUserDeprecationMessage('Since symfony/validator 7.3: Using constraints not supporting named arguments is deprecated. Try adding the HasNamedArguments attribute to Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithoutNamedArguments.'); - - $loader->loadClassMetadata($metadata); - } } diff --git a/Tests/Mapping/Loader/constraint-mapping-value-option.xml b/Tests/Mapping/Loader/constraint-mapping-value-option.xml deleted file mode 100644 index d0fea931d..000000000 --- a/Tests/Mapping/Loader/constraint-mapping-value-option.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - Symfony\Component\Validator\Tests\Fixtures\ - - - - - - - - - string - - - - A - B - - - - - - diff --git a/Tests/Mapping/Loader/constraint-mapping-value-option.yml b/Tests/Mapping/Loader/constraint-mapping-value-option.yml deleted file mode 100644 index 149497ad1..000000000 --- a/Tests/Mapping/Loader/constraint-mapping-value-option.yml +++ /dev/null @@ -1,10 +0,0 @@ -namespaces: - custom: Symfony\Component\Validator\Tests\Fixtures\ - -Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: - properties: - firstName: - # Constraint with single value - - Type: string - # Constraint with multiple values - - Choice: [A, B] diff --git a/Tests/Mapping/Loader/constraint-without-named-arguments-support.xml b/Tests/Mapping/Loader/constraint-without-named-arguments-support.xml deleted file mode 100644 index 48321b174..000000000 --- a/Tests/Mapping/Loader/constraint-without-named-arguments-support.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/Tests/Mapping/Loader/constraint-without-named-arguments-support.yml b/Tests/Mapping/Loader/constraint-without-named-arguments-support.yml deleted file mode 100644 index 3e25b78e4..000000000 --- a/Tests/Mapping/Loader/constraint-without-named-arguments-support.yml +++ /dev/null @@ -1,4 +0,0 @@ -Symfony\Component\Validator\Tests\Fixtures\DummyEntityConstraintWithoutNamedArguments: - constraints: - - Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithoutNamedArguments: - groups: foo From ff1202cd9594cf8b20bbf6bcb328b435dd4f5d40 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 9 Oct 2024 11:06:51 +0200 Subject: [PATCH 19/57] run tests using PHPUnit 11.5 --- Tests/ConstraintTest.php | 122 +++++++----------- Tests/Constraints/CardSchemeTest.php | 7 +- Tests/Constraints/CascadeTest.php | 7 +- Tests/Constraints/ChoiceTest.php | 7 +- Tests/Constraints/ChoiceValidatorTest.php | 49 +++---- Tests/Constraints/CollectionTest.php | 12 +- Tests/Constraints/CompoundTest.php | 17 ++- Tests/Constraints/CountValidatorTestCase.php | 51 +++----- Tests/Constraints/DisableAutoMappingTest.php | 7 +- Tests/Constraints/EmailTest.php | 12 +- Tests/Constraints/EnableAutoMappingTest.php | 7 +- Tests/Constraints/ExpressionSyntaxTest.php | 7 +- Tests/Constraints/ExpressionTest.php | 17 ++- Tests/Constraints/FileValidatorTestCase.php | 12 +- ...idatorWithPositiveOrZeroConstraintTest.php | 12 +- ...hanValidatorWithPositiveConstraintTest.php | 12 +- Tests/Constraints/ImageValidatorTest.php | 71 +++++----- Tests/Constraints/IpTest.php | 12 +- Tests/Constraints/IsFalseValidatorTest.php | 7 +- Tests/Constraints/IsTrueValidatorTest.php | 7 +- Tests/Constraints/IsbnValidatorTest.php | 19 ++- Tests/Constraints/LengthTest.php | 12 +- ...idatorWithNegativeOrZeroConstraintTest.php | 12 +- ...hanValidatorWithNegativeConstraintTest.php | 12 +- Tests/Constraints/NotBlankTest.php | 12 +- .../NotCompromisedPasswordValidatorTest.php | 12 +- Tests/Constraints/NotNullValidatorTest.php | 7 +- Tests/Constraints/RangeTest.php | 27 ++-- Tests/Constraints/RangeValidatorTest.php | 83 +++++------- Tests/Constraints/RegexTest.php | 22 ++-- Tests/Constraints/RegexValidatorTest.php | 19 ++- Tests/Constraints/TypeTest.php | 7 +- Tests/Constraints/TypeValidatorTest.php | 7 +- Tests/Constraints/UniqueTest.php | 12 +- Tests/Constraints/UrlTest.php | 17 ++- Tests/Constraints/UuidTest.php | 12 +- Tests/Constraints/WhenTest.php | 12 +- Tests/Mapping/Loader/XmlFileLoaderTest.php | 15 +-- Tests/Mapping/Loader/YamlFileLoaderTest.php | 15 +-- phpunit.xml.dist | 11 +- 40 files changed, 367 insertions(+), 433 deletions(-) diff --git a/Tests/ConstraintTest.php b/Tests/ConstraintTest.php index 441850977..a9398efd9 100644 --- a/Tests/ConstraintTest.php +++ b/Tests/ConstraintTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -29,9 +31,8 @@ class ConstraintTest extends TestCase { - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSetProperties() { $constraint = new LegacyConstraintA([ @@ -43,9 +44,8 @@ public function testSetProperties() $this->assertEquals('bar', $constraint->property2); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSetNotExistingPropertyThrowsException() { $this->expectException(InvalidOptionsException::class); @@ -55,9 +55,8 @@ public function testSetNotExistingPropertyThrowsException() ]); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testMagicPropertiesAreNotAllowed() { $constraint = new LegacyConstraintA(); @@ -67,9 +66,8 @@ public function testMagicPropertiesAreNotAllowed() $constraint->foo = 'bar'; } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidAndRequiredOptionsPassed() { $this->expectException(InvalidOptionsException::class); @@ -80,9 +78,8 @@ public function testInvalidAndRequiredOptionsPassed() ]); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSetDefaultProperty() { $constraint = new LegacyConstraintA('foo'); @@ -90,9 +87,8 @@ public function testSetDefaultProperty() $this->assertEquals('foo', $constraint->property2); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSetDefaultPropertyDoctrineStyle() { $constraint = new LegacyConstraintA(['value' => 'foo']); @@ -100,9 +96,8 @@ public function testSetDefaultPropertyDoctrineStyle() $this->assertEquals('foo', $constraint->property2); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSetDefaultPropertyDoctrineStylePlusOtherProperty() { $constraint = new LegacyConstraintA(['value' => 'foo', 'property1' => 'bar']); @@ -111,9 +106,8 @@ public function testSetDefaultPropertyDoctrineStylePlusOtherProperty() $this->assertEquals('bar', $constraint->property1); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSetDefaultPropertyDoctrineStyleWhenDefaultPropertyIsNamedValue() { $constraint = new ConstraintWithValueAsDefault(['value' => 'foo']); @@ -122,9 +116,8 @@ public function testSetDefaultPropertyDoctrineStyleWhenDefaultPropertyIsNamedVal $this->assertNull($constraint->property); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testDontSetDefaultPropertyIfValuePropertyExists() { $constraint = new ConstraintWithValue(['value' => 'foo']); @@ -133,9 +126,8 @@ public function testDontSetDefaultPropertyIfValuePropertyExists() $this->assertNull($constraint->property); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSetUndefinedDefaultProperty() { $this->expectException(ConstraintDefinitionException::class); @@ -143,9 +135,8 @@ public function testSetUndefinedDefaultProperty() new ConstraintB('foo'); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testRequiredOptionsMustBeDefined() { $this->expectException(MissingOptionsException::class); @@ -153,9 +144,8 @@ public function testRequiredOptionsMustBeDefined() new ConstraintC(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testRequiredOptionsPassed() { $constraint = new ConstraintC(['option1' => 'default']); @@ -163,9 +153,8 @@ public function testRequiredOptionsPassed() $this->assertSame('default', $constraint->option1); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testGroupsAreConvertedToArray() { $constraint = new LegacyConstraintA(['groups' => 'Foo']); @@ -180,18 +169,16 @@ public function testAddDefaultGroupAddsGroup() $this->assertEquals(['Default', 'Foo'], $constraint->groups); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testAllowsSettingZeroRequiredPropertyValue() { $constraint = new LegacyConstraintA(0); $this->assertEquals(0, $constraint->property2); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testCanCreateConstraintWithNoDefaultOptionAndEmptyArray() { $constraint = new ConstraintB([]); @@ -222,9 +209,8 @@ public function testSerialize() $this->assertEquals($constraint, $restoredConstraint); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSerializeDoctrineStyle() { $constraint = new LegacyConstraintA([ @@ -248,9 +234,8 @@ public function testSerializeInitializesGroupsOptionToDefault() $this->assertEquals($expected, $constraint); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSerializeInitializesGroupsOptionToDefaultDoctrineStyle() { $constraint = new LegacyConstraintA([ @@ -278,9 +263,8 @@ public function testSerializeKeepsCustomGroups() $this->assertSame(['MyGroup'], $constraint->groups); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSerializeKeepsCustomGroupsDoctrineStyle() { $constraint = new LegacyConstraintA([ @@ -300,9 +284,8 @@ public function testGetErrorNameForUnknownCode() Constraint::getErrorName(1); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testOptionsAsDefaultOption() { $constraint = new LegacyConstraintA($options = ['value1']); @@ -314,9 +297,8 @@ public function testOptionsAsDefaultOption() $this->assertEquals($options, $constraint->property2); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidOptions() { $this->expectException(InvalidOptionsException::class); @@ -324,9 +306,8 @@ public function testInvalidOptions() new LegacyConstraintA(['property2' => 'foo', 'bar', 5 => 'baz']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testOptionsWithInvalidInternalPointer() { $options = ['property1' => 'foo']; @@ -338,9 +319,8 @@ public function testOptionsWithInvalidInternalPointer() $this->assertEquals('foo', $constraint->property1); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testAttributeSetUndefinedDefaultOption() { $this->expectException(ConstraintDefinitionException::class); @@ -348,9 +328,8 @@ public function testAttributeSetUndefinedDefaultOption() new ConstraintB(['value' => 1]); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testStaticPropertiesAreNoOptions() { $this->expectException(InvalidOptionsException::class); @@ -360,9 +339,8 @@ public function testStaticPropertiesAreNoOptions() ]); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSetTypedProperty() { $constraint = new ConstraintWithTypedProperty([ diff --git a/Tests/Constraints/CardSchemeTest.php b/Tests/Constraints/CardSchemeTest.php index 154d35a25..cdd78a7d4 100644 --- a/Tests/Constraints/CardSchemeTest.php +++ b/Tests/Constraints/CardSchemeTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\CardScheme; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -47,9 +49,8 @@ public function testMissingSchemes() new CardScheme(null); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSchemesInOptionsArray() { $constraint = new CardScheme(null, options: ['schemes' => [CardScheme::MASTERCARD]]); diff --git a/Tests/Constraints/CascadeTest.php b/Tests/Constraints/CascadeTest.php index fc4d7ce0f..e33add926 100644 --- a/Tests/Constraints/CascadeTest.php +++ b/Tests/Constraints/CascadeTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Cascade; use Symfony\Component\Validator\Mapping\CascadingStrategy; @@ -35,9 +37,8 @@ public function testExcludeProperties() self::assertSame(['foo' => 0, 'bar' => 1], $constraint->exclude); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testExcludePropertiesDoctrineStyle() { $constraint = new Cascade(['exclude' => ['foo', 'bar']]); diff --git a/Tests/Constraints/ChoiceTest.php b/Tests/Constraints/ChoiceTest.php index ddfb31b11..a74991575 100644 --- a/Tests/Constraints/ChoiceTest.php +++ b/Tests/Constraints/ChoiceTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -19,9 +21,8 @@ class ChoiceTest extends TestCase { - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSetDefaultPropertyChoice() { $constraint = new ConstraintChoiceWithPreset('A'); diff --git a/Tests/Constraints/ChoiceValidatorTest.php b/Tests/Constraints/ChoiceValidatorTest.php index acfbb8419..4629432fc 100644 --- a/Tests/Constraints/ChoiceValidatorTest.php +++ b/Tests/Constraints/ChoiceValidatorTest.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Constraints\ChoiceValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -81,9 +84,8 @@ public function testValidChoiceArray() $this->assertNoViolation(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testValidChoiceArrayFirstArgument() { $this->validator->validate('bar', new Choice(['foo', 'bar'])); @@ -91,11 +93,9 @@ public function testValidChoiceArrayFirstArgument() $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider provideLegacyConstraintsWithChoicesArrayDoctrineStyle - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('provideLegacyConstraintsWithChoicesArrayDoctrineStyle')] public function testValidChoiceArrayDoctrineStyle(Choice $constraint) { $this->validator->validate('bar', $constraint); @@ -126,11 +126,9 @@ public static function provideConstraintsWithCallbackFunction(): iterable yield 'named arguments, static method' => [new Choice(callback: [__CLASS__, 'staticCallback'])]; } - /** - * @group legacy - * - * @dataProvider provideLegacyConstraintsWithCallbackFunctionDoctrineStyle - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('provideLegacyConstraintsWithCallbackFunctionDoctrineStyle')] public function testValidChoiceCallbackFunctionDoctrineStyle(Choice $constraint) { $this->validator->validate('bar', $constraint); @@ -194,9 +192,8 @@ public function testMultipleChoices() $this->assertNoViolation(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testMultipleChoicesDoctrineStyle() { $this->validator->validate(['baz', 'bar'], new Choice([ @@ -218,9 +215,8 @@ public function testInvalidChoice() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidChoiceDoctrineStyle() { $this->validator->validate('baz', new Choice(['choices' => ['foo', 'bar'], 'message' => 'myMessage'])); @@ -266,9 +262,8 @@ public function testInvalidChoiceMultiple() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidChoiceMultipleDoctrineStyle() { $this->validator->validate(['foo', 'baz'], new Choice([ @@ -306,9 +301,8 @@ public function testTooFewChoices() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testTooFewChoicesDoctrineStyle() { $value = ['foo']; @@ -351,9 +345,8 @@ public function testTooManyChoices() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testTooManyChoicesDoctrineStyle() { $value = ['foo', 'bar', 'moo']; diff --git a/Tests/Constraints/CollectionTest.php b/Tests/Constraints/CollectionTest.php index c1c32f90a..dc962b3e9 100644 --- a/Tests/Constraints/CollectionTest.php +++ b/Tests/Constraints/CollectionTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Email; @@ -26,9 +28,8 @@ */ class CollectionTest extends TestCase { - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testRejectNonConstraints() { $this->expectException(InvalidOptionsException::class); @@ -103,9 +104,8 @@ public function testConstraintHasDefaultGroupWithOptionalValues() $this->assertEquals(['Default'], $constraint->fields['bar']->groups); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testOnlySomeKeysAreKnowOptions() { $constraint = new Collection([ diff --git a/Tests/Constraints/CompoundTest.php b/Tests/Constraints/CompoundTest.php index c3c55eb3e..7c08d84b0 100644 --- a/Tests/Constraints/CompoundTest.php +++ b/Tests/Constraints/CompoundTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Compound; use Symfony\Component\Validator\Constraints\Length; @@ -19,9 +21,8 @@ class CompoundTest extends TestCase { - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testItCannotRedefineConstraintsOption() { $this->expectException(ConstraintDefinitionException::class); @@ -38,9 +39,8 @@ public function testGroupsAndPayload() $this->assertSame($payload, $compound->payload); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testGroupsAndPayloadInOptionsArray() { $payload = new \stdClass(); @@ -50,9 +50,8 @@ public function testGroupsAndPayloadInOptionsArray() $this->assertSame($payload, $compound->payload); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testCanDependOnNormalizedOptions() { $constraint = new ForwardingOptionCompound($min = 3); diff --git a/Tests/Constraints/CountValidatorTestCase.php b/Tests/Constraints/CountValidatorTestCase.php index da319cd8b..08b171dc9 100644 --- a/Tests/Constraints/CountValidatorTestCase.php +++ b/Tests/Constraints/CountValidatorTestCase.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\Count; use Symfony\Component\Validator\Constraints\CountValidator; use Symfony\Component\Validator\Constraints\DivisibleBy; @@ -69,11 +72,9 @@ public static function getFiveOrMoreElements() ]; } - /** - * @group legacy - * - * @dataProvider getThreeOrLessElements - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getThreeOrLessElements')] public function testValidValuesMax($value) { $constraint = new Count(['max' => 3]); @@ -93,11 +94,9 @@ public function testValidValuesMaxNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getFiveOrMoreElements - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getFiveOrMoreElements')] public function testValidValuesMin($value) { $constraint = new Count(['min' => 5]); @@ -117,11 +116,9 @@ public function testValidValuesMinNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getFourElements - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getFourElements')] public function testValidValuesExact($value) { $constraint = new Count(4); @@ -141,11 +138,9 @@ public function testValidValuesExactNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getFiveOrMoreElements - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getFiveOrMoreElements')] public function testTooManyValues($value) { $constraint = new Count([ @@ -182,11 +177,9 @@ public function testTooManyValuesNamed($value) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getThreeOrLessElements - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getThreeOrLessElements')] public function testTooFewValues($value) { $constraint = new Count([ @@ -223,11 +216,9 @@ public function testTooFewValuesNamed($value) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getFiveOrMoreElements - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getFiveOrMoreElements')] public function testTooManyValuesExact($value) { $constraint = new Count([ diff --git a/Tests/Constraints/DisableAutoMappingTest.php b/Tests/Constraints/DisableAutoMappingTest.php index e7b6a8db7..e8dbed4eb 100644 --- a/Tests/Constraints/DisableAutoMappingTest.php +++ b/Tests/Constraints/DisableAutoMappingTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\DisableAutoMapping; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -23,9 +25,8 @@ */ class DisableAutoMappingTest extends TestCase { - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testGroups() { $this->expectException(ConstraintDefinitionException::class); diff --git a/Tests/Constraints/EmailTest.php b/Tests/Constraints/EmailTest.php index 9436b4bd6..2a6302eb4 100644 --- a/Tests/Constraints/EmailTest.php +++ b/Tests/Constraints/EmailTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -54,9 +56,8 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $email->normalizer); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerThrowsException() { $this->expectException(InvalidArgumentException::class); @@ -64,9 +65,8 @@ public function testInvalidNormalizerThrowsException() new Email(['normalizer' => 'Unknown Callable']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerObjectThrowsException() { $this->expectException(InvalidArgumentException::class); diff --git a/Tests/Constraints/EnableAutoMappingTest.php b/Tests/Constraints/EnableAutoMappingTest.php index 525a62ed5..a1c44c37d 100644 --- a/Tests/Constraints/EnableAutoMappingTest.php +++ b/Tests/Constraints/EnableAutoMappingTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\EnableAutoMapping; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -23,9 +25,8 @@ */ class EnableAutoMappingTest extends TestCase { - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testGroups() { $this->expectException(ConstraintDefinitionException::class); diff --git a/Tests/Constraints/ExpressionSyntaxTest.php b/Tests/Constraints/ExpressionSyntaxTest.php index 8731a5d85..99875b9fd 100644 --- a/Tests/Constraints/ExpressionSyntaxTest.php +++ b/Tests/Constraints/ExpressionSyntaxTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\ExpressionSyntax; use Symfony\Component\Validator\Constraints\ExpressionSyntaxValidator; @@ -44,9 +46,8 @@ public static function provideServiceValidatedConstraints(): iterable yield 'attribute' => [$metadata->properties['b']->constraints[0]]; } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testValidatedByServiceDoctrineStyle() { $constraint = new ExpressionSyntax(['service' => 'my_service']); diff --git a/Tests/Constraints/ExpressionTest.php b/Tests/Constraints/ExpressionTest.php index 22e5c624e..61d11fb8a 100644 --- a/Tests/Constraints/ExpressionTest.php +++ b/Tests/Constraints/ExpressionTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Expression; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -51,9 +53,8 @@ public function testMissingPattern() new Expression(null); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testMissingPatternDoctrineStyle() { $this->expectException(MissingOptionsException::class); @@ -62,9 +63,8 @@ public function testMissingPatternDoctrineStyle() new Expression([]); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInitializeWithOptionsArray() { $constraint = new Expression([ @@ -74,9 +74,8 @@ public function testInitializeWithOptionsArray() $this->assertSame('!this.getParent().get("field2").getData()', $constraint->expression); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testExpressionInOptionsArray() { $constraint = new Expression(null, options: ['expression' => '!this.getParent().get("field2").getData()']); diff --git a/Tests/Constraints/FileValidatorTestCase.php b/Tests/Constraints/FileValidatorTestCase.php index b1ebf530e..53f7ad0b5 100644 --- a/Tests/Constraints/FileValidatorTestCase.php +++ b/Tests/Constraints/FileValidatorTestCase.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\Validator\Constraints\File; use Symfony\Component\Validator\Constraints\FileValidator; @@ -375,9 +377,8 @@ public function testInvalidMimeType() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidMimeTypeDoctrineStyle() { $file = $this @@ -451,9 +452,8 @@ public function testDisallowEmpty() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testDisallowEmptyDoctrineStyle() { ftruncate($this->file, 0); diff --git a/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php b/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php index 47f190851..4ce00abc2 100644 --- a/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php +++ b/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\GreaterThanOrEqualValidator; use Symfony\Component\Validator\Constraints\PositiveOrZero; @@ -61,9 +63,8 @@ public static function provideInvalidComparisons(): array ]; } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintExceptionIfPropertyPath() { $this->expectException(ConstraintDefinitionException::class); @@ -72,9 +73,8 @@ public function testThrowsConstraintExceptionIfPropertyPath() return new PositiveOrZero(['propertyPath' => 'field']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintExceptionIfValue() { $this->expectException(ConstraintDefinitionException::class); diff --git a/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php b/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php index 6b58bff85..795a7ffdf 100644 --- a/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php +++ b/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\GreaterThanValidator; use Symfony\Component\Validator\Constraints\Positive; @@ -58,9 +60,8 @@ public static function provideInvalidComparisons(): array ]; } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintExceptionIfPropertyPath() { $this->expectException(ConstraintDefinitionException::class); @@ -69,9 +70,8 @@ public function testThrowsConstraintExceptionIfPropertyPath() return new Positive(['propertyPath' => 'field']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintExceptionIfValue() { $this->expectException(ConstraintDefinitionException::class); diff --git a/Tests/Constraints/ImageValidatorTest.php b/Tests/Constraints/ImageValidatorTest.php index 7a7aa9197..8c556b48f 100644 --- a/Tests/Constraints/ImageValidatorTest.php +++ b/Tests/Constraints/ImageValidatorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\Mime\MimeTypes; use Symfony\Component\Validator\Constraints\Image; @@ -87,9 +89,9 @@ public function testFileNotFound() /** * Checks that the logic from FileValidator still works. - * - * @group legacy */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testFileNotFoundDoctrineStyle() { $this->validator->validate('foobar', new Image([ @@ -127,9 +129,8 @@ public function testWidthTooSmall() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testWidthTooSmallDoctrineStyle() { $this->validator->validate($this->image, new Image([ @@ -155,9 +156,8 @@ public function testWidthTooBig() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testWidthTooBigDoctrineStyle() { $this->validator->validate($this->image, new Image([ @@ -183,9 +183,8 @@ public function testHeightTooSmall() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testHeightTooSmallDoctrineStyle() { $this->validator->validate($this->image, new Image([ @@ -211,9 +210,8 @@ public function testHeightTooBig() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testHeightTooBigDoctrineStyle() { $this->validator->validate($this->image, new Image([ @@ -241,9 +239,8 @@ public function testPixelsTooFew() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testPixelsTooFewDoctrineStyle() { $this->validator->validate($this->image, new Image([ @@ -273,9 +270,8 @@ public function testPixelsTooMany() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testPixelsTooManyDoctrineStyle() { $this->validator->validate($this->image, new Image([ @@ -303,9 +299,8 @@ public function testRatioTooSmall() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testRatioTooSmallDoctrineStyle() { $this->validator->validate($this->image, new Image([ @@ -331,9 +326,8 @@ public function testRatioTooBig() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testRatioTooBigDoctrineStyle() { $this->validator->validate($this->image, new Image([ @@ -386,9 +380,8 @@ public function testSquareNotAllowed() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testSquareNotAllowedDoctrineStyle() { $this->validator->validate($this->image, new Image([ @@ -414,9 +407,8 @@ public function testLandscapeNotAllowed() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testLandscapeNotAllowedDoctrineStyle() { $this->validator->validate($this->imageLandscape, new Image([ @@ -442,9 +434,8 @@ public function testPortraitNotAllowed() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testPortraitNotAllowedDoctrineStyle() { $this->validator->validate($this->imagePortrait, new Image([ @@ -478,9 +469,8 @@ public function testCorrupted() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testCorruptedDoctrineStyle() { if (!\function_exists('imagecreatefromstring')) { @@ -534,9 +524,8 @@ public function testInvalidMimeTypeWithNarrowedSet() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidMimeTypeWithNarrowedSetDoctrineStyle() { $this->validator->validate($this->image, new Image([ diff --git a/Tests/Constraints/IpTest.php b/Tests/Constraints/IpTest.php index 2d740ae88..01545c77c 100644 --- a/Tests/Constraints/IpTest.php +++ b/Tests/Constraints/IpTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Ip; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -29,9 +31,8 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $ip->normalizer); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerThrowsException() { $this->expectException(InvalidArgumentException::class); @@ -39,9 +40,8 @@ public function testInvalidNormalizerThrowsException() new Ip(['normalizer' => 'Unknown Callable']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerObjectThrowsException() { $this->expectException(InvalidArgumentException::class); diff --git a/Tests/Constraints/IsFalseValidatorTest.php b/Tests/Constraints/IsFalseValidatorTest.php index c6e2ccef6..5e1eae795 100644 --- a/Tests/Constraints/IsFalseValidatorTest.php +++ b/Tests/Constraints/IsFalseValidatorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\IsFalse; use Symfony\Component\Validator\Constraints\IsFalseValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -46,9 +48,8 @@ public function testTrueIsInvalid() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testTrueIsInvalidDoctrineStyle() { $constraint = new IsFalse([ diff --git a/Tests/Constraints/IsTrueValidatorTest.php b/Tests/Constraints/IsTrueValidatorTest.php index 4a9eb7702..543549314 100644 --- a/Tests/Constraints/IsTrueValidatorTest.php +++ b/Tests/Constraints/IsTrueValidatorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\IsTrueValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -46,9 +48,8 @@ public function testFalseIsInvalid() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testFalseIsInvalidDoctrineStyle() { $this->validator->validate(false, new IsTrue([ diff --git a/Tests/Constraints/IsbnValidatorTest.php b/Tests/Constraints/IsbnValidatorTest.php index 3ae3864d5..82a60b894 100644 --- a/Tests/Constraints/IsbnValidatorTest.php +++ b/Tests/Constraints/IsbnValidatorTest.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\Isbn; use Symfony\Component\Validator\Constraints\IsbnValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -157,11 +160,9 @@ public function testValidIsbn10($isbn) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getInvalidIsbn10 - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getInvalidIsbn10')] public function testInvalidIsbn10($isbn, $code) { $constraint = new Isbn([ @@ -202,11 +203,9 @@ public function testValidIsbn13($isbn) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getInvalidIsbn13 - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getInvalidIsbn13')] public function testInvalidIsbn13($isbn, $code) { $constraint = new Isbn([ diff --git a/Tests/Constraints/LengthTest.php b/Tests/Constraints/LengthTest.php index 6e292cb35..8859e68a8 100644 --- a/Tests/Constraints/LengthTest.php +++ b/Tests/Constraints/LengthTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -33,9 +35,8 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $length->normalizer); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerThrowsException() { $this->expectException(InvalidArgumentException::class); @@ -43,9 +44,8 @@ public function testInvalidNormalizerThrowsException() new Length(['min' => 0, 'max' => 10, 'normalizer' => 'Unknown Callable']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerObjectThrowsException() { $this->expectException(InvalidArgumentException::class); diff --git a/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php b/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php index 685bb58a6..61fc7ac9a 100644 --- a/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php +++ b/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\LessThanOrEqualValidator; use Symfony\Component\Validator\Constraints\NegativeOrZero; @@ -59,9 +61,8 @@ public static function provideInvalidComparisons(): array ]; } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintExceptionIfPropertyPath() { $this->expectException(ConstraintDefinitionException::class); @@ -70,9 +71,8 @@ public function testThrowsConstraintExceptionIfPropertyPath() return new NegativeOrZero(['propertyPath' => 'field']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintExceptionIfValue() { $this->expectException(ConstraintDefinitionException::class); diff --git a/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php b/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php index 5174a951d..0b40a19c1 100644 --- a/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php +++ b/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\LessThanValidator; use Symfony\Component\Validator\Constraints\Negative; @@ -58,9 +60,8 @@ public static function provideInvalidComparisons(): array ]; } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintExceptionIfPropertyPath() { $this->expectException(ConstraintDefinitionException::class); @@ -69,9 +70,8 @@ public function testThrowsConstraintExceptionIfPropertyPath() return new Negative(['propertyPath' => 'field']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintExceptionIfValue() { $this->expectException(ConstraintDefinitionException::class); diff --git a/Tests/Constraints/NotBlankTest.php b/Tests/Constraints/NotBlankTest.php index d04a65f1c..68a863473 100644 --- a/Tests/Constraints/NotBlankTest.php +++ b/Tests/Constraints/NotBlankTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -45,9 +47,8 @@ public function testAttributes() self::assertSame('myMessage', $bConstraint->message); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerThrowsException() { $this->expectException(InvalidArgumentException::class); @@ -55,9 +56,8 @@ public function testInvalidNormalizerThrowsException() new NotBlank(['normalizer' => 'Unknown Callable']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerObjectThrowsException() { $this->expectException(InvalidArgumentException::class); diff --git a/Tests/Constraints/NotCompromisedPasswordValidatorTest.php b/Tests/Constraints/NotCompromisedPasswordValidatorTest.php index 11c325d53..7b9d7f49f 100644 --- a/Tests/Constraints/NotCompromisedPasswordValidatorTest.php +++ b/Tests/Constraints/NotCompromisedPasswordValidatorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\Luhn; use Symfony\Component\Validator\Constraints\NotCompromisedPassword; use Symfony\Component\Validator\Constraints\NotCompromisedPasswordValidator; @@ -102,9 +104,8 @@ public function testThresholdNotReached() $this->assertNoViolation(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThresholdNotReachedDoctrineStyle() { $this->validator->validate(self::PASSWORD_LEAKED, new NotCompromisedPassword(['threshold' => 10])); @@ -216,9 +217,8 @@ public function testApiErrorSkipped() $this->validator->validate(self::PASSWORD_TRIGGERING_AN_ERROR, new NotCompromisedPassword(skipOnError: true)); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testApiErrorSkippedDoctrineStyle() { $this->expectNotToPerformAssertions(); diff --git a/Tests/Constraints/NotNullValidatorTest.php b/Tests/Constraints/NotNullValidatorTest.php index fec2ec12a..b47aa0fa1 100644 --- a/Tests/Constraints/NotNullValidatorTest.php +++ b/Tests/Constraints/NotNullValidatorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotNullValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -52,9 +54,8 @@ public function testNullIsInvalid() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testNullIsInvalidDoctrineStyle() { $this->validator->validate(null, new NotNull([ diff --git a/Tests/Constraints/RangeTest.php b/Tests/Constraints/RangeTest.php index 01481e8bc..7847285fa 100644 --- a/Tests/Constraints/RangeTest.php +++ b/Tests/Constraints/RangeTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -18,9 +20,8 @@ class RangeTest extends TestCase { - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintExceptionIfBothMinLimitAndPropertyPath() { $this->expectException(ConstraintDefinitionException::class); @@ -38,9 +39,8 @@ public function testThrowsConstraintExceptionIfBothMinLimitAndPropertyPathNamed( new Range(min: 'min', minPropertyPath: 'minPropertyPath'); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintExceptionIfBothMaxLimitAndPropertyPath() { $this->expectException(ConstraintDefinitionException::class); @@ -92,9 +92,8 @@ public function testThrowsConstraintDefinitionExceptionIfBothMinAndMaxAndMaxMess new Range(min: 'min', max: 'max', maxMessage: 'maxMessage'); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintDefinitionExceptionIfBothMinAndMaxAndMinMessageAndMaxMessageOptions() { $this->expectException(ConstraintDefinitionException::class); @@ -107,9 +106,8 @@ public function testThrowsConstraintDefinitionExceptionIfBothMinAndMaxAndMinMess ]); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintDefinitionExceptionIfBothMinAndMaxAndMinMessageOptions() { $this->expectException(ConstraintDefinitionException::class); @@ -121,9 +119,8 @@ public function testThrowsConstraintDefinitionExceptionIfBothMinAndMaxAndMinMess ]); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testThrowsConstraintDefinitionExceptionIfBothMinAndMaxAndMaxMessageOptions() { $this->expectException(ConstraintDefinitionException::class); diff --git a/Tests/Constraints/RangeValidatorTest.php b/Tests/Constraints/RangeValidatorTest.php index 423c8d460..34f78c5ac 100644 --- a/Tests/Constraints/RangeValidatorTest.php +++ b/Tests/Constraints/RangeValidatorTest.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Intl\Util\IntlTestHelper; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\RangeValidator; @@ -69,11 +72,9 @@ public static function getMoreThanTwenty(): array ]; } - /** - * @group legacy - * - * @dataProvider getTenToTwenty - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getTenToTwenty')] public function testValidValuesMin($value) { $constraint = new Range(['min' => 10]); @@ -93,11 +94,9 @@ public function testValidValuesMinNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getTenToTwenty - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getTenToTwenty')] public function testValidValuesMax($value) { $constraint = new Range(['max' => 20]); @@ -117,11 +116,9 @@ public function testValidValuesMaxNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getTenToTwenty - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getTenToTwenty')] public function testValidValuesMinMax($value) { $constraint = new Range(['min' => 10, 'max' => 20]); @@ -141,11 +138,9 @@ public function testValidValuesMinMaxNamed($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getLessThanTen - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getLessThanTen')] public function testInvalidValuesMin($value, $formattedValue) { $constraint = new Range([ @@ -178,11 +173,9 @@ public function testInvalidValuesMinNamed($value, $formattedValue) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getMoreThanTwenty - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getMoreThanTwenty')] public function testInvalidValuesMax($value, $formattedValue) { $constraint = new Range([ @@ -215,11 +208,9 @@ public function testInvalidValuesMaxNamed($value, $formattedValue) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getMoreThanTwenty - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getMoreThanTwenty')] public function testInvalidValuesCombinedMax($value, $formattedValue) { $constraint = new Range([ @@ -255,11 +246,9 @@ public function testInvalidValuesCombinedMaxNamed($value, $formattedValue) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getLessThanTen - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getLessThanTen')] public function testInvalidValuesCombinedMin($value, $formattedValue) { $constraint = new Range([ @@ -634,11 +623,9 @@ public function testNoViolationOnNullObjectWithPropertyPaths() $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getTenToTwenty - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getTenToTwenty')] public function testValidValuesMinPropertyPath($value) { $this->setObject(new Limit(10)); @@ -747,11 +734,9 @@ public function testInvalidValuesMaxPropertyPath($value, $formattedValue) ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getMoreThanTwenty - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getMoreThanTwenty')] public function testInvalidValuesCombinedMaxPropertyPath($value, $formattedValue) { $this->setObject(new MinMax(10, 20)); @@ -799,11 +784,9 @@ public function testInvalidValuesCombinedMaxPropertyPathNamed($value, $formatted ->assertRaised(); } - /** - * @group legacy - * - * @dataProvider getLessThanTen - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getLessThanTen')] public function testInvalidValuesCombinedMinPropertyPath($value, $formattedValue) { $this->setObject(new MinMax(10, 20)); diff --git a/Tests/Constraints/RegexTest.php b/Tests/Constraints/RegexTest.php index 5d3919ab8..7c26c9880 100644 --- a/Tests/Constraints/RegexTest.php +++ b/Tests/Constraints/RegexTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Regex; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -97,9 +99,8 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $regex->normalizer); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerThrowsException() { $this->expectException(InvalidArgumentException::class); @@ -107,9 +108,8 @@ public function testInvalidNormalizerThrowsException() new Regex(['pattern' => '/^[0-9]+$/', 'normalizer' => 'Unknown Callable']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerObjectThrowsException() { $this->expectException(InvalidArgumentException::class); @@ -148,9 +148,8 @@ public function testMissingPattern() new Regex(null); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testMissingPatternDoctrineStyle() { $this->expectException(MissingOptionsException::class); @@ -159,9 +158,8 @@ public function testMissingPatternDoctrineStyle() new Regex([]); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testPatternInOptionsArray() { $constraint = new Regex(null, options: ['pattern' => '/^[0-9]+$/']); diff --git a/Tests/Constraints/RegexValidatorTest.php b/Tests/Constraints/RegexValidatorTest.php index bafc752c3..9d6764af7 100644 --- a/Tests/Constraints/RegexValidatorTest.php +++ b/Tests/Constraints/RegexValidatorTest.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\Regex; use Symfony\Component\Validator\Constraints\RegexValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -54,11 +57,9 @@ public function testValidValues($value) $this->assertNoViolation(); } - /** - * @group legacy - * - * @dataProvider getValidValuesWithWhitespaces - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getValidValuesWithWhitespaces')] public function testValidValuesWithWhitespaces($value) { $constraint = new Regex(['pattern' => '/^[0-9]+$/', 'normalizer' => 'trim']); @@ -106,11 +107,9 @@ public static function getValidValuesWithWhitespaces() ]; } - /** - * @group legacy - * - * @dataProvider getInvalidValues - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getInvalidValues')] public function testInvalidValues($value) { $constraint = new Regex([ diff --git a/Tests/Constraints/TypeTest.php b/Tests/Constraints/TypeTest.php index a56cc514c..a9f68bc38 100644 --- a/Tests/Constraints/TypeTest.php +++ b/Tests/Constraints/TypeTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Exception\MissingOptionsException; @@ -46,9 +48,8 @@ public function testMissingType() new Type(null); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testTypeInOptionsArray() { $constraint = new Type(null, options: ['type' => 'digit']); diff --git a/Tests/Constraints/TypeValidatorTest.php b/Tests/Constraints/TypeValidatorTest.php index 8e9e1aa3b..3dbf23f7f 100644 --- a/Tests/Constraints/TypeValidatorTest.php +++ b/Tests/Constraints/TypeValidatorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\TypeValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -221,9 +223,8 @@ public function testInvalidValuesMultipleTypes() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidValuesMultipleTypesDoctrineStyle() { $this->validator->validate('12345', new Type([ diff --git a/Tests/Constraints/UniqueTest.php b/Tests/Constraints/UniqueTest.php index 9fe2599fd..94e7c42d4 100644 --- a/Tests/Constraints/UniqueTest.php +++ b/Tests/Constraints/UniqueTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Unique; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -37,9 +39,8 @@ public function testAttributes() self::assertSame('intval', $dConstraint->normalizer); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerThrowsException() { $this->expectException(InvalidArgumentException::class); @@ -47,9 +48,8 @@ public function testInvalidNormalizerThrowsException() new Unique(['normalizer' => 'Unknown Callable']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerObjectThrowsException() { $this->expectException(InvalidArgumentException::class); diff --git a/Tests/Constraints/UrlTest.php b/Tests/Constraints/UrlTest.php index cbc9bc18c..a15caf263 100644 --- a/Tests/Constraints/UrlTest.php +++ b/Tests/Constraints/UrlTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Url; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -29,9 +31,8 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $url->normalizer); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerThrowsException() { $this->expectException(InvalidArgumentException::class); @@ -39,9 +40,8 @@ public function testInvalidNormalizerThrowsException() new Url(['normalizer' => 'Unknown Callable', 'requireTld' => true]); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerObjectThrowsException() { $this->expectException(InvalidArgumentException::class); @@ -80,9 +80,8 @@ public function testAttributes() self::assertTrue($dConstraint->requireTld); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testRequireTldDefaultsToFalse() { $constraint = new Url(); diff --git a/Tests/Constraints/UuidTest.php b/Tests/Constraints/UuidTest.php index 22901a9db..a2cc15ca6 100644 --- a/Tests/Constraints/UuidTest.php +++ b/Tests/Constraints/UuidTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Uuid; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -29,9 +31,8 @@ public function testNormalizerCanBeSet() $this->assertEquals('trim', $uuid->normalizer); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerThrowsException() { $this->expectException(InvalidArgumentException::class); @@ -39,9 +40,8 @@ public function testInvalidNormalizerThrowsException() new Uuid(['normalizer' => 'Unknown Callable']); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidNormalizerObjectThrowsException() { $this->expectException(InvalidArgumentException::class); diff --git a/Tests/Constraints/WhenTest.php b/Tests/Constraints/WhenTest.php index 21d606701..fc5f5e88b 100644 --- a/Tests/Constraints/WhenTest.php +++ b/Tests/Constraints/WhenTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Length; @@ -26,9 +28,8 @@ final class WhenTest extends TestCase { - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testMissingOptionsExceptionIsThrown() { $this->expectException(MissingOptionsException::class); @@ -155,9 +156,8 @@ public function testAttributesWithClosure() self::assertSame(['Default', 'WhenTestWithClosure'], $fooConstraint->groups); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testConstraintsInOptionsArray() { $constraints = [ diff --git a/Tests/Mapping/Loader/XmlFileLoaderTest.php b/Tests/Mapping/Loader/XmlFileLoaderTest.php index 3b0872df2..eb04a03f2 100644 --- a/Tests/Mapping/Loader/XmlFileLoaderTest.php +++ b/Tests/Mapping/Loader/XmlFileLoaderTest.php @@ -11,8 +11,9 @@ namespace Symfony\Component\Validator\Tests\Mapping\Loader; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Choice; @@ -40,8 +41,6 @@ class XmlFileLoaderTest extends TestCase { - use ExpectUserDeprecationMessageTrait; - public function testLoadClassMetadataReturnsTrueIfSuccessful() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml'); @@ -94,9 +93,8 @@ public function testLoadClassMetadata() $this->assertEquals($expected, $metadata); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testLoadClassMetadataValueOption() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-value-option.xml'); @@ -192,9 +190,8 @@ public function testDoNotModifyStateIfExceptionIsThrown() } } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testLoadConstraintWithoutNamedArgumentsSupport() { $loader = new XmlFileLoader(__DIR__.'/constraint-without-named-arguments-support.xml'); diff --git a/Tests/Mapping/Loader/YamlFileLoaderTest.php b/Tests/Mapping/Loader/YamlFileLoaderTest.php index 9cf77fc38..5356e9414 100644 --- a/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -11,8 +11,9 @@ namespace Symfony\Component\Validator\Tests\Mapping\Loader; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Choice; @@ -37,8 +38,6 @@ class YamlFileLoaderTest extends TestCase { - use ExpectUserDeprecationMessageTrait; - public function testLoadClassMetadataReturnsFalseIfEmpty() { $loader = new YamlFileLoader(__DIR__.'/empty-mapping.yml'); @@ -138,9 +137,8 @@ public function testLoadClassMetadata() $this->assertEquals($expected, $metadata); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testLoadClassMetadataValueOption() { $loader = new YamlFileLoader(__DIR__.'/constraint-mapping-value-option.yml'); @@ -208,9 +206,8 @@ public function testLoadGroupProvider() $this->assertEquals($expected, $metadata); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testLoadConstraintWithoutNamedArgumentsSupport() { $loader = new YamlFileLoader(__DIR__.'/constraint-without-named-arguments-support.yml'); diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 8288431b6..cdd1c74a9 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -27,5 +28,9 @@ ./Tests ./vendor - + + + + + From 1c83cd00cf5c2ff6e279ec9be4f5ea071121c9bb Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 31 Jul 2025 14:36:46 +0200 Subject: [PATCH 20/57] replace PHPUnit annotations with attributes --- Tests/ConstraintValidatorTest.php | 5 +- Tests/ConstraintViolationListTest.php | 5 +- .../AbstractComparisonValidatorTestCase.php | 9 +- Tests/Constraints/AllValidatorTest.php | 9 +- .../Constraints/AtLeastOneOfValidatorTest.php | 13 +- Tests/Constraints/BicValidatorTest.php | 20 +- Tests/Constraints/BlankValidatorTest.php | 5 +- Tests/Constraints/CardSchemeValidatorTest.php | 13 +- Tests/Constraints/CharsetValidatorTest.php | 13 +- Tests/Constraints/ChoiceValidatorTest.php | 4 +- Tests/Constraints/CidrTest.php | 9 +- Tests/Constraints/CidrValidatorTest.php | 25 +-- Tests/Constraints/CollectionTest.php | 13 +- Tests/Constraints/CountValidatorTestCase.php | 28 +-- Tests/Constraints/CountryValidatorTest.php | 17 +- Tests/Constraints/CssColorValidatorTest.php | 89 +++------ Tests/Constraints/CurrencyValidatorTest.php | 17 +- Tests/Constraints/DateTimeValidatorTest.php | 9 +- Tests/Constraints/DateValidatorTest.php | 13 +- .../Constraints/DivisibleByValidatorTest.php | 5 +- Tests/Constraints/EmailValidatorTest.php | 38 +--- Tests/Constraints/ExpressionSyntaxTest.php | 5 +- Tests/Constraints/ExpressionValidatorTest.php | 5 +- Tests/Constraints/FileTest.php | 25 +-- Tests/Constraints/FileValidatorTestCase.php | 37 +--- ...idatorWithPositiveOrZeroConstraintTest.php | 9 +- ...hanValidatorWithPositiveConstraintTest.php | 9 +- Tests/Constraints/HostnameValidatorTest.php | 33 +-- Tests/Constraints/IbanValidatorTest.php | 25 +-- Tests/Constraints/ImageValidatorTest.php | 17 +- .../InvalidComparisonToValueTestTrait.php | 5 +- Tests/Constraints/IpValidatorTest.php | 85 ++------ Tests/Constraints/IsNullValidatorTest.php | 9 +- Tests/Constraints/IsbnValidatorTest.php | 24 +-- Tests/Constraints/IsinValidatorTest.php | 17 +- Tests/Constraints/IssnValidatorTest.php | 17 +- Tests/Constraints/JsonValidatorTest.php | 9 +- Tests/Constraints/LanguageValidatorTest.php | 17 +- Tests/Constraints/LengthValidatorTest.php | 49 ++--- ...idatorWithNegativeOrZeroConstraintTest.php | 9 +- ...hanValidatorWithNegativeConstraintTest.php | 9 +- Tests/Constraints/LocaleValidatorTest.php | 21 +- Tests/Constraints/LuhnValidatorTest.php | 13 +- Tests/Constraints/MacAddressValidatorTest.php | 189 ++++++------------ .../NoSuspiciousCharactersValidatorTest.php | 13 +- Tests/Constraints/NotBlankValidatorTest.php | 9 +- Tests/Constraints/NotNullValidatorTest.php | 5 +- .../PasswordStrengthValidatorTest.php | 13 +- ...sswordStrengthValidatorWithClosureTest.php | 9 +- Tests/Constraints/RangeValidatorTest.php | 132 +++--------- Tests/Constraints/RegexTest.php | 5 +- Tests/Constraints/RegexValidatorTest.php | 12 +- .../ThrowsOnInvalidStringDatesTestTrait.php | 5 +- Tests/Constraints/TimeValidatorTest.php | 25 +-- Tests/Constraints/TimezoneTest.php | 5 +- Tests/Constraints/TimezoneValidatorTest.php | 38 +--- Tests/Constraints/TypeValidatorTest.php | 13 +- Tests/Constraints/UlidValidatorTest.php | 13 +- Tests/Constraints/UniqueValidatorTest.php | 25 +-- Tests/Constraints/UrlValidatorTest.php | 43 ++-- Tests/Constraints/UuidValidatorTest.php | 25 +-- .../ValidComparisonToValueTrait.php | 6 +- Tests/Constraints/WeekValidatorTest.php | 13 +- Tests/Constraints/WhenTest.php | 5 +- Tests/Constraints/WordCountTest.php | 5 +- Tests/Constraints/WordCountValidatorTest.php | 14 +- Tests/Constraints/YamlValidatorTest.php | 9 +- .../AddAutoMappingConfigurationPassTest.php | 5 +- .../Mapping/Loader/PropertyInfoLoaderTest.php | 5 +- Tests/Mapping/Loader/YamlFileLoaderTest.php | 5 +- Tests/Resources/TranslationFilesTest.php | 9 +- Tests/Util/PropertyPathTest.php | 5 +- Tests/Validator/RecursiveValidatorTest.php | 133 ++++++------ 73 files changed, 503 insertions(+), 1098 deletions(-) diff --git a/Tests/ConstraintValidatorTest.php b/Tests/ConstraintValidatorTest.php index d378ba292..3060bd23d 100644 --- a/Tests/ConstraintValidatorTest.php +++ b/Tests/ConstraintValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -20,9 +21,7 @@ class ConstraintValidatorTest extends TestCase { use IcuCompatibilityTrait; - /** - * @dataProvider formatValueProvider - */ + #[DataProvider('formatValueProvider')] public function testFormatValue(string $expected, mixed $value, int $format = 0) { \Locale::setDefault('en'); diff --git a/Tests/ConstraintViolationListTest.php b/Tests/ConstraintViolationListTest.php index 0d22bd85e..ee7d53112 100644 --- a/Tests/ConstraintViolationListTest.php +++ b/Tests/ConstraintViolationListTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; @@ -123,9 +124,7 @@ public function testToString() $this->assertEquals($expected, (string) $this->list); } - /** - * @dataProvider findByCodesProvider - */ + #[DataProvider('findByCodesProvider')] public function testFindByCodes($code, $violationsCount) { $violations = [ diff --git a/Tests/Constraints/AbstractComparisonValidatorTestCase.php b/Tests/Constraints/AbstractComparisonValidatorTestCase.php index 25fed976c..883db201c 100644 --- a/Tests/Constraints/AbstractComparisonValidatorTestCase.php +++ b/Tests/Constraints/AbstractComparisonValidatorTestCase.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -75,9 +76,7 @@ public static function provideInvalidConstraintOptions() ]; } - /** - * @dataProvider provideInvalidConstraintOptions - */ + #[DataProvider('provideInvalidConstraintOptions')] public function testThrowsConstraintExceptionIfNoValueOrPropertyPath($options) { $this->expectException(ConstraintDefinitionException::class); @@ -95,9 +94,7 @@ public function testThrowsConstraintExceptionIfBothValueAndPropertyPath() ]); } - /** - * @dataProvider provideValidComparisonsToPropertyPath - */ + #[DataProvider('provideValidComparisonsToPropertyPath')] public function testValidComparisonToPropertyPath($comparedValue) { $constraint = $this->createConstraint(['propertyPath' => 'value']); diff --git a/Tests/Constraints/AllValidatorTest.php b/Tests/Constraints/AllValidatorTest.php index ee6a29174..9c70c935c 100644 --- a/Tests/Constraints/AllValidatorTest.php +++ b/Tests/Constraints/AllValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\AllValidator; use Symfony\Component\Validator\Constraints\NotNull; @@ -38,9 +39,7 @@ public function testThrowsExceptionIfNotTraversable() $this->validator->validate('foo.barbar', new All(new Range(min: 4))); } - /** - * @dataProvider getValidArguments - */ + #[DataProvider('getValidArguments')] public function testWalkSingleConstraint($array) { $constraint = new Range(min: 4); @@ -56,9 +55,7 @@ public function testWalkSingleConstraint($array) $this->assertNoViolation(); } - /** - * @dataProvider getValidArguments - */ + #[DataProvider('getValidArguments')] public function testWalkMultipleConstraints($array) { $constraint1 = new Range(min: 4); diff --git a/Tests/Constraints/AtLeastOneOfValidatorTest.php b/Tests/Constraints/AtLeastOneOfValidatorTest.php index 59b737edc..ff2d04dc2 100644 --- a/Tests/Constraints/AtLeastOneOfValidatorTest.php +++ b/Tests/Constraints/AtLeastOneOfValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\AtLeastOneOf; use Symfony\Component\Validator\Constraints\AtLeastOneOfValidator; use Symfony\Component\Validator\Constraints\Choice; @@ -54,9 +55,7 @@ protected function createValidator(): AtLeastOneOfValidator return new AtLeastOneOfValidator(); } - /** - * @dataProvider getValidCombinations - */ + #[DataProvider('getValidCombinations')] public function testValidCombinations($value, $constraints) { $this->assertCount(0, Validation::createValidator()->validate($value, new AtLeastOneOf($constraints))); @@ -96,9 +95,7 @@ public static function getValidCombinations() ]; } - /** - * @dataProvider getInvalidCombinations - */ + #[DataProvider('getInvalidCombinations')] public function testInvalidCombinationsWithDefaultMessage($value, $constraints) { $atLeastOneOf = new AtLeastOneOf(constraints: $constraints); @@ -118,9 +115,7 @@ public function testInvalidCombinationsWithDefaultMessage($value, $constraints) $this->assertEquals(new ConstraintViolation(implode('', $message), implode('', $message), [], $value, '', $value, null, AtLeastOneOf::AT_LEAST_ONE_OF_ERROR, $atLeastOneOf), $violations->get(0)); } - /** - * @dataProvider getInvalidCombinations - */ + #[DataProvider('getInvalidCombinations')] public function testInvalidCombinationsWithCustomMessage($value, $constraints) { $atLeastOneOf = new AtLeastOneOf( diff --git a/Tests/Constraints/BicValidatorTest.php b/Tests/Constraints/BicValidatorTest.php index 315cb859e..6c1f275e9 100644 --- a/Tests/Constraints/BicValidatorTest.php +++ b/Tests/Constraints/BicValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Bic; use Symfony\Component\Validator\Constraints\BicValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -189,9 +190,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Bic()); } - /** - * @dataProvider getValidBics - */ + #[DataProvider('getValidBics')] public function testValidBics($bic) { $this->validator->validate($bic, new Bic()); @@ -212,9 +211,7 @@ public static function getValidBics() ]; } - /** - * @dataProvider getInvalidBics - */ + #[DataProvider('getInvalidBics')] public function testInvalidBics($bic, $code) { $constraint = new Bic( @@ -229,9 +226,7 @@ public function testInvalidBics($bic, $code) ->assertRaised(); } - /** - * @dataProvider getInvalidBics - */ + #[DataProvider('getInvalidBics')] public function testInvalidBicsNamed($bic, $code) { $constraint = new Bic(message: 'myMessage'); @@ -270,11 +265,10 @@ public static function getInvalidBics() } /** - * @dataProvider getValidBicSpecialCases - * * Some territories have their own ISO country code but can use another country code * for IBAN accounts. Example: "French Guiana" (country code "GF") can use FR too. */ + #[DataProvider('getValidBicSpecialCases')] public function testValidBicSpecialCases(string $bic, string $iban) { $constraint = new Bic(iban: $iban); @@ -313,9 +307,7 @@ public static function getValidBicSpecialCases() yield ['CAIXEABBXXX', 'ES79 2100 0813 6101 2345 6789']; } - /** - * @dataProvider getValidBicsWithNormalizerToUpper - */ + #[DataProvider('getValidBicsWithNormalizerToUpper')] public function testValidBicsWithNormalizerToUpper($bic) { $this->validator->validate($bic, new Bic(mode: Bic::VALIDATION_MODE_CASE_INSENSITIVE)); diff --git a/Tests/Constraints/BlankValidatorTest.php b/Tests/Constraints/BlankValidatorTest.php index 21d3fc83e..62ee839a5 100644 --- a/Tests/Constraints/BlankValidatorTest.php +++ b/Tests/Constraints/BlankValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Blank; use Symfony\Component\Validator\Constraints\BlankValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -36,9 +37,7 @@ public function testBlankIsValid() $this->assertNoViolation(); } - /** - * @dataProvider getInvalidValues - */ + #[DataProvider('getInvalidValues')] public function testInvalidValues($value, $valueAsString) { $constraint = new Blank( diff --git a/Tests/Constraints/CardSchemeValidatorTest.php b/Tests/Constraints/CardSchemeValidatorTest.php index d70457833..0426b557a 100644 --- a/Tests/Constraints/CardSchemeValidatorTest.php +++ b/Tests/Constraints/CardSchemeValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\CardScheme; use Symfony\Component\Validator\Constraints\CardSchemeValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -36,9 +37,7 @@ public function testEmptyStringIsValid() $this->assertNoViolation(); } - /** - * @dataProvider getValidNumbers - */ + #[DataProvider('getValidNumbers')] public function testValidNumbers($scheme, $number) { $this->validator->validate($number, new CardScheme(schemes: $scheme)); @@ -46,9 +45,7 @@ public function testValidNumbers($scheme, $number) $this->assertNoViolation(); } - /** - * @dataProvider getValidNumbers - */ + #[DataProvider('getValidNumbers')] public function testValidNumbersWithNewLine($scheme, $number) { $this->validator->validate($number."\n", new CardScheme(schemes: $scheme, message: 'myMessage')); @@ -69,9 +66,7 @@ public function testValidNumberWithOrderedArguments() $this->assertNoViolation(); } - /** - * @dataProvider getInvalidNumbers - */ + #[DataProvider('getInvalidNumbers')] public function testInvalidNumbers($scheme, $number, $code) { $constraint = new CardScheme( diff --git a/Tests/Constraints/CharsetValidatorTest.php b/Tests/Constraints/CharsetValidatorTest.php index 5c2f2c884..f9c782ea6 100644 --- a/Tests/Constraints/CharsetValidatorTest.php +++ b/Tests/Constraints/CharsetValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Charset; use Symfony\Component\Validator\Constraints\CharsetValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -24,9 +25,7 @@ protected function createValidator(): CharsetValidator return new CharsetValidator(); } - /** - * @dataProvider provideValidValues - */ + #[DataProvider('provideValidValues')] public function testEncodingIsValid(string|\Stringable $value, array|string $encodings) { $this->validator->validate($value, new Charset(encodings: $encodings)); @@ -34,9 +33,7 @@ public function testEncodingIsValid(string|\Stringable $value, array|string $enc $this->assertNoViolation(); } - /** - * @dataProvider provideInvalidValues - */ + #[DataProvider('provideInvalidValues')] public function testInvalidValues(string $value, array|string $encodings) { $this->validator->validate($value, new Charset(encodings: $encodings)); @@ -48,9 +45,7 @@ public function testInvalidValues(string $value, array|string $encodings) ->assertRaised(); } - /** - * @dataProvider provideInvalidTypes - */ + #[DataProvider('provideInvalidTypes')] public function testNonStringValues(mixed $value) { $this->expectException(UnexpectedValueException::class); diff --git a/Tests/Constraints/ChoiceValidatorTest.php b/Tests/Constraints/ChoiceValidatorTest.php index 4629432fc..a2935323f 100644 --- a/Tests/Constraints/ChoiceValidatorTest.php +++ b/Tests/Constraints/ChoiceValidatorTest.php @@ -109,9 +109,7 @@ public static function provideLegacyConstraintsWithChoicesArrayDoctrineStyle(): yield 'Doctrine default option' => [new Choice(['value' => ['foo', 'bar']])]; } - /** - * @dataProvider provideConstraintsWithCallbackFunction - */ + #[DataProvider('provideConstraintsWithCallbackFunction')] public function testValidChoiceCallbackFunction(Choice $constraint) { $this->validator->validate('bar', $constraint); diff --git a/Tests/Constraints/CidrTest.php b/Tests/Constraints/CidrTest.php index 25059104d..9653cba73 100644 --- a/Tests/Constraints/CidrTest.php +++ b/Tests/Constraints/CidrTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Cidr; use Symfony\Component\Validator\Constraints\Ip; @@ -65,9 +66,7 @@ public function testWithInvalidVersion() new Cidr(version: '8'); } - /** - * @dataProvider getValidMinMaxValues - */ + #[DataProvider('getValidMinMaxValues')] public function testWithValidMinMaxValues(string $ipVersion, int $netmaskMin, int $netmaskMax) { $cidrConstraint = new Cidr( @@ -81,9 +80,7 @@ public function testWithValidMinMaxValues(string $ipVersion, int $netmaskMin, in self::assertEquals($netmaskMax, $cidrConstraint->netmaskMax); } - /** - * @dataProvider getInvalidMinMaxValues - */ + #[DataProvider('getInvalidMinMaxValues')] public function testWithInvalidMinMaxValues(string $ipVersion, int $netmaskMin, int $netmaskMax) { $expectedMax = Ip::V4 == $ipVersion ? 32 : 128; diff --git a/Tests/Constraints/CidrValidatorTest.php b/Tests/Constraints/CidrValidatorTest.php index 6dfdc4931..91229d74f 100644 --- a/Tests/Constraints/CidrValidatorTest.php +++ b/Tests/Constraints/CidrValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Cidr; use Symfony\Component\Validator\Constraints\CidrValidator; use Symfony\Component\Validator\Constraints\Ip; @@ -55,9 +56,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(123456, new Cidr()); } - /** - * @dataProvider getWithInvalidNetmask - */ + #[DataProvider('getWithInvalidNetmask')] public function testInvalidNetmask(string $cidr) { $this->validator->validate($cidr, new Cidr()); @@ -68,9 +67,7 @@ public function testInvalidNetmask(string $cidr) ->assertRaised(); } - /** - * @dataProvider getWithInvalidIps - */ + #[DataProvider('getWithInvalidIps')] public function testInvalidIpValue(string $cidr) { $this->validator->validate($cidr, new Cidr()); @@ -81,9 +78,7 @@ public function testInvalidIpValue(string $cidr) ->assertRaised(); } - /** - * @dataProvider getValid - */ + #[DataProvider('getValid')] public function testValidCidr(string|\Stringable $cidr, string $version) { $this->validator->validate($cidr, new Cidr(version: $version)); @@ -91,9 +86,7 @@ public function testValidCidr(string|\Stringable $cidr, string $version) $this->assertNoViolation(); } - /** - * @dataProvider getWithInvalidMasksAndIps - */ + #[DataProvider('getWithInvalidMasksAndIps')] public function testInvalidIpAddressAndNetmask(string|\Stringable $cidr) { $this->validator->validate($cidr, new Cidr()); @@ -103,9 +96,7 @@ public function testInvalidIpAddressAndNetmask(string|\Stringable $cidr) ->assertRaised(); } - /** - * @dataProvider getOutOfRangeNetmask - */ + #[DataProvider('getOutOfRangeNetmask')] public function testOutOfRangeNetmask(string $cidr, int $maxExpected, ?string $version = null, ?int $min = null, ?int $max = null) { $cidrConstraint = new Cidr( @@ -123,9 +114,7 @@ public function testOutOfRangeNetmask(string $cidr, int $maxExpected, ?string $v ->assertRaised(); } - /** - * @dataProvider getWithWrongVersion - */ + #[DataProvider('getWithWrongVersion')] public function testWrongVersion(string $cidr, string $version) { $this->validator->validate($cidr, new Cidr(version: $version)); diff --git a/Tests/Constraints/CollectionTest.php b/Tests/Constraints/CollectionTest.php index dc962b3e9..994a75081 100644 --- a/Tests/Constraints/CollectionTest.php +++ b/Tests/Constraints/CollectionTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Email; @@ -166,10 +167,8 @@ public function testEmptyFieldsInOptions() $this->assertSame('foo bar baz', $constraint->extraFieldsMessage); } - /** - * @testWith [[]] - * [null] - */ + #[TestWith([[]])] + #[TestWith([null])] public function testEmptyConstraintListForField(?array $fieldConstraint) { $constraint = new Collection( @@ -189,10 +188,8 @@ public function testEmptyConstraintListForField(?array $fieldConstraint) $this->assertSame('foo bar baz', $constraint->extraFieldsMessage); } - /** - * @testWith [[]] - * [null] - */ + #[TestWith([[]])] + #[TestWith([null])] public function testEmptyConstraintListForFieldInOptions(?array $fieldConstraint) { $constraint = new Collection( diff --git a/Tests/Constraints/CountValidatorTestCase.php b/Tests/Constraints/CountValidatorTestCase.php index 08b171dc9..93f91fd9b 100644 --- a/Tests/Constraints/CountValidatorTestCase.php +++ b/Tests/Constraints/CountValidatorTestCase.php @@ -83,9 +83,7 @@ public function testValidValuesMax($value) $this->assertNoViolation(); } - /** - * @dataProvider getThreeOrLessElements - */ + #[DataProvider('getThreeOrLessElements')] public function testValidValuesMaxNamed($value) { $constraint = new Count(max: 3); @@ -105,9 +103,7 @@ public function testValidValuesMin($value) $this->assertNoViolation(); } - /** - * @dataProvider getFiveOrMoreElements - */ + #[DataProvider('getFiveOrMoreElements')] public function testValidValuesMinNamed($value) { $constraint = new Count(min: 5); @@ -127,9 +123,7 @@ public function testValidValuesExact($value) $this->assertNoViolation(); } - /** - * @dataProvider getFourElements - */ + #[DataProvider('getFourElements')] public function testValidValuesExactNamed($value) { $constraint = new Count(exactly: 4); @@ -159,9 +153,7 @@ public function testTooManyValues($value) ->assertRaised(); } - /** - * @dataProvider getFiveOrMoreElements - */ + #[DataProvider('getFiveOrMoreElements')] public function testTooManyValuesNamed($value) { $constraint = new Count(max: 4, maxMessage: 'myMessage'); @@ -198,9 +190,7 @@ public function testTooFewValues($value) ->assertRaised(); } - /** - * @dataProvider getThreeOrLessElements - */ + #[DataProvider('getThreeOrLessElements')] public function testTooFewValuesNamed($value) { $constraint = new Count(min: 4, minMessage: 'myMessage'); @@ -238,9 +228,7 @@ public function testTooManyValuesExact($value) ->assertRaised(); } - /** - * @dataProvider getFiveOrMoreElements - */ + #[DataProvider('getFiveOrMoreElements')] public function testTooManyValuesExactNamed($value) { $constraint = new Count(exactly: 4, exactMessage: 'myMessage'); @@ -256,9 +244,7 @@ public function testTooManyValuesExactNamed($value) ->assertRaised(); } - /** - * @dataProvider getThreeOrLessElements - */ + #[DataProvider('getThreeOrLessElements')] public function testTooFewValuesExact($value) { $constraint = new Count( diff --git a/Tests/Constraints/CountryValidatorTest.php b/Tests/Constraints/CountryValidatorTest.php index e535ce4f5..668195fcc 100644 --- a/Tests/Constraints/CountryValidatorTest.php +++ b/Tests/Constraints/CountryValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Intl\Util\IntlTestHelper; use Symfony\Component\Validator\Constraints\Country; use Symfony\Component\Validator\Constraints\CountryValidator; @@ -60,9 +61,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Country()); } - /** - * @dataProvider getValidCountries - */ + #[DataProvider('getValidCountries')] public function testValidCountries($country) { $this->validator->validate($country, new Country()); @@ -79,9 +78,7 @@ public static function getValidCountries() ]; } - /** - * @dataProvider getInvalidCountries - */ + #[DataProvider('getInvalidCountries')] public function testInvalidCountries($country) { $constraint = new Country(message: 'myMessage'); @@ -102,9 +99,7 @@ public static function getInvalidCountries() ]; } - /** - * @dataProvider getValidAlpha3Countries - */ + #[DataProvider('getValidAlpha3Countries')] public function testValidAlpha3Countries($country) { $this->validator->validate($country, new Country(alpha3: true)); @@ -121,9 +116,7 @@ public static function getValidAlpha3Countries() ]; } - /** - * @dataProvider getInvalidAlpha3Countries - */ + #[DataProvider('getInvalidAlpha3Countries')] public function testInvalidAlpha3Countries($country) { $constraint = new Country( diff --git a/Tests/Constraints/CssColorValidatorTest.php b/Tests/Constraints/CssColorValidatorTest.php index bc1087c47..857fac605 100644 --- a/Tests/Constraints/CssColorValidatorTest.php +++ b/Tests/Constraints/CssColorValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\CssColor; use Symfony\Component\Validator\Constraints\CssColorValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -44,18 +45,14 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new CssColor(CssColor::HEX_LONG)); } - /** - * @dataProvider getValidAnyColor - */ + #[DataProvider('getValidAnyColor')] public function testValidAnyColor($cssColor) { $this->validator->validate($cssColor, new CssColor()); $this->assertNoViolation(); } - /** - * @dataProvider getValidAnyColor - */ + #[DataProvider('getValidAnyColor')] public function testValidAnyColorWithNewLine($cssColor) { $this->validator->validate($cssColor."\n", new CssColor([], 'myMessage')); @@ -85,9 +82,7 @@ public static function getValidAnyColor(): array ]; } - /** - * @dataProvider getValidHexLongColors - */ + #[DataProvider('getValidHexLongColors')] public function testValidHexLongColors($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::HEX_LONG)); @@ -99,9 +94,7 @@ public static function getValidHexLongColors(): array return [['#ABCDEF'], ['#abcdef'], ['#C0FFEE'], ['#c0ffee'], ['#501311']]; } - /** - * @dataProvider getValidHexLongColorsWithAlpha - */ + #[DataProvider('getValidHexLongColorsWithAlpha')] public function testValidHexLongColorsWithAlpha($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::HEX_LONG_WITH_ALPHA)); @@ -113,9 +106,7 @@ public static function getValidHexLongColorsWithAlpha(): array return [['#ABCDEF00'], ['#abcdef01'], ['#C0FFEE02'], ['#c0ffee03'], ['#501311FF']]; } - /** - * @dataProvider getValidHexShortColors - */ + #[DataProvider('getValidHexShortColors')] public function testValidHexShortColors($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::HEX_SHORT)); @@ -127,9 +118,7 @@ public static function getValidHexShortColors(): array return [['#F4B'], ['#FAB'], ['#f4b'], ['#fab']]; } - /** - * @dataProvider getValidHexShortColorsWithAlpha - */ + #[DataProvider('getValidHexShortColorsWithAlpha')] public function testValidHexShortColorsWithAlpha($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::HEX_SHORT_WITH_ALPHA)); @@ -141,9 +130,7 @@ public static function getValidHexShortColorsWithAlpha(): array return [['#F4B1'], ['#FAB1'], ['#f4b1'], ['#fab1']]; } - /** - * @dataProvider getValidBasicNamedColors - */ + #[DataProvider('getValidBasicNamedColors')] public function testValidBasicNamedColors($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::BASIC_NAMED_COLORS)); @@ -158,9 +145,7 @@ public static function getValidBasicNamedColors(): array ]; } - /** - * @dataProvider getValidExtendedNamedColors - */ + #[DataProvider('getValidExtendedNamedColors')] public function testValidExtendedNamedColors($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::EXTENDED_NAMED_COLORS)); @@ -175,9 +160,7 @@ public static function getValidExtendedNamedColors(): array ]; } - /** - * @dataProvider getValidSystemColors - */ + #[DataProvider('getValidSystemColors')] public function testValidSystemColors($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::SYSTEM_COLORS)); @@ -193,9 +176,7 @@ public static function getValidSystemColors(): array ]; } - /** - * @dataProvider getValidKeywords - */ + #[DataProvider('getValidKeywords')] public function testValidKeywords($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::KEYWORDS)); @@ -207,9 +188,7 @@ public static function getValidKeywords(): array return [['transparent'], ['currentColor']]; } - /** - * @dataProvider getValidRGB - */ + #[DataProvider('getValidRGB')] public function testValidRGB($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::RGB)); @@ -225,9 +204,7 @@ public static function getValidRGB(): array ]; } - /** - * @dataProvider getValidRGBA - */ + #[DataProvider('getValidRGBA')] public function testValidRGBA($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::RGBA)); @@ -244,9 +221,7 @@ public static function getValidRGBA(): array ]; } - /** - * @dataProvider getValidHSL - */ + #[DataProvider('getValidHSL')] public function testValidHSL($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::HSL)); @@ -262,9 +237,7 @@ public static function getValidHSL(): array ]; } - /** - * @dataProvider getValidHSLA - */ + #[DataProvider('getValidHSLA')] public function testValidHSLA($cssColor) { $this->validator->validate($cssColor, new CssColor(CssColor::HSLA)); @@ -281,9 +254,7 @@ public static function getValidHSLA(): array ]; } - /** - * @dataProvider getInvalidHexColors - */ + #[DataProvider('getInvalidHexColors')] public function testInvalidHexColors($cssColor) { $constraint = new CssColor([CssColor::HEX_LONG, CssColor::HEX_LONG_WITH_ALPHA], 'myMessage'); @@ -300,9 +271,7 @@ public static function getInvalidHexColors(): array return [['ABCDEF'], ['abcdef'], ['#K0FFEE'], ['#k0ffee'], ['#_501311'], ['ABCDEF00'], ['abcdefcc'], ['#K0FFEE33'], ['#k0ffeecc'], ['#_50131100'], ['#FAℬ'], ['#Ⅎab'], ['#F4️⃣B'], ['#f(4)b'], ['#907;']]; } - /** - * @dataProvider getInvalidShortHexColors - */ + #[DataProvider('getInvalidShortHexColors')] public function testInvalidShortHexColors($cssColor) { $this->validator->validate($cssColor, new CssColor([CssColor::HEX_SHORT, CssColor::HEX_SHORT_WITH_ALPHA], 'myMessage')); @@ -318,9 +287,7 @@ public static function getInvalidShortHexColors(): array return [['ABC'], ['ABCD'], ['abc'], ['abcd'], ['#K0F'], ['#K0FF'], ['#k0f'], ['#k0ff'], ['#_50'], ['#_501']]; } - /** - * @dataProvider getInvalidNamedColors - */ + #[DataProvider('getInvalidNamedColors')] public function testInvalidNamedColors($cssColor) { $this->validator->validate($cssColor, new CssColor([ @@ -341,9 +308,7 @@ public static function getInvalidNamedColors(): array return [['fabpot'], ['ngrekas'], ['symfony'], ['FABPOT'], ['NGREKAS'], ['SYMFONY'], [new StringableValue('SYMFONY')]]; } - /** - * @dataProvider getInvalidRGB - */ + #[DataProvider('getInvalidRGB')] public function testInvalidRGB($cssColor) { $this->validator->validate($cssColor, new CssColor([ @@ -364,9 +329,7 @@ public static function getInvalidRGB(): array return [['rgb(999,999,999)'], ['rgb(-99,-99,-99)'], ['rgb(a,b,c)'], ['rgb(99 99, 9 99, 99 9)']]; } - /** - * @dataProvider getInvalidRGBA - */ + #[DataProvider('getInvalidRGBA')] public function testInvalidRGBA($cssColor) { $this->validator->validate($cssColor, new CssColor([ @@ -392,9 +355,7 @@ public static function getInvalidRGBA(): array ]; } - /** - * @dataProvider getInvalidHSL - */ + #[DataProvider('getInvalidHSL')] public function testInvalidHSL($cssColor) { $this->validator->validate($cssColor, new CssColor([ @@ -415,9 +376,7 @@ public static function getInvalidHSL(): array return [['hsl(1000, 1000%, 20000%)'], ['hsl(-100, -10%, -2%)'], ['hsl(a, b, c)'], ['hsl(a, b%, c%)'], ['hsl( 99 99% , 9 99% , 99 9%)']]; } - /** - * @dataProvider getInvalidHSLA - */ + #[DataProvider('getInvalidHSLA')] public function testInvalidHSLA($cssColor) { $this->validator->validate($cssColor, new CssColor([ @@ -444,9 +403,7 @@ public static function getInvalidHSLA(): array ]; } - /** - * @dataProvider getInvalidFormats - */ + #[DataProvider('getInvalidFormats')] public function testUnknownFormatAsStringThrowsException($formats) { $this->expectException(\InvalidArgumentException::class); diff --git a/Tests/Constraints/CurrencyValidatorTest.php b/Tests/Constraints/CurrencyValidatorTest.php index 51def4a2a..7b940d0e5 100644 --- a/Tests/Constraints/CurrencyValidatorTest.php +++ b/Tests/Constraints/CurrencyValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Intl\Util\IntlTestHelper; use Symfony\Component\Validator\Constraints\Currency; use Symfony\Component\Validator\Constraints\CurrencyValidator; @@ -60,9 +61,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Currency()); } - /** - * @dataProvider getValidCurrencies - */ + #[DataProvider('getValidCurrencies')] public function testValidCurrencies($currency) { $this->validator->validate($currency, new Currency()); @@ -70,9 +69,7 @@ public function testValidCurrencies($currency) $this->assertNoViolation(); } - /** - * @dataProvider getValidCurrencies - **/ + #[DataProvider('getValidCurrencies')] public function testValidCurrenciesWithCountrySpecificLocale($currency) { IntlTestHelper::requireFullIntl($this, false); @@ -95,9 +92,7 @@ public static function getValidCurrencies() ]; } - /** - * @dataProvider getInvalidCurrencies - */ + #[DataProvider('getInvalidCurrencies')] public function testInvalidCurrencies($currency) { $constraint = new Currency(message: 'myMessage'); @@ -110,9 +105,7 @@ public function testInvalidCurrencies($currency) ->assertRaised(); } - /** - * @dataProvider getInvalidCurrencies - */ + #[DataProvider('getInvalidCurrencies')] public function testInvalidCurrenciesNamed($currency) { $constraint = new Currency(message: 'myMessage'); diff --git a/Tests/Constraints/DateTimeValidatorTest.php b/Tests/Constraints/DateTimeValidatorTest.php index 383f06215..b1361a4cb 100644 --- a/Tests/Constraints/DateTimeValidatorTest.php +++ b/Tests/Constraints/DateTimeValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\DateTime; use Symfony\Component\Validator\Constraints\DateTimeValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -58,9 +59,7 @@ public function testDateTimeWithDefaultFormat() ->assertRaised(); } - /** - * @dataProvider getValidDateTimes - */ + #[DataProvider('getValidDateTimes')] public function testValidDateTimes($format, $dateTime) { $constraint = new DateTime(format: $format); @@ -81,9 +80,7 @@ public static function getValidDateTimes() ]; } - /** - * @dataProvider getInvalidDateTimes - */ + #[DataProvider('getInvalidDateTimes')] public function testInvalidDateTimes($format, $dateTime, $code) { $constraint = new DateTime( diff --git a/Tests/Constraints/DateValidatorTest.php b/Tests/Constraints/DateValidatorTest.php index 65909ef83..4cc41eb2d 100644 --- a/Tests/Constraints/DateValidatorTest.php +++ b/Tests/Constraints/DateValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Date; use Symfony\Component\Validator\Constraints\DateValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -43,9 +44,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Date()); } - /** - * @dataProvider getValidDates - */ + #[DataProvider('getValidDates')] public function testValidDates($date) { $this->validator->validate($date, new Date()); @@ -53,9 +52,7 @@ public function testValidDates($date) $this->assertNoViolation(); } - /** - * @dataProvider getValidDates - */ + #[DataProvider('getValidDates')] public function testValidDatesWithNewLine(string $date) { $this->validator->validate($date."\n", new Date(message: 'myMessage')); @@ -75,9 +72,7 @@ public static function getValidDates() ]; } - /** - * @dataProvider getInvalidDates - */ + #[DataProvider('getInvalidDates')] public function testInvalidDates($date, $code) { $constraint = new Date(message: 'myMessage'); diff --git a/Tests/Constraints/DivisibleByValidatorTest.php b/Tests/Constraints/DivisibleByValidatorTest.php index be96ad2b4..a181cfa01 100644 --- a/Tests/Constraints/DivisibleByValidatorTest.php +++ b/Tests/Constraints/DivisibleByValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\DivisibleBy; use Symfony\Component\Validator\Constraints\DivisibleByValidator; @@ -90,9 +91,7 @@ public static function provideInvalidComparisons(): array ]; } - /** - * @dataProvider throwsOnNonNumericValuesProvider - */ + #[DataProvider('throwsOnNonNumericValuesProvider')] public function testThrowsOnNonNumericValues(string $expectedGivenType, $value, $comparedValue) { $this->expectException(UnexpectedValueException::class); diff --git a/Tests/Constraints/EmailValidatorTest.php b/Tests/Constraints/EmailValidatorTest.php index 483b534e6..47e90f077 100644 --- a/Tests/Constraints/EmailValidatorTest.php +++ b/Tests/Constraints/EmailValidatorTest.php @@ -11,14 +11,14 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Constraints\EmailValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; -/** - * @group dns-sensitive - */ +#[Group('dns-sensitive')] class EmailValidatorTest extends ConstraintValidatorTestCase { protected function createValidator(): EmailValidator @@ -60,9 +60,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Email()); } - /** - * @dataProvider getValidEmails - */ + #[DataProvider('getValidEmails')] public function testValidEmails($email) { $this->validator->validate($email, new Email()); @@ -70,9 +68,7 @@ public function testValidEmails($email) $this->assertNoViolation(); } - /** - * @dataProvider getValidEmails - */ + #[DataProvider('getValidEmails')] public function testValidEmailsWithNewLine($email) { $this->validator->validate($email."\n", new Email()); @@ -92,9 +88,7 @@ public static function getValidEmails() ]; } - /** - * @dataProvider getValidEmailsWithWhitespaces - */ + #[DataProvider('getValidEmailsWithWhitespaces')] public function testValidNormalizedEmails($email) { $this->validator->validate($email, new Email(normalizer: 'trim')); @@ -110,9 +104,7 @@ public static function getValidEmailsWithWhitespaces() ]; } - /** - * @dataProvider getValidEmailsHtml5 - */ + #[DataProvider('getValidEmailsHtml5')] public function testValidEmailsHtml5($email) { $this->validator->validate($email, new Email(mode: Email::VALIDATION_MODE_HTML5)); @@ -130,9 +122,7 @@ public static function getValidEmailsHtml5() ]; } - /** - * @dataProvider getInvalidEmails - */ + #[DataProvider('getInvalidEmails')] public function testInvalidEmails($email) { $constraint = new Email(message: 'myMessage'); @@ -155,9 +145,7 @@ public static function getInvalidEmails() ]; } - /** - * @dataProvider getInvalidHtml5Emails - */ + #[DataProvider('getInvalidHtml5Emails')] public function testInvalidHtml5Emails($email) { $constraint = new Email( @@ -195,9 +183,7 @@ public static function getInvalidHtml5Emails() ]; } - /** - * @dataProvider getInvalidAllowNoTldEmails - */ + #[DataProvider('getInvalidAllowNoTldEmails')] public function testInvalidAllowNoTldEmails($email) { $constraint = new Email( @@ -265,9 +251,7 @@ public function testUnknownModesOnValidateTriggerException() $this->validator->validate('example@example..com', $constraint); } - /** - * @dataProvider getInvalidEmailsForStrictChecks - */ + #[DataProvider('getInvalidEmailsForStrictChecks')] public function testStrictWithInvalidEmails($email) { $constraint = new Email( diff --git a/Tests/Constraints/ExpressionSyntaxTest.php b/Tests/Constraints/ExpressionSyntaxTest.php index 99875b9fd..56caa358e 100644 --- a/Tests/Constraints/ExpressionSyntaxTest.php +++ b/Tests/Constraints/ExpressionSyntaxTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; @@ -28,9 +29,7 @@ public function testValidatedByStandardValidator() self::assertSame(ExpressionSyntaxValidator::class, $constraint->validatedBy()); } - /** - * @dataProvider provideServiceValidatedConstraints - */ + #[DataProvider('provideServiceValidatedConstraints')] public function testValidatedByService(ExpressionSyntax $constraint) { self::assertSame('my_service', $constraint->validatedBy()); diff --git a/Tests/Constraints/ExpressionValidatorTest.php b/Tests/Constraints/ExpressionValidatorTest.php index 21c9eb630..8ac513e1b 100644 --- a/Tests/Constraints/ExpressionValidatorTest.php +++ b/Tests/Constraints/ExpressionValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\Validator\Constraints\Expression; use Symfony\Component\Validator\Constraints\ExpressionLanguageProvider; @@ -355,9 +356,7 @@ public function testIsValidExpressionInvalid() $this->assertCount(2, $this->context->getViolations()); } - /** - * @dataProvider provideCompileIsValid - */ + #[DataProvider('provideCompileIsValid')] public function testCompileIsValid(string $expression, array $names, string $expected) { $expressionLanguage = new ExpressionLanguage(); diff --git a/Tests/Constraints/FileTest.php b/Tests/Constraints/FileTest.php index 3e03f7881..bcf03517a 100644 --- a/Tests/Constraints/FileTest.php +++ b/Tests/Constraints/FileTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\File; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -20,9 +21,7 @@ class FileTest extends TestCase { - /** - * @dataProvider provideValidSizes - */ + #[DataProvider('provideValidSizes')] public function testMaxSize($maxSize, $bytes, $binaryFormat) { $file = new File(maxSize: $maxSize); @@ -41,9 +40,7 @@ public function testMagicIsset() $this->assertFalse($file->__isset('toto')); } - /** - * @dataProvider provideValidSizes - */ + #[DataProvider('provideValidSizes')] public function testMaxSizeCanBeSetAfterInitialization($maxSize, $bytes, $binaryFormat) { $file = new File(); @@ -53,9 +50,7 @@ public function testMaxSizeCanBeSetAfterInitialization($maxSize, $bytes, $binary $this->assertSame($binaryFormat, $file->binaryFormat); } - /** - * @dataProvider provideInvalidSizes - */ + #[DataProvider('provideInvalidSizes')] public function testInvalidValueForMaxSizeThrowsExceptionAfterInitialization($maxSize) { $file = new File(maxSize: 1000); @@ -65,9 +60,7 @@ public function testInvalidValueForMaxSizeThrowsExceptionAfterInitialization($ma $file->maxSize = $maxSize; } - /** - * @dataProvider provideInvalidSizes - */ + #[DataProvider('provideInvalidSizes')] public function testMaxSizeCannotBeSetToInvalidValueAfterInitialization($maxSize) { $file = new File(maxSize: 1000); @@ -105,9 +98,7 @@ public function testInvalidFilenameCountUnitThrowsException() $file = new File(filenameCountUnit: 'nonExistentCountUnit'); } - /** - * @dataProvider provideInValidSizes - */ + #[DataProvider('provideInValidSizes')] public function testInvalidMaxSize($maxSize) { $this->expectException(ConstraintDefinitionException::class); @@ -146,9 +137,7 @@ public static function provideInvalidSizes() ]; } - /** - * @dataProvider provideFormats - */ + #[DataProvider('provideFormats')] public function testBinaryFormat($maxSize, $guessedFormat, $binaryFormat) { $file = new File(maxSize: $maxSize, binaryFormat: $guessedFormat); diff --git a/Tests/Constraints/FileValidatorTestCase.php b/Tests/Constraints/FileValidatorTestCase.php index 53f7ad0b5..993570788 100644 --- a/Tests/Constraints/FileValidatorTestCase.php +++ b/Tests/Constraints/FileValidatorTestCase.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\HttpFoundation\File\UploadedFile; @@ -161,9 +162,7 @@ public static function provideMaxSizeExceededTests() ]; } - /** - * @dataProvider provideMaxSizeExceededTests - */ + #[DataProvider('provideMaxSizeExceededTests')] public function testMaxSizeExceeded($bytesWritten, $limit, $sizeAsString, $limitAsString, $suffix) { fseek($this->file, $bytesWritten - 1, \SEEK_SET); @@ -213,9 +212,7 @@ public static function provideMaxSizeNotExceededTests() ]; } - /** - * @dataProvider provideMaxSizeNotExceededTests - */ + #[DataProvider('provideMaxSizeNotExceededTests')] public function testMaxSizeNotExceeded($bytesWritten, $limit) { fseek($this->file, $bytesWritten - 1, \SEEK_SET); @@ -260,9 +257,7 @@ public static function provideBinaryFormatTests() ]; } - /** - * @dataProvider provideBinaryFormatTests - */ + #[DataProvider('provideBinaryFormatTests')] public function testBinaryFormat($bytesWritten, $limit, $binaryFormat, $sizeAsString, $limitAsString, $suffix) { fseek($this->file, $bytesWritten - 1, \SEEK_SET); @@ -469,9 +464,7 @@ public function testDisallowEmptyDoctrineStyle() ->assertRaised(); } - /** - * @dataProvider uploadedFileErrorProvider - */ + #[DataProvider('uploadedFileErrorProvider')] public function testUploadedFileError($error, $message, array $params = [], $maxSize = null) { $file = new UploadedFile(tempnam(sys_get_temp_dir(), 'file-validator-test-'), 'originalName', 'mime', $error); @@ -544,9 +537,7 @@ public function testNegativeMaxSize() $file->maxSize = -1; } - /** - * @dataProvider providerValidExtension - */ + #[DataProvider('providerValidExtension')] public function testExtensionValid(string $name) { $path = __DIR__.'/Fixtures/'.$name; @@ -573,9 +564,7 @@ public static function providerValidExtension(): iterable yield ['uppercased-extension.TXT']; } - /** - * @dataProvider provideInvalidExtension - */ + #[DataProvider('provideInvalidExtension')] public function testExtensionInvalid(string $name, string $extension) { $path = __DIR__.'/Fixtures/'.$name; @@ -672,9 +661,7 @@ public function testUploadedFileExtensions() $this->assertNoViolation(); } - /** - * @dataProvider provideFilenameMaxLengthIsTooLong - */ + #[DataProvider('provideFilenameMaxLengthIsTooLong')] public function testFilenameMaxLengthIsTooLong(File $constraintFile, string $filename, string $messageViolation) { file_put_contents($this->path, '1'); @@ -718,9 +705,7 @@ public static function provideFilenameMaxLengthIsTooLong(): \Generator ]; } - /** - * @dataProvider provideFilenameCountUnit - */ + #[DataProvider('provideFilenameCountUnit')] public function testValidCountUnitFilenameMaxLength(int $maxLength, string $countUnit) { file_put_contents($this->path, '1'); @@ -731,9 +716,7 @@ public function testValidCountUnitFilenameMaxLength(int $maxLength, string $coun $this->assertNoViolation(); } - /** - * @dataProvider provideFilenameCharset - */ + #[DataProvider('provideFilenameCharset')] public function testFilenameCharset(string $filename, string $charset, bool $isValid) { file_put_contents($this->path, '1'); diff --git a/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php b/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php index 4ce00abc2..7431f18ee 100644 --- a/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php +++ b/Tests/Constraints/GreaterThanOrEqualValidatorWithPositiveOrZeroConstraintTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraint; @@ -83,9 +84,7 @@ public function testThrowsConstraintExceptionIfValue() return new PositiveOrZero(['value' => 0]); } - /** - * @dataProvider provideInvalidConstraintOptions - */ + #[DataProvider('provideInvalidConstraintOptions')] public function testThrowsConstraintExceptionIfNoValueOrPropertyPath($options) { $this->markTestSkipped('Value option always set for PositiveOrZero constraint'); @@ -101,9 +100,7 @@ public function testInvalidValuePath() $this->markTestSkipped('PropertyPath option is not used in PositiveOrZero constraint'); } - /** - * @dataProvider provideValidComparisonsToPropertyPath - */ + #[DataProvider('provideValidComparisonsToPropertyPath')] public function testValidComparisonToPropertyPath($comparedValue) { $this->markTestSkipped('PropertyPath option is not used in PositiveOrZero constraint'); diff --git a/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php b/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php index 795a7ffdf..74062a164 100644 --- a/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php +++ b/Tests/Constraints/GreaterThanValidatorWithPositiveConstraintTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraint; @@ -80,9 +81,7 @@ public function testThrowsConstraintExceptionIfValue() return new Positive(['value' => 0]); } - /** - * @dataProvider provideInvalidConstraintOptions - */ + #[DataProvider('provideInvalidConstraintOptions')] public function testThrowsConstraintExceptionIfNoValueOrPropertyPath($options) { $this->markTestSkipped('Value option always set for Positive constraint.'); @@ -103,9 +102,7 @@ public function testInvalidValuePath() $this->markTestSkipped('PropertyPath option is not used in Positive constraint'); } - /** - * @dataProvider provideValidComparisonsToPropertyPath - */ + #[DataProvider('provideValidComparisonsToPropertyPath')] public function testValidComparisonToPropertyPath($comparedValue) { $this->markTestSkipped('PropertyPath option is not used in Positive constraint'); diff --git a/Tests/Constraints/HostnameValidatorTest.php b/Tests/Constraints/HostnameValidatorTest.php index 2471fe0b5..54544ed0a 100644 --- a/Tests/Constraints/HostnameValidatorTest.php +++ b/Tests/Constraints/HostnameValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Hostname; use Symfony\Component\Validator\Constraints\HostnameValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -42,9 +43,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Hostname()); } - /** - * @dataProvider getValidMultilevelDomains - */ + #[DataProvider('getValidMultilevelDomains')] public function testValidTldDomainsPassValidationIfTldRequired($domain) { $this->validator->validate($domain, new Hostname()); @@ -52,9 +51,7 @@ public function testValidTldDomainsPassValidationIfTldRequired($domain) $this->assertNoViolation(); } - /** - * @dataProvider getValidMultilevelDomains - */ + #[DataProvider('getValidMultilevelDomains')] public function testValidTldDomainsPassValidationIfTldNotRequired($domain) { $this->validator->validate($domain, new Hostname(requireTld: false)); @@ -76,9 +73,7 @@ public static function getValidMultilevelDomains() ]; } - /** - * @dataProvider getInvalidDomains - */ + #[DataProvider('getInvalidDomains')] public function testInvalidDomainsRaiseViolationIfTldRequired($domain) { $this->validator->validate($domain, new Hostname(message: 'myMessage')); @@ -89,9 +84,7 @@ public function testInvalidDomainsRaiseViolationIfTldRequired($domain) ->assertRaised(); } - /** - * @dataProvider getInvalidDomains - */ + #[DataProvider('getInvalidDomains')] public function testInvalidDomainsRaiseViolationIfTldNotRequired($domain) { $this->validator->validate($domain, new Hostname( @@ -116,9 +109,7 @@ public static function getInvalidDomains() ]; } - /** - * @dataProvider getReservedDomains - */ + #[DataProvider('getReservedDomains')] public function testReservedDomainsPassValidationIfTldNotRequired($domain) { $this->validator->validate($domain, new Hostname(requireTld: false)); @@ -126,9 +117,7 @@ public function testReservedDomainsPassValidationIfTldNotRequired($domain) $this->assertNoViolation(); } - /** - * @dataProvider getReservedDomains - */ + #[DataProvider('getReservedDomains')] public function testReservedDomainsRaiseViolationIfTldRequired($domain) { $this->validator->validate($domain, new Hostname( @@ -169,9 +158,7 @@ public function testReservedDomainsRaiseViolationIfTldRequiredNamed() ->assertRaised(); } - /** - * @dataProvider getTopLevelDomains - */ + #[DataProvider('getTopLevelDomains')] public function testTopLevelDomainsPassValidationIfTldNotRequired($domain) { $this->validator->validate($domain, new Hostname(requireTld: false)); @@ -179,9 +166,7 @@ public function testTopLevelDomainsPassValidationIfTldNotRequired($domain) $this->assertNoViolation(); } - /** - * @dataProvider getTopLevelDomains - */ + #[DataProvider('getTopLevelDomains')] public function testTopLevelDomainsRaiseViolationIfTldRequired($domain) { $this->validator->validate($domain, new Hostname( diff --git a/Tests/Constraints/IbanValidatorTest.php b/Tests/Constraints/IbanValidatorTest.php index 184924d5e..6a349bcaa 100644 --- a/Tests/Constraints/IbanValidatorTest.php +++ b/Tests/Constraints/IbanValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Iban; use Symfony\Component\Validator\Constraints\IbanValidator; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -38,9 +39,7 @@ public function testEmptyStringIsValid() $this->assertNoViolation(); } - /** - * @dataProvider getValidIbans - */ + #[DataProvider('getValidIbans')] public function testValidIbans($iban) { $this->validator->validate($iban, new Iban()); @@ -48,9 +47,7 @@ public function testValidIbans($iban) $this->assertNoViolation(); } - /** - * @dataProvider getValidIbans - */ + #[DataProvider('getValidIbans')] public function testValidIbansWithNewLine(string $iban) { $this->validator->validate($iban."\n", new Iban()); @@ -193,9 +190,7 @@ public static function getValidIbans() ]; } - /** - * @dataProvider getIbansWithInvalidFormat - */ + #[DataProvider('getIbansWithInvalidFormat')] public function testIbansWithInvalidFormat($iban) { $this->assertViolationRaised($iban, Iban::INVALID_FORMAT_ERROR); @@ -312,9 +307,7 @@ public static function getIbansWithInvalidFormat() ]; } - /** - * @dataProvider getIbansWithValidFormatButIncorrectChecksum - */ + #[DataProvider('getIbansWithValidFormatButIncorrectChecksum')] public function testIbansWithValidFormatButIncorrectChecksum($iban) { $this->assertViolationRaised($iban, Iban::CHECKSUM_FAILED_ERROR); @@ -430,9 +423,7 @@ public static function getIbansWithValidFormatButIncorrectChecksum() ]; } - /** - * @dataProvider getUnsupportedCountryCodes - */ + #[DataProvider('getUnsupportedCountryCodes')] public function testIbansWithUnsupportedCountryCode($countryCode) { $this->assertViolationRaised($countryCode.'260211000000230064016', Iban::NOT_SUPPORTED_COUNTRY_CODE_ERROR); @@ -454,9 +445,7 @@ public function testIbansWithInvalidCharacters() $this->assertViolationRaised('CH930076201162385295]', Iban::INVALID_CHARACTERS_ERROR); } - /** - * @dataProvider getIbansWithInvalidCountryCode - */ + #[DataProvider('getIbansWithInvalidCountryCode')] public function testIbansWithInvalidCountryCode($iban) { $this->assertViolationRaised($iban, Iban::INVALID_COUNTRY_CODE_ERROR); diff --git a/Tests/Constraints/ImageValidatorTest.php b/Tests/Constraints/ImageValidatorTest.php index 8c556b48f..18956036e 100644 --- a/Tests/Constraints/ImageValidatorTest.php +++ b/Tests/Constraints/ImageValidatorTest.php @@ -11,8 +11,10 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\Mime\MimeTypes; use Symfony\Component\Validator\Constraints\Image; @@ -20,10 +22,9 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** - * @requires extension fileinfo - * * @extends ConstraintValidatorTestCase */ +#[RequiresPhpExtension('fileinfo')] class ImageValidatorTest extends ConstraintValidatorTestCase { protected string $path; @@ -544,7 +545,7 @@ public function testInvalidMimeTypeWithNarrowedSetDoctrineStyle() ->assertRaised(); } - /** @dataProvider provideSvgWithViolation */ + #[DataProvider('provideSvgWithViolation')] public function testSvgWithViolation(string $image, Image $constraint, string $violation, array $parameters = []) { $this->validator->validate($image, $constraint); @@ -644,7 +645,7 @@ public static function provideSvgWithViolation(): iterable ]; } - /** @dataProvider provideSvgWithoutViolation */ + #[DataProvider('provideSvgWithoutViolation')] public function testSvgWithoutViolation(string $image, Image $constraint) { $this->validator->validate($image, $constraint); @@ -680,9 +681,7 @@ public static function provideSvgWithoutViolation(): iterable ]; } - /** - * @dataProvider providerValidExtension - */ + #[DataProvider('providerValidExtension')] public function testExtensionValid(string $name) { if (!class_exists(MimeTypes::class)) { @@ -702,9 +701,7 @@ public static function providerValidExtension(): iterable yield ['test.png.gif']; } - /** - * @dataProvider provideInvalidExtension - */ + #[DataProvider('provideInvalidExtension')] public function testExtensionInvalid(string $name, string $extension) { $path = __DIR__.'/Fixtures/'.$name; diff --git a/Tests/Constraints/InvalidComparisonToValueTestTrait.php b/Tests/Constraints/InvalidComparisonToValueTestTrait.php index 5b261d504..0f833edf4 100644 --- a/Tests/Constraints/InvalidComparisonToValueTestTrait.php +++ b/Tests/Constraints/InvalidComparisonToValueTestTrait.php @@ -11,13 +11,12 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Intl\Util\IntlTestHelper; trait InvalidComparisonToValueTestTrait { - /** - * @dataProvider provideAllInvalidComparisons - */ + #[DataProvider('provideAllInvalidComparisons')] public function testInvalidComparisonToValue($dirtyValue, $dirtyValueAsString, $comparedValue, $comparedValueString, $comparedValueType) { // Conversion of dates to string differs between ICU versions diff --git a/Tests/Constraints/IpValidatorTest.php b/Tests/Constraints/IpValidatorTest.php index e37d61bb6..e839dce84 100644 --- a/Tests/Constraints/IpValidatorTest.php +++ b/Tests/Constraints/IpValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Ip; use Symfony\Component\Validator\Constraints\IpValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -50,9 +51,7 @@ public function testInvalidValidatorVersion() new Ip(version: 666); } - /** - * @dataProvider getValidIpsV4 - */ + #[DataProvider('getValidIpsV4')] public function testValidIpsV4($ip) { $this->validator->validate($ip, new Ip(version: Ip::V4)); @@ -74,9 +73,7 @@ public static function getValidIpsV4() ]; } - /** - * @dataProvider getValidIpsV4WithWhitespaces - */ + #[DataProvider('getValidIpsV4WithWhitespaces')] public function testValidIpsV4WithWhitespaces($ip) { $this->validator->validate($ip, new Ip( @@ -109,9 +106,7 @@ public static function getValidIpsV4WithWhitespaces() ]; } - /** - * @dataProvider getValidIpsV6 - */ + #[DataProvider('getValidIpsV6')] public function testValidIpsV6($ip) { $this->validator->validate($ip, new Ip(version: Ip::V6)); @@ -144,9 +139,7 @@ public static function getValidIpsV6() ]; } - /** - * @dataProvider getValidIpsAll - */ + #[DataProvider('getValidIpsAll')] public function testValidIpsAll($ip) { $this->validator->validate($ip, new Ip(version: Ip::ALL)); @@ -159,9 +152,7 @@ public static function getValidIpsAll() return array_merge(self::getValidIpsV4(), self::getValidIpsV6()); } - /** - * @dataProvider getInvalidIpsV4 - */ + #[DataProvider('getInvalidIpsV4')] public function testInvalidIpsV4($ip) { $constraint = new Ip( @@ -177,9 +168,7 @@ public function testInvalidIpsV4($ip) ->assertRaised(); } - /** - * @dataProvider getValidPublicIpsV4 - */ + #[DataProvider('getValidPublicIpsV4')] public function testInvalidNoPublicIpsV4($ip) { $constraint = new Ip( @@ -219,9 +208,7 @@ public static function getInvalidIpsV4() ]; } - /** - * @dataProvider getValidPrivateIpsV4 - */ + #[DataProvider('getValidPrivateIpsV4')] public function testValidPrivateIpsV4($ip) { $this->validator->validate($ip, new Ip(version: Ip::V4_ONLY_PRIVATE)); @@ -229,9 +216,7 @@ public function testValidPrivateIpsV4($ip) $this->assertNoViolation(); } - /** - * @dataProvider getValidPrivateIpsV4 - */ + #[DataProvider('getValidPrivateIpsV4')] public function testInvalidPrivateIpsV4($ip) { $constraint = new Ip( @@ -247,9 +232,7 @@ public function testInvalidPrivateIpsV4($ip) ->assertRaised(); } - /** - * @dataProvider getInvalidPrivateIpsV4 - */ + #[DataProvider('getInvalidPrivateIpsV4')] public function testInvalidOnlyPrivateIpsV4($ip) { $constraint = new Ip( @@ -279,9 +262,7 @@ public static function getInvalidPrivateIpsV4() return array_merge(self::getValidPublicIpsV4(), self::getValidReservedIpsV4()); } - /** - * @dataProvider getValidReservedIpsV4 - */ + #[DataProvider('getValidReservedIpsV4')] public function testValidReservedIpsV4($ip) { $this->validator->validate($ip, new Ip(version: Ip::V4_ONLY_RESERVED)); @@ -289,9 +270,7 @@ public function testValidReservedIpsV4($ip) $this->assertNoViolation(); } - /** - * @dataProvider getValidReservedIpsV4 - */ + #[DataProvider('getValidReservedIpsV4')] public function testInvalidReservedIpsV4($ip) { $constraint = new Ip( @@ -307,9 +286,7 @@ public function testInvalidReservedIpsV4($ip) ->assertRaised(); } - /** - * @dataProvider getInvalidReservedIpsV4 - */ + #[DataProvider('getInvalidReservedIpsV4')] public function testInvalidOnlyReservedIpsV4($ip) { $constraint = new Ip( @@ -339,9 +316,7 @@ public static function getInvalidReservedIpsV4() return array_merge(self::getValidPublicIpsV4(), self::getValidPrivateIpsV4()); } - /** - * @dataProvider getInvalidPublicIpsV4 - */ + #[DataProvider('getInvalidPublicIpsV4')] public function testInvalidPublicIpsV4($ip) { $constraint = new Ip( @@ -362,9 +337,7 @@ public static function getInvalidPublicIpsV4() return array_merge(self::getValidPrivateIpsV4(), self::getValidReservedIpsV4()); } - /** - * @dataProvider getInvalidIpsV6 - */ + #[DataProvider('getInvalidIpsV6')] public function testInvalidIpsV6($ip) { $constraint = new Ip( @@ -399,9 +372,7 @@ public static function getInvalidIpsV6() ]; } - /** - * @dataProvider getInvalidPrivateIpsV6 - */ + #[DataProvider('getInvalidPrivateIpsV6')] public function testInvalidPrivateIpsV6($ip) { $constraint = new Ip( @@ -426,9 +397,7 @@ public static function getInvalidPrivateIpsV6() ]; } - /** - * @dataProvider getInvalidReservedIpsV6 - */ + #[DataProvider('getInvalidReservedIpsV6')] public function testInvalidReservedIpsV6($ip) { $constraint = new Ip( @@ -452,9 +421,7 @@ public static function getInvalidReservedIpsV6() return self::getInvalidIpsV6(); } - /** - * @dataProvider getInvalidPublicIpsV6 - */ + #[DataProvider('getInvalidPublicIpsV6')] public function testInvalidPublicIpsV6($ip) { $constraint = new Ip( @@ -475,9 +442,7 @@ public static function getInvalidPublicIpsV6() return array_merge(self::getInvalidPrivateIpsV6(), self::getInvalidReservedIpsV6()); } - /** - * @dataProvider getInvalidIpsAll - */ + #[DataProvider('getInvalidIpsAll')] public function testInvalidIpsAll($ip) { $constraint = new Ip( @@ -498,9 +463,7 @@ public static function getInvalidIpsAll() return array_merge(self::getInvalidIpsV4(), self::getInvalidIpsV6()); } - /** - * @dataProvider getInvalidPrivateIpsAll - */ + #[DataProvider('getInvalidPrivateIpsAll')] public function testInvalidPrivateIpsAll($ip) { $constraint = new Ip( @@ -521,9 +484,7 @@ public static function getInvalidPrivateIpsAll() return array_merge(self::getValidPrivateIpsV4(), self::getInvalidPrivateIpsV6()); } - /** - * @dataProvider getInvalidReservedIpsAll - */ + #[DataProvider('getInvalidReservedIpsAll')] public function testInvalidReservedIpsAll($ip) { $constraint = new Ip( @@ -544,9 +505,7 @@ public static function getInvalidReservedIpsAll() return array_merge(self::getValidReservedIpsV4(), self::getInvalidReservedIpsV6()); } - /** - * @dataProvider getInvalidPublicIpsAll - */ + #[DataProvider('getInvalidPublicIpsAll')] public function testInvalidPublicIpsAll($ip) { $constraint = new Ip( diff --git a/Tests/Constraints/IsNullValidatorTest.php b/Tests/Constraints/IsNullValidatorTest.php index ed6beffc4..556f9aed0 100644 --- a/Tests/Constraints/IsNullValidatorTest.php +++ b/Tests/Constraints/IsNullValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\IsNull; use Symfony\Component\Validator\Constraints\IsNullValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -29,9 +30,7 @@ public function testNullIsValid() $this->assertNoViolation(); } - /** - * @dataProvider getInvalidValues - */ + #[DataProvider('getInvalidValues')] public function testInvalidValues($value, $valueAsString) { $constraint = new IsNull(message: 'myMessage'); @@ -44,9 +43,7 @@ public function testInvalidValues($value, $valueAsString) ->assertRaised(); } - /** - * @dataProvider getInvalidValues - */ + #[DataProvider('getInvalidValues')] public function testInvalidValuesNamed($value, $valueAsString) { $constraint = new IsNull(message: 'myMessage'); diff --git a/Tests/Constraints/IsbnValidatorTest.php b/Tests/Constraints/IsbnValidatorTest.php index 82a60b894..737d9de0c 100644 --- a/Tests/Constraints/IsbnValidatorTest.php +++ b/Tests/Constraints/IsbnValidatorTest.php @@ -148,9 +148,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), $constraint); } - /** - * @dataProvider getValidIsbn10 - */ + #[DataProvider('getValidIsbn10')] public function testValidIsbn10($isbn) { $constraint = new Isbn(type: 'isbn10'); @@ -191,9 +189,7 @@ public function testInvalidIsbn10Named() ->assertRaised(); } - /** - * @dataProvider getValidIsbn13 - */ + #[DataProvider('getValidIsbn13')] public function testValidIsbn13($isbn) { $constraint = new Isbn(type: 'isbn13'); @@ -221,9 +217,7 @@ public function testInvalidIsbn13($isbn, $code) ->assertRaised(); } - /** - * @dataProvider getInvalidIsbn13 - */ + #[DataProvider('getInvalidIsbn13')] public function testInvalidIsbn13Named($isbn, $code) { $constraint = new Isbn( @@ -239,9 +233,7 @@ public function testInvalidIsbn13Named($isbn, $code) ->assertRaised(); } - /** - * @dataProvider getValidIsbn - */ + #[DataProvider('getValidIsbn')] public function testValidIsbnAny($isbn) { $constraint = new Isbn(); @@ -251,9 +243,7 @@ public function testValidIsbnAny($isbn) $this->assertNoViolation(); } - /** - * @dataProvider getInvalidIsbn10 - */ + #[DataProvider('getInvalidIsbn10')] public function testInvalidIsbnAnyIsbn10($isbn, $code) { $constraint = new Isbn(bothIsbnMessage: 'myMessage'); @@ -271,9 +261,7 @@ public function testInvalidIsbnAnyIsbn10($isbn, $code) ->assertRaised(); } - /** - * @dataProvider getInvalidIsbn13 - */ + #[DataProvider('getInvalidIsbn13')] public function testInvalidIsbnAnyIsbn13($isbn, $code) { $constraint = new Isbn(bothIsbnMessage: 'myMessage'); diff --git a/Tests/Constraints/IsinValidatorTest.php b/Tests/Constraints/IsinValidatorTest.php index b1ac3be20..3ba01a960 100644 --- a/Tests/Constraints/IsinValidatorTest.php +++ b/Tests/Constraints/IsinValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Isin; use Symfony\Component\Validator\Constraints\IsinValidator; use Symfony\Component\Validator\Constraints\Luhn; @@ -37,9 +38,7 @@ public function testEmptyStringIsValid() $this->assertNoViolation(); } - /** - * @dataProvider getValidIsin - */ + #[DataProvider('getValidIsin')] public function testValidIsin($isin) { $this->validator->validate($isin, new Isin()); @@ -63,9 +62,7 @@ public static function getValidIsin() ]; } - /** - * @dataProvider getIsinWithInvalidLenghFormat - */ + #[DataProvider('getIsinWithInvalidLenghFormat')] public function testIsinWithInvalidFormat($isin) { $this->assertViolationRaised($isin, Isin::INVALID_LENGTH_ERROR); @@ -88,9 +85,7 @@ public static function getIsinWithInvalidLenghFormat() ]; } - /** - * @dataProvider getIsinWithInvalidPattern - */ + #[DataProvider('getIsinWithInvalidPattern')] public function testIsinWithInvalidPattern($isin) { $this->assertViolationRaised($isin, Isin::INVALID_PATTERN_ERROR); @@ -106,9 +101,7 @@ public static function getIsinWithInvalidPattern() ]; } - /** - * @dataProvider getIsinWithValidFormatButIncorrectChecksum - */ + #[DataProvider('getIsinWithValidFormatButIncorrectChecksum')] public function testIsinWithValidFormatButIncorrectChecksum($isin) { $this->expectViolationsAt(0, $isin, new Luhn()); diff --git a/Tests/Constraints/IssnValidatorTest.php b/Tests/Constraints/IssnValidatorTest.php index 6351ab620..bd5844e1e 100644 --- a/Tests/Constraints/IssnValidatorTest.php +++ b/Tests/Constraints/IssnValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Issn; use Symfony\Component\Validator\Constraints\IssnValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -114,9 +115,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), $constraint); } - /** - * @dataProvider getValidLowerCasedIssn - */ + #[DataProvider('getValidLowerCasedIssn')] public function testCaseSensitiveIssns($issn) { $constraint = new Issn( @@ -132,9 +131,7 @@ public function testCaseSensitiveIssns($issn) ->assertRaised(); } - /** - * @dataProvider getValidNonHyphenatedIssn - */ + #[DataProvider('getValidNonHyphenatedIssn')] public function testRequireHyphenIssns($issn) { $constraint = new Issn( @@ -150,9 +147,7 @@ public function testRequireHyphenIssns($issn) ->assertRaised(); } - /** - * @dataProvider getValidIssn - */ + #[DataProvider('getValidIssn')] public function testValidIssn($issn) { $constraint = new Issn(); @@ -162,9 +157,7 @@ public function testValidIssn($issn) $this->assertNoViolation(); } - /** - * @dataProvider getInvalidIssn - */ + #[DataProvider('getInvalidIssn')] public function testInvalidIssn($issn, $code) { $constraint = new Issn(message: 'myMessage'); diff --git a/Tests/Constraints/JsonValidatorTest.php b/Tests/Constraints/JsonValidatorTest.php index 123cb95fe..50d30c5a3 100644 --- a/Tests/Constraints/JsonValidatorTest.php +++ b/Tests/Constraints/JsonValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Json; use Symfony\Component\Validator\Constraints\JsonValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -22,9 +23,7 @@ protected function createValidator(): JsonValidator return new JsonValidator(); } - /** - * @dataProvider getValidValues - */ + #[DataProvider('getValidValues')] public function testJsonIsValid($value) { $this->validator->validate($value, new Json()); @@ -32,9 +31,7 @@ public function testJsonIsValid($value) $this->assertNoViolation(); } - /** - * @dataProvider getInvalidValues - */ + #[DataProvider('getInvalidValues')] public function testInvalidValues($value) { $constraint = new Json(message: 'myMessageTest'); diff --git a/Tests/Constraints/LanguageValidatorTest.php b/Tests/Constraints/LanguageValidatorTest.php index d7c01a478..ca18619d0 100644 --- a/Tests/Constraints/LanguageValidatorTest.php +++ b/Tests/Constraints/LanguageValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Intl\Util\IntlTestHelper; use Symfony\Component\Validator\Constraints\Language; use Symfony\Component\Validator\Constraints\LanguageValidator; @@ -60,9 +61,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Language()); } - /** - * @dataProvider getValidLanguages - */ + #[DataProvider('getValidLanguages')] public function testValidLanguages($language) { $this->validator->validate($language, new Language()); @@ -78,9 +77,7 @@ public static function getValidLanguages() ]; } - /** - * @dataProvider getInvalidLanguages - */ + #[DataProvider('getInvalidLanguages')] public function testInvalidLanguages($language) { $constraint = new Language(message: 'myMessage'); @@ -101,9 +98,7 @@ public static function getInvalidLanguages() ]; } - /** - * @dataProvider getValidAlpha3Languages - */ + #[DataProvider('getValidAlpha3Languages')] public function testValidAlpha3Languages($language) { $this->validator->validate($language, new Language(alpha3: true)); @@ -120,9 +115,7 @@ public static function getValidAlpha3Languages() ]; } - /** - * @dataProvider getInvalidAlpha3Languages - */ + #[DataProvider('getInvalidAlpha3Languages')] public function testInvalidAlpha3Languages($language) { $constraint = new Language( diff --git a/Tests/Constraints/LengthValidatorTest.php b/Tests/Constraints/LengthValidatorTest.php index 81351ffb2..86f90a69c 100644 --- a/Tests/Constraints/LengthValidatorTest.php +++ b/Tests/Constraints/LengthValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\LengthValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -115,9 +116,7 @@ public static function getThreeCharactersWithWhitespaces() ]; } - /** - * @dataProvider getFiveOrMoreCharacters - */ + #[DataProvider('getFiveOrMoreCharacters')] public function testValidValuesMin(int|string $value) { $constraint = new Length(min: 5); @@ -126,9 +125,7 @@ public function testValidValuesMin(int|string $value) $this->assertNoViolation(); } - /** - * @dataProvider getThreeOrLessCharacters - */ + #[DataProvider('getThreeOrLessCharacters')] public function testValidValuesMax(int|string $value) { $constraint = new Length(max: 3); @@ -137,9 +134,7 @@ public function testValidValuesMax(int|string $value) $this->assertNoViolation(); } - /** - * @dataProvider getFourCharacters - */ + #[DataProvider('getFourCharacters')] public function testValidValuesExact(int|string $value) { $constraint = new Length(4); @@ -148,9 +143,7 @@ public function testValidValuesExact(int|string $value) $this->assertNoViolation(); } - /** - * @dataProvider getThreeCharactersWithWhitespaces - */ + #[DataProvider('getThreeCharactersWithWhitespaces')] public function testValidNormalizedValues($value) { $constraint = new Length(min: 3, max: 3, normalizer: 'trim'); @@ -183,9 +176,7 @@ public function testValidBytesValues() $this->assertNoViolation(); } - /** - * @dataProvider getThreeOrLessCharacters - */ + #[DataProvider('getThreeOrLessCharacters')] public function testInvalidValuesMin(int|string $value, int $valueLength) { $constraint = new Length( @@ -206,9 +197,7 @@ public function testInvalidValuesMin(int|string $value, int $valueLength) ->assertRaised(); } - /** - * @dataProvider getThreeOrLessCharacters - */ + #[DataProvider('getThreeOrLessCharacters')] public function testInvalidValuesMinNamed(int|string $value, int $valueLength) { $constraint = new Length(min: 4, minMessage: 'myMessage'); @@ -226,9 +215,7 @@ public function testInvalidValuesMinNamed(int|string $value, int $valueLength) ->assertRaised(); } - /** - * @dataProvider getFiveOrMoreCharacters - */ + #[DataProvider('getFiveOrMoreCharacters')] public function testInvalidValuesMax(int|string $value, int $valueLength) { $constraint = new Length( @@ -249,9 +236,7 @@ public function testInvalidValuesMax(int|string $value, int $valueLength) ->assertRaised(); } - /** - * @dataProvider getFiveOrMoreCharacters - */ + #[DataProvider('getFiveOrMoreCharacters')] public function testInvalidValuesMaxNamed(int|string $value, int $valueLength) { $constraint = new Length(max: 4, maxMessage: 'myMessage'); @@ -269,9 +254,7 @@ public function testInvalidValuesMaxNamed(int|string $value, int $valueLength) ->assertRaised(); } - /** - * @dataProvider getThreeOrLessCharacters - */ + #[DataProvider('getThreeOrLessCharacters')] public function testInvalidValuesExactLessThanFour(int|string $value, int $valueLength) { $constraint = new Length( @@ -294,9 +277,7 @@ public function testInvalidValuesExactLessThanFour(int|string $value, int $value ->assertRaised(); } - /** - * @dataProvider getThreeOrLessCharacters - */ + #[DataProvider('getThreeOrLessCharacters')] public function testInvalidValuesExactLessThanFourNamed(int|string $value, int $valueLength) { $constraint = new Length(exactly: 4, exactMessage: 'myMessage'); @@ -315,9 +296,7 @@ public function testInvalidValuesExactLessThanFourNamed(int|string $value, int $ ->assertRaised(); } - /** - * @dataProvider getFiveOrMoreCharacters - */ + #[DataProvider('getFiveOrMoreCharacters')] public function testInvalidValuesExactMoreThanFour(int|string $value, int $valueLength) { $constraint = new Length( @@ -340,9 +319,7 @@ public function testInvalidValuesExactMoreThanFour(int|string $value, int $value ->assertRaised(); } - /** - * @dataProvider getOneCharset - */ + #[DataProvider('getOneCharset')] public function testOneCharset($value, $charset, $isValid) { $constraint = new Length( diff --git a/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php b/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php index 61fc7ac9a..318a33df3 100644 --- a/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php +++ b/Tests/Constraints/LessThanOrEqualValidatorWithNegativeOrZeroConstraintTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraint; @@ -81,9 +82,7 @@ public function testThrowsConstraintExceptionIfValue() return new NegativeOrZero(['value' => 0]); } - /** - * @dataProvider provideInvalidConstraintOptions - */ + #[DataProvider('provideInvalidConstraintOptions')] public function testThrowsConstraintExceptionIfNoValueOrPropertyPath($options) { $this->markTestSkipped('Value option always set for NegativeOrZero constraint'); @@ -104,9 +103,7 @@ public function testInvalidValuePath() $this->markTestSkipped('PropertyPath option is not used in NegativeOrZero constraint'); } - /** - * @dataProvider provideValidComparisonsToPropertyPath - */ + #[DataProvider('provideValidComparisonsToPropertyPath')] public function testValidComparisonToPropertyPath($comparedValue) { $this->markTestSkipped('PropertyPath option is not used in NegativeOrZero constraint'); diff --git a/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php b/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php index 0b40a19c1..5bb0629f8 100644 --- a/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php +++ b/Tests/Constraints/LessThanValidatorWithNegativeConstraintTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraint; @@ -80,9 +81,7 @@ public function testThrowsConstraintExceptionIfValue() return new Negative(['value' => 0]); } - /** - * @dataProvider provideInvalidConstraintOptions - */ + #[DataProvider('provideInvalidConstraintOptions')] public function testThrowsConstraintExceptionIfNoValueOrPropertyPath($options) { $this->markTestSkipped('Value option always set for Negative constraint'); @@ -103,9 +102,7 @@ public function testInvalidValuePath() $this->markTestSkipped('PropertyPath option is not used in Negative constraint'); } - /** - * @dataProvider provideValidComparisonsToPropertyPath - */ + #[DataProvider('provideValidComparisonsToPropertyPath')] public function testValidComparisonToPropertyPath($comparedValue) { $this->markTestSkipped('PropertyPath option is not used in Negative constraint'); diff --git a/Tests/Constraints/LocaleValidatorTest.php b/Tests/Constraints/LocaleValidatorTest.php index 3b3819512..56253d3ac 100644 --- a/Tests/Constraints/LocaleValidatorTest.php +++ b/Tests/Constraints/LocaleValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Locale; use Symfony\Component\Validator\Constraints\LocaleValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -43,9 +44,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Locale()); } - /** - * @dataProvider getValidLocales - */ + #[DataProvider('getValidLocales')] public function testValidLocales($locale) { $this->validator->validate($locale, new Locale()); @@ -66,9 +65,7 @@ public static function getValidLocales() ]; } - /** - * @dataProvider getInvalidLocales - */ + #[DataProvider('getInvalidLocales')] public function testInvalidLocales($locale) { $constraint = new Locale(message: 'myMessage'); @@ -102,9 +99,7 @@ public function testTooLongLocale() ->assertRaised(); } - /** - * @dataProvider getUncanonicalizedLocales - */ + #[DataProvider('getUncanonicalizedLocales')] public function testValidLocalesWithCanonicalization(string $locale) { $constraint = new Locale(message: 'myMessage'); @@ -114,9 +109,7 @@ public function testValidLocalesWithCanonicalization(string $locale) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocales - */ + #[DataProvider('getValidLocales')] public function testValidLocalesWithoutCanonicalization(string $locale) { $constraint = new Locale( @@ -129,9 +122,7 @@ public function testValidLocalesWithoutCanonicalization(string $locale) $this->assertNoViolation(); } - /** - * @dataProvider getUncanonicalizedLocales - */ + #[DataProvider('getUncanonicalizedLocales')] public function testInvalidLocalesWithoutCanonicalization(string $locale) { $constraint = new Locale( diff --git a/Tests/Constraints/LuhnValidatorTest.php b/Tests/Constraints/LuhnValidatorTest.php index 9eb33bde6..1f946c22d 100644 --- a/Tests/Constraints/LuhnValidatorTest.php +++ b/Tests/Constraints/LuhnValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Luhn; use Symfony\Component\Validator\Constraints\LuhnValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -37,9 +38,7 @@ public function testEmptyStringIsValid() $this->assertNoViolation(); } - /** - * @dataProvider getValidNumbers - */ + #[DataProvider('getValidNumbers')] public function testValidNumbers($number) { $this->validator->validate($number, new Luhn()); @@ -71,9 +70,7 @@ public static function getValidNumbers() ]; } - /** - * @dataProvider getInvalidNumbers - */ + #[DataProvider('getInvalidNumbers')] public function testInvalidNumbers($number, $code) { $constraint = new Luhn(message: 'myMessage'); @@ -97,9 +94,7 @@ public static function getInvalidNumbers() ]; } - /** - * @dataProvider getInvalidTypes - */ + #[DataProvider('getInvalidTypes')] public function testInvalidTypes($number) { $this->expectException(UnexpectedValueException::class); diff --git a/Tests/Constraints/MacAddressValidatorTest.php b/Tests/Constraints/MacAddressValidatorTest.php index 5abb7487b..84ff05cb6 100644 --- a/Tests/Constraints/MacAddressValidatorTest.php +++ b/Tests/Constraints/MacAddressValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\MacAddress; use Symfony\Component\Validator\Constraints\MacAddressValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -53,9 +54,7 @@ public function testInvalidValidatorType() new MacAddress(type: 666); } - /** - * @dataProvider getValidMacs - */ + #[DataProvider('getValidMacs')] public function testValidMac($mac) { $this->validator->validate($mac, new MacAddress()); @@ -63,9 +62,7 @@ public function testValidMac($mac) $this->assertNoViolation(); } - /** - * @dataProvider getNotValidMacs - */ + #[DataProvider('getNotValidMacs')] public function testNotValidMac($mac) { $this->validator->validate($mac, new MacAddress()); @@ -153,12 +150,10 @@ public static function getValidBroadcastMacs(): array ]; } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidLocalMulticastMacs - * @dataProvider getValidUniversalUnicastMacs - * @dataProvider getValidUniversalMulticastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidLocalMulticastMacs')] + #[DataProvider('getValidUniversalUnicastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] public function testValidAllNoBroadcastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::ALL_NO_BROADCAST)); @@ -166,9 +161,7 @@ public function testValidAllNoBroadcastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidBroadcastMacs - */ + #[DataProvider('getValidBroadcastMacs')] public function testInvalidAllNoBroadcastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::ALL_NO_BROADCAST); @@ -181,11 +174,9 @@ public function testInvalidAllNoBroadcastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidLocalMulticastMacs - * @dataProvider getValidBroadcastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidLocalMulticastMacs')] + #[DataProvider('getValidBroadcastMacs')] public function testValidLocalMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::LOCAL_ALL)); @@ -193,10 +184,8 @@ public function testValidLocalMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidUniversalUnicastMacs - * @dataProvider getValidUniversalMulticastMacs - */ + #[DataProvider('getValidUniversalUnicastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] public function testInvalidLocalMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::LOCAL_ALL); @@ -209,10 +198,8 @@ public function testInvalidLocalMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidLocalMulticastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidLocalMulticastMacs')] public function testValidLocalNoBroadcastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::LOCAL_NO_BROADCAST)); @@ -220,11 +207,9 @@ public function testValidLocalNoBroadcastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidUniversalUnicastMacs - * @dataProvider getValidUniversalMulticastMacs - * @dataProvider getValidBroadcastMacs - */ + #[DataProvider('getValidUniversalUnicastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] + #[DataProvider('getValidBroadcastMacs')] public function testInvalidLocalNoBroadcastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::LOCAL_NO_BROADCAST); @@ -237,9 +222,7 @@ public function testInvalidLocalNoBroadcastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidLocalUnicastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] public function testValidLocalUnicastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::LOCAL_UNICAST)); @@ -247,11 +230,9 @@ public function testValidLocalUnicastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocalMulticastMacs - * @dataProvider getValidUniversalUnicastMacs - * @dataProvider getValidUniversalMulticastMacs - */ + #[DataProvider('getValidLocalMulticastMacs')] + #[DataProvider('getValidUniversalUnicastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] public function testInvalidLocalUnicastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::LOCAL_UNICAST); @@ -264,10 +245,8 @@ public function testInvalidLocalUnicastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidLocalMulticastMacs - * @dataProvider getValidBroadcastMacs - */ + #[DataProvider('getValidLocalMulticastMacs')] + #[DataProvider('getValidBroadcastMacs')] public function testValidLocalMulticastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::LOCAL_MULTICAST)); @@ -275,11 +254,9 @@ public function testValidLocalMulticastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidUniversalUnicastMacs - * @dataProvider getValidUniversalMulticastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidUniversalUnicastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] public function testInvalidLocalMulticastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::LOCAL_MULTICAST); @@ -292,9 +269,7 @@ public function testInvalidLocalMulticastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidLocalMulticastMacs - */ + #[DataProvider('getValidLocalMulticastMacs')] public function testValidLocalMulticastNoBroadcastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::LOCAL_MULTICAST_NO_BROADCAST)); @@ -302,12 +277,10 @@ public function testValidLocalMulticastNoBroadcastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidUniversalUnicastMacs - * @dataProvider getValidUniversalMulticastMacs - * @dataProvider getValidBroadcastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidUniversalUnicastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] + #[DataProvider('getValidBroadcastMacs')] public function testInvalidLocalMulticastNoBroadcastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::LOCAL_MULTICAST_NO_BROADCAST); @@ -320,10 +293,8 @@ public function testInvalidLocalMulticastNoBroadcastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidUniversalUnicastMacs - * @dataProvider getValidUniversalMulticastMacs - */ + #[DataProvider('getValidUniversalUnicastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] public function testValidUniversalMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::UNIVERSAL_ALL)); @@ -331,10 +302,8 @@ public function testValidUniversalMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidLocalMulticastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidLocalMulticastMacs')] public function testInvalidUniversalMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::UNIVERSAL_ALL); @@ -347,9 +316,7 @@ public function testInvalidUniversalMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidUniversalUnicastMacs - */ + #[DataProvider('getValidUniversalUnicastMacs')] public function testValidUniversalUnicastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::UNIVERSAL_UNICAST)); @@ -357,11 +324,9 @@ public function testValidUniversalUnicastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidLocalMulticastMacs - * @dataProvider getValidUniversalMulticastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidLocalMulticastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] public function testInvalidUniversalUnicastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::UNIVERSAL_UNICAST); @@ -374,9 +339,7 @@ public function testInvalidUniversalUnicastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidUniversalMulticastMacs - */ + #[DataProvider('getValidUniversalMulticastMacs')] public function testValidUniversalMulticastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::UNIVERSAL_MULTICAST)); @@ -384,11 +347,9 @@ public function testValidUniversalMulticastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidLocalMulticastMacs - * @dataProvider getValidUniversalUnicastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidLocalMulticastMacs')] + #[DataProvider('getValidUniversalUnicastMacs')] public function testInvalidUniversalMulticastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::UNIVERSAL_MULTICAST); @@ -401,10 +362,8 @@ public function testInvalidUniversalMulticastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidUniversalUnicastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidUniversalUnicastMacs')] public function testUnicastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::UNICAST_ALL)); @@ -412,10 +371,8 @@ public function testUnicastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocalMulticastMacs - * @dataProvider getValidUniversalMulticastMacs - */ + #[DataProvider('getValidLocalMulticastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] public function testInvalidUnicastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::UNICAST_ALL); @@ -428,11 +385,9 @@ public function testInvalidUnicastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidLocalMulticastMacs - * @dataProvider getValidUniversalMulticastMacs - * @dataProvider getValidBroadcastMacs - */ + #[DataProvider('getValidLocalMulticastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] + #[DataProvider('getValidBroadcastMacs')] public function testMulticastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::MULTICAST_ALL)); @@ -440,10 +395,8 @@ public function testMulticastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidUniversalUnicastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidUniversalUnicastMacs')] public function testInvalidMulticastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::MULTICAST_ALL); @@ -456,10 +409,8 @@ public function testInvalidMulticastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidLocalMulticastMacs - * @dataProvider getValidUniversalMulticastMacs - */ + #[DataProvider('getValidLocalMulticastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] public function testMulticastNoBroadcastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::MULTICAST_NO_BROADCAST)); @@ -467,11 +418,9 @@ public function testMulticastNoBroadcastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidUniversalUnicastMacs - * @dataProvider getValidBroadcastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidUniversalUnicastMacs')] + #[DataProvider('getValidBroadcastMacs')] public function testInvalidMulticastNoBroadcastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::MULTICAST_NO_BROADCAST); @@ -484,9 +433,7 @@ public function testInvalidMulticastNoBroadcastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidBroadcastMacs - */ + #[DataProvider('getValidBroadcastMacs')] public function testBroadcastMacs($mac) { $this->validator->validate($mac, new MacAddress(type: MacAddress::BROADCAST)); @@ -494,12 +441,10 @@ public function testBroadcastMacs($mac) $this->assertNoViolation(); } - /** - * @dataProvider getValidLocalUnicastMacs - * @dataProvider getValidLocalMulticastMacs - * @dataProvider getValidUniversalUnicastMacs - * @dataProvider getValidUniversalMulticastMacs - */ + #[DataProvider('getValidLocalUnicastMacs')] + #[DataProvider('getValidLocalMulticastMacs')] + #[DataProvider('getValidUniversalUnicastMacs')] + #[DataProvider('getValidUniversalMulticastMacs')] public function testInvalidBroadcastMacs($mac) { $constraint = new MacAddress('myMessage', type: MacAddress::BROADCAST); @@ -512,9 +457,7 @@ public function testInvalidBroadcastMacs($mac) ->assertRaised(); } - /** - * @dataProvider getValidMacsWithWhitespaces - */ + #[DataProvider('getValidMacsWithWhitespaces')] public function testValidMacsWithWhitespaces($mac) { $this->validator->validate($mac, new MacAddress(normalizer: 'trim')); @@ -534,9 +477,7 @@ public static function getValidMacsWithWhitespaces(): array ]; } - /** - * @dataProvider getInvalidMacs - */ + #[DataProvider('getInvalidMacs')] public function testInvalidMacs($mac) { $constraint = new MacAddress('myMessage'); diff --git a/Tests/Constraints/NoSuspiciousCharactersValidatorTest.php b/Tests/Constraints/NoSuspiciousCharactersValidatorTest.php index c38a431f5..57c9fd0a9 100644 --- a/Tests/Constraints/NoSuspiciousCharactersValidatorTest.php +++ b/Tests/Constraints/NoSuspiciousCharactersValidatorTest.php @@ -11,15 +11,16 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Validator\Constraints\NoSuspiciousCharacters; use Symfony\Component\Validator\Constraints\NoSuspiciousCharactersValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** - * @requires extension intl - * * @extends ConstraintValidatorTestCase */ +#[RequiresPhpExtension('intl')] class NoSuspiciousCharactersValidatorTest extends ConstraintValidatorTestCase { protected function createValidator(): NoSuspiciousCharactersValidator @@ -27,9 +28,7 @@ protected function createValidator(): NoSuspiciousCharactersValidator return new NoSuspiciousCharactersValidator(); } - /** - * @dataProvider provideNonSuspiciousStrings - */ + #[DataProvider('provideNonSuspiciousStrings')] public function testNonSuspiciousStrings(string $string, array $options = []) { $this->validator->validate($string, new NoSuspiciousCharacters(...$options)); @@ -53,9 +52,7 @@ public static function provideNonSuspiciousStrings(): iterable ]; } - /** - * @dataProvider provideSuspiciousStrings - */ + #[DataProvider('provideSuspiciousStrings')] public function testSuspiciousStrings(string $string, array $options, array $errors) { $this->validator->validate($string, new NoSuspiciousCharacters(...$options)); diff --git a/Tests/Constraints/NotBlankValidatorTest.php b/Tests/Constraints/NotBlankValidatorTest.php index 42d5f3a60..274a4d6cf 100644 --- a/Tests/Constraints/NotBlankValidatorTest.php +++ b/Tests/Constraints/NotBlankValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotBlankValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -22,9 +23,7 @@ protected function createValidator(): NotBlankValidator return new NotBlankValidator(); } - /** - * @dataProvider getValidValues - */ + #[DataProvider('getValidValues')] public function testValidValues($value) { $this->validator->validate($value, new NotBlank()); @@ -117,9 +116,7 @@ public function testAllowNullFalse() ->assertRaised(); } - /** - * @dataProvider getWhitespaces - */ + #[DataProvider('getWhitespaces')] public function testNormalizedStringIsInvalid($value) { $constraint = new NotBlank( diff --git a/Tests/Constraints/NotNullValidatorTest.php b/Tests/Constraints/NotNullValidatorTest.php index b47aa0fa1..5468fc3b3 100644 --- a/Tests/Constraints/NotNullValidatorTest.php +++ b/Tests/Constraints/NotNullValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\NotNull; @@ -24,9 +25,7 @@ protected function createValidator(): NotNullValidator return new NotNullValidator(); } - /** - * @dataProvider getValidValues - */ + #[DataProvider('getValidValues')] public function testValidValues($value) { $this->validator->validate($value, new NotNull()); diff --git a/Tests/Constraints/PasswordStrengthValidatorTest.php b/Tests/Constraints/PasswordStrengthValidatorTest.php index fb063f4a7..c96976c87 100644 --- a/Tests/Constraints/PasswordStrengthValidatorTest.php +++ b/Tests/Constraints/PasswordStrengthValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\PasswordStrength; use Symfony\Component\Validator\Constraints\PasswordStrengthValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -23,9 +24,7 @@ protected function createValidator(): PasswordStrengthValidator return new PasswordStrengthValidator(); } - /** - * @dataProvider getValidValues - */ + #[DataProvider('getValidValues')] public function testValidValues(string|\Stringable $value, int $expectedStrength) { $this->validator->validate($value, new PasswordStrength(minScore: $expectedStrength)); @@ -53,9 +52,7 @@ public static function getValidValues(): iterable yield [new StringableValue('How-is-this'), PasswordStrength::STRENGTH_WEAK]; } - /** - * @dataProvider provideInvalidConstraints - */ + #[DataProvider('provideInvalidConstraints')] public function testThePasswordIsWeak(PasswordStrength $constraint, string $password, string $expectedMessage, string $expectedCode, string $strength) { $this->validator->validate($password, $constraint); @@ -93,9 +90,7 @@ public static function provideInvalidConstraints(): iterable ]; } - /** - * @dataProvider getPasswordValues - */ + #[DataProvider('getPasswordValues')] public function testStrengthEstimator(string $password, int $expectedStrength) { self::assertSame($expectedStrength, PasswordStrengthValidator::estimateStrength((string) $password)); diff --git a/Tests/Constraints/PasswordStrengthValidatorWithClosureTest.php b/Tests/Constraints/PasswordStrengthValidatorWithClosureTest.php index 3d24e8c5b..33347e6fb 100644 --- a/Tests/Constraints/PasswordStrengthValidatorWithClosureTest.php +++ b/Tests/Constraints/PasswordStrengthValidatorWithClosureTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\PasswordStrength; use Symfony\Component\Validator\Constraints\PasswordStrengthValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -33,9 +34,7 @@ protected function createValidator(): PasswordStrengthValidator }); } - /** - * @dataProvider getValidValues - */ + #[DataProvider('getValidValues')] public function testValidValues(string|\Stringable $value, int $expectedStrength) { $this->validator->validate($value, new PasswordStrength(minScore: $expectedStrength)); @@ -62,9 +61,7 @@ public static function getValidValues(): iterable yield [new StringableValue('HeloW0rld'), PasswordStrength::STRENGTH_WEAK]; } - /** - * @dataProvider provideInvalidConstraints - */ + #[DataProvider('provideInvalidConstraints')] public function testThePasswordIsWeak(PasswordStrength $constraint, string $password, string $expectedMessage, string $expectedCode, string $strength) { $this->validator->validate($password, $constraint); diff --git a/Tests/Constraints/RangeValidatorTest.php b/Tests/Constraints/RangeValidatorTest.php index 34f78c5ac..5e13a8cb3 100644 --- a/Tests/Constraints/RangeValidatorTest.php +++ b/Tests/Constraints/RangeValidatorTest.php @@ -83,9 +83,7 @@ public function testValidValuesMin($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenToTwenty - */ + #[DataProvider('getTenToTwenty')] public function testValidValuesMinNamed($value) { $constraint = new Range(min: 10); @@ -105,9 +103,7 @@ public function testValidValuesMax($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenToTwenty - */ + #[DataProvider('getTenToTwenty')] public function testValidValuesMaxNamed($value) { $constraint = new Range(max: 20); @@ -127,9 +123,7 @@ public function testValidValuesMinMax($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenToTwenty - */ + #[DataProvider('getTenToTwenty')] public function testValidValuesMinMaxNamed($value) { $constraint = new Range(min: 10, max: 20); @@ -157,9 +151,7 @@ public function testInvalidValuesMin($value, $formattedValue) ->assertRaised(); } - /** - * @dataProvider getLessThanTen - */ + #[DataProvider('getLessThanTen')] public function testInvalidValuesMinNamed($value, $formattedValue) { $constraint = new Range(min: 10, minMessage: 'myMessage'); @@ -192,9 +184,7 @@ public function testInvalidValuesMax($value, $formattedValue) ->assertRaised(); } - /** - * @dataProvider getMoreThanTwenty - */ + #[DataProvider('getMoreThanTwenty')] public function testInvalidValuesMaxNamed($value, $formattedValue) { $constraint = new Range(max: 20, maxMessage: 'myMessage'); @@ -229,9 +219,7 @@ public function testInvalidValuesCombinedMax($value, $formattedValue) ->assertRaised(); } - /** - * @dataProvider getMoreThanTwenty - */ + #[DataProvider('getMoreThanTwenty')] public function testInvalidValuesCombinedMaxNamed($value, $formattedValue) { $constraint = new Range(min: 10, max: 20, notInRangeMessage: 'myNotInRangeMessage'); @@ -267,9 +255,7 @@ public function testInvalidValuesCombinedMin($value, $formattedValue) ->assertRaised(); } - /** - * @dataProvider getLessThanTen - */ + #[DataProvider('getLessThanTen')] public function testInvalidValuesCombinedMinNamed($value, $formattedValue) { $constraint = new Range(min: 10, max: 20, notInRangeMessage: 'myNotInRangeMessage'); @@ -343,9 +329,7 @@ public static function getLaterThanTwentiethMarch2014(): array return $tests; } - /** - * @dataProvider getTenthToTwentiethMarch2014 - */ + #[DataProvider('getTenthToTwentiethMarch2014')] public function testValidDatesMin($value) { $constraint = new Range(min: 'March 10, 2014'); @@ -354,9 +338,7 @@ public function testValidDatesMin($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenthToTwentiethMarch2014 - */ + #[DataProvider('getTenthToTwentiethMarch2014')] public function testValidDatesMax($value) { $constraint = new Range(max: 'March 20, 2014'); @@ -365,9 +347,7 @@ public function testValidDatesMax($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenthToTwentiethMarch2014 - */ + #[DataProvider('getTenthToTwentiethMarch2014')] public function testValidDatesMinMax($value) { $constraint = new Range(min: 'March 10, 2014', max: 'March 20, 2014'); @@ -376,9 +356,7 @@ public function testValidDatesMinMax($value) $this->assertNoViolation(); } - /** - * @dataProvider getSoonerThanTenthMarch2014 - */ + #[DataProvider('getSoonerThanTenthMarch2014')] public function testInvalidDatesMin(\DateTimeInterface $value, string $dateTimeAsString) { // Conversion of dates to string differs between ICU versions @@ -399,9 +377,7 @@ public function testInvalidDatesMin(\DateTimeInterface $value, string $dateTimeA ->assertRaised(); } - /** - * @dataProvider getLaterThanTwentiethMarch2014 - */ + #[DataProvider('getLaterThanTwentiethMarch2014')] public function testInvalidDatesMax(\DateTimeInterface $value, string $dateTimeAsString) { // Conversion of dates to string differs between ICU versions @@ -422,9 +398,7 @@ public function testInvalidDatesMax(\DateTimeInterface $value, string $dateTimeA ->assertRaised(); } - /** - * @dataProvider getLaterThanTwentiethMarch2014 - */ + #[DataProvider('getLaterThanTwentiethMarch2014')] public function testInvalidDatesCombinedMax(\DateTimeInterface $value, string $dateTimeAsString) { // Conversion of dates to string differs between ICU versions @@ -447,9 +421,7 @@ public function testInvalidDatesCombinedMax(\DateTimeInterface $value, string $d ->assertRaised(); } - /** - * @dataProvider getSoonerThanTenthMarch2014 - */ + #[DataProvider('getSoonerThanTenthMarch2014')] public function testInvalidDatesCombinedMin($value, $dateTimeAsString) { // Conversion of dates to string differs between ICU versions @@ -586,9 +558,7 @@ public function testNonNumericWithNonParsableDatetimeMinAndMax() ->assertRaised(); } - /** - * @dataProvider throwsOnInvalidStringDatesProvider - */ + #[DataProvider('throwsOnInvalidStringDatesProvider')] public function testThrowsOnInvalidStringDates($expectedMessage, $value, $min, $max) { $this->expectException(ConstraintDefinitionException::class); @@ -637,9 +607,7 @@ public function testValidValuesMinPropertyPath($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenToTwenty - */ + #[DataProvider('getTenToTwenty')] public function testValidValuesMinPropertyPathNamed($value) { $this->setObject(new Limit(10)); @@ -649,9 +617,7 @@ public function testValidValuesMinPropertyPathNamed($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenToTwenty - */ + #[DataProvider('getTenToTwenty')] public function testValidValuesMaxPropertyPath($value) { $this->setObject(new Limit(20)); @@ -663,9 +629,7 @@ public function testValidValuesMaxPropertyPath($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenToTwenty - */ + #[DataProvider('getTenToTwenty')] public function testValidValuesMaxPropertyPathNamed($value) { $this->setObject(new Limit(20)); @@ -675,9 +639,7 @@ public function testValidValuesMaxPropertyPathNamed($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenToTwenty - */ + #[DataProvider('getTenToTwenty')] public function testValidValuesMinMaxPropertyPath($value) { $this->setObject(new MinMax(10, 20)); @@ -690,9 +652,7 @@ public function testValidValuesMinMaxPropertyPath($value) $this->assertNoViolation(); } - /** - * @dataProvider getLessThanTen - */ + #[DataProvider('getLessThanTen')] public function testInvalidValuesMinPropertyPath($value, $formattedValue) { $this->setObject(new Limit(10)); @@ -712,9 +672,7 @@ public function testInvalidValuesMinPropertyPath($value, $formattedValue) ->assertRaised(); } - /** - * @dataProvider getMoreThanTwenty - */ + #[DataProvider('getMoreThanTwenty')] public function testInvalidValuesMaxPropertyPath($value, $formattedValue) { $this->setObject(new Limit(20)); @@ -759,9 +717,7 @@ public function testInvalidValuesCombinedMaxPropertyPath($value, $formattedValue ->assertRaised(); } - /** - * @dataProvider getMoreThanTwenty - */ + #[DataProvider('getMoreThanTwenty')] public function testInvalidValuesCombinedMaxPropertyPathNamed($value, $formattedValue) { $this->setObject(new MinMax(10, 20)); @@ -809,9 +765,7 @@ public function testInvalidValuesCombinedMinPropertyPath($value, $formattedValue ->assertRaised(); } - /** - * @dataProvider getLessThanTen - */ + #[DataProvider('getLessThanTen')] public function testInvalidValuesCombinedMinPropertyPathNamed($value, $formattedValue) { $this->setObject(new MinMax(10, 20)); @@ -834,9 +788,7 @@ public function testInvalidValuesCombinedMinPropertyPathNamed($value, $formatted ->assertRaised(); } - /** - * @dataProvider getLessThanTen - */ + #[DataProvider('getLessThanTen')] public function testViolationOnNullObjectWithDefinedMin($value, $formattedValue) { $this->setObject(null); @@ -855,9 +807,7 @@ public function testViolationOnNullObjectWithDefinedMin($value, $formattedValue) ->assertRaised(); } - /** - * @dataProvider getMoreThanTwenty - */ + #[DataProvider('getMoreThanTwenty')] public function testViolationOnNullObjectWithDefinedMax($value, $formattedValue) { $this->setObject(null); @@ -876,9 +826,7 @@ public function testViolationOnNullObjectWithDefinedMax($value, $formattedValue) ->assertRaised(); } - /** - * @dataProvider getTenthToTwentiethMarch2014 - */ + #[DataProvider('getTenthToTwentiethMarch2014')] public function testValidDatesMinPropertyPath($value) { $this->setObject(new Limit('March 10, 2014')); @@ -888,9 +836,7 @@ public function testValidDatesMinPropertyPath($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenthToTwentiethMarch2014 - */ + #[DataProvider('getTenthToTwentiethMarch2014')] public function testValidDatesMaxPropertyPath($value) { $this->setObject(new Limit('March 20, 2014')); @@ -901,9 +847,7 @@ public function testValidDatesMaxPropertyPath($value) $this->assertNoViolation(); } - /** - * @dataProvider getTenthToTwentiethMarch2014 - */ + #[DataProvider('getTenthToTwentiethMarch2014')] public function testValidDatesMinMaxPropertyPath($value) { $this->setObject(new MinMax('March 10, 2014', 'March 20, 2014')); @@ -914,9 +858,7 @@ public function testValidDatesMinMaxPropertyPath($value) $this->assertNoViolation(); } - /** - * @dataProvider getSoonerThanTenthMarch2014 - */ + #[DataProvider('getSoonerThanTenthMarch2014')] public function testInvalidDatesMinPropertyPath($value, $dateTimeAsString) { // Conversion of dates to string differs between ICU versions @@ -940,9 +882,7 @@ public function testInvalidDatesMinPropertyPath($value, $dateTimeAsString) ->assertRaised(); } - /** - * @dataProvider getLaterThanTwentiethMarch2014 - */ + #[DataProvider('getLaterThanTwentiethMarch2014')] public function testInvalidDatesMaxPropertyPath($value, $dateTimeAsString) { // Conversion of dates to string differs between ICU versions @@ -966,9 +906,7 @@ public function testInvalidDatesMaxPropertyPath($value, $dateTimeAsString) ->assertRaised(); } - /** - * @dataProvider getLaterThanTwentiethMarch2014 - */ + #[DataProvider('getLaterThanTwentiethMarch2014')] public function testInvalidDatesCombinedMaxPropertyPath($value, $dateTimeAsString) { // Conversion of dates to string differs between ICU versions @@ -995,9 +933,7 @@ public function testInvalidDatesCombinedMaxPropertyPath($value, $dateTimeAsStrin ->assertRaised(); } - /** - * @dataProvider getSoonerThanTenthMarch2014 - */ + #[DataProvider('getSoonerThanTenthMarch2014')] public function testInvalidDatesCombinedMinPropertyPath($value, $dateTimeAsString) { // Conversion of dates to string differs between ICU versions @@ -1066,9 +1002,7 @@ public static function provideMessageIfMinAndMaxSet(): array ]; } - /** - * @dataProvider provideMessageIfMinAndMaxSet - */ + #[DataProvider('provideMessageIfMinAndMaxSet')] public function testMessageIfMinAndMaxSet(array $constraintExtraOptions, int $value, string $expectedMessage, string $expectedCode) { $constraint = new Range(...array_merge(['min' => 1, 'max' => 10], $constraintExtraOptions)); diff --git a/Tests/Constraints/RegexTest.php b/Tests/Constraints/RegexTest.php index 7c26c9880..3ce8fbf46 100644 --- a/Tests/Constraints/RegexTest.php +++ b/Tests/Constraints/RegexTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; @@ -67,9 +68,7 @@ public static function provideHtmlPatterns() ]; } - /** - * @dataProvider provideHtmlPatterns - */ + #[DataProvider('provideHtmlPatterns')] public function testGetHtmlPattern($pattern, $htmlPattern, $match = true) { $constraint = new Regex( diff --git a/Tests/Constraints/RegexValidatorTest.php b/Tests/Constraints/RegexValidatorTest.php index 9d6764af7..a2ea4c6d5 100644 --- a/Tests/Constraints/RegexValidatorTest.php +++ b/Tests/Constraints/RegexValidatorTest.php @@ -46,9 +46,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Regex(pattern: '/^[0-9]+$/')); } - /** - * @dataProvider getValidValues - */ + #[DataProvider('getValidValues')] public function testValidValues($value) { $constraint = new Regex(pattern: '/^[0-9]+$/'); @@ -68,9 +66,7 @@ public function testValidValuesWithWhitespaces($value) $this->assertNoViolation(); } - /** - * @dataProvider getValidValuesWithWhitespaces - */ + #[DataProvider('getValidValuesWithWhitespaces')] public function testValidValuesWithWhitespacesNamed($value) { $constraint = new Regex(pattern: '/^[0-9]+$/', normalizer: 'trim'); @@ -126,9 +122,7 @@ public function testInvalidValues($value) ->assertRaised(); } - /** - * @dataProvider getInvalidValues - */ + #[DataProvider('getInvalidValues')] public function testInvalidValuesNamed($value) { $constraint = new Regex(pattern: '/^[0-9]+$/', message: 'myMessage'); diff --git a/Tests/Constraints/ThrowsOnInvalidStringDatesTestTrait.php b/Tests/Constraints/ThrowsOnInvalidStringDatesTestTrait.php index ac40492fd..938b44a47 100644 --- a/Tests/Constraints/ThrowsOnInvalidStringDatesTestTrait.php +++ b/Tests/Constraints/ThrowsOnInvalidStringDatesTestTrait.php @@ -11,14 +11,13 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\AbstractComparison; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; trait ThrowsOnInvalidStringDatesTestTrait { - /** - * @dataProvider throwsOnInvalidStringDatesProvider - */ + #[DataProvider('throwsOnInvalidStringDatesProvider')] public function testThrowsOnInvalidStringDates(AbstractComparison $constraint, $expectedMessage, $value) { $this->expectException(ConstraintDefinitionException::class); diff --git a/Tests/Constraints/TimeValidatorTest.php b/Tests/Constraints/TimeValidatorTest.php index 7c1a9feb9..82ea054b1 100644 --- a/Tests/Constraints/TimeValidatorTest.php +++ b/Tests/Constraints/TimeValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Time; use Symfony\Component\Validator\Constraints\TimeValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -50,9 +51,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Time()); } - /** - * @dataProvider getValidTimes - */ + #[DataProvider('getValidTimes')] public function testValidTimes($time) { $this->validator->validate($time, new Time()); @@ -60,9 +59,7 @@ public function testValidTimes($time) $this->assertNoViolation(); } - /** - * @dataProvider getValidTimes - */ + #[DataProvider('getValidTimes')] public function testValidTimesWithNewLine(string $time) { $this->validator->validate($time."\n", new Time()); @@ -82,9 +79,7 @@ public static function getValidTimes() ]; } - /** - * @dataProvider getValidTimesWithoutSeconds - */ + #[DataProvider('getValidTimesWithoutSeconds')] public function testValidTimesWithoutSeconds(string $time) { $this->validator->validate($time, new Time(withSeconds: false)); @@ -92,9 +87,7 @@ public function testValidTimesWithoutSeconds(string $time) $this->assertNoViolation(); } - /** - * @dataProvider getValidTimesWithoutSeconds - */ + #[DataProvider('getValidTimesWithoutSeconds')] public function testValidTimesWithoutSecondsWithNewLine(string $time) { $this->validator->validate($time."\n", new Time(withSeconds: false)); @@ -114,9 +107,7 @@ public static function getValidTimesWithoutSeconds() ]; } - /** - * @dataProvider getInvalidTimesWithoutSeconds - */ + #[DataProvider('getInvalidTimesWithoutSeconds')] public function testInvalidTimesWithoutSeconds(string $time) { $this->validator->validate($time, $constraint = new Time()); @@ -136,9 +127,7 @@ public static function getInvalidTimesWithoutSeconds() ]; } - /** - * @dataProvider getInvalidTimes - */ + #[DataProvider('getInvalidTimes')] public function testInvalidTimes($time, $code) { $constraint = new Time(message: 'myMessage'); diff --git a/Tests/Constraints/TimezoneTest.php b/Tests/Constraints/TimezoneTest.php index 41fed2386..4a3f4f6d1 100644 --- a/Tests/Constraints/TimezoneTest.php +++ b/Tests/Constraints/TimezoneTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Timezone; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -50,9 +51,7 @@ public function testExceptionForGroupedTimezonesByCountryWithoutZone() new Timezone(countryCode: 'AR'); } - /** - * @dataProvider provideInvalidZones - */ + #[DataProvider('provideInvalidZones')] public function testExceptionForInvalidGroupedTimezones(int $zone) { $this->expectException(ConstraintDefinitionException::class); diff --git a/Tests/Constraints/TimezoneValidatorTest.php b/Tests/Constraints/TimezoneValidatorTest.php index 5595f872c..b9a04adc4 100644 --- a/Tests/Constraints/TimezoneValidatorTest.php +++ b/Tests/Constraints/TimezoneValidatorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Validator\Constraints\Timezone; use Symfony\Component\Validator\Constraints\TimezoneValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -47,9 +49,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Timezone()); } - /** - * @dataProvider getValidTimezones - */ + #[DataProvider('getValidTimezones')] public function testValidTimezones(string $timezone) { $this->validator->validate($timezone, new Timezone()); @@ -87,9 +87,7 @@ public static function getValidTimezones(): iterable yield ['Pacific/Noumea']; } - /** - * @dataProvider getValidGroupedTimezones - */ + #[DataProvider('getValidGroupedTimezones')] public function testValidGroupedTimezones(string $timezone, int $zone) { $constraint = new Timezone(zone: $zone); @@ -118,9 +116,7 @@ public static function getValidGroupedTimezones(): iterable yield ['Atlantic/Azores', \DateTimeZone::ATLANTIC | \DateTimeZone::ASIA]; } - /** - * @dataProvider getInvalidTimezones - */ + #[DataProvider('getInvalidTimezones')] public function testInvalidTimezoneWithoutZone(string $timezone) { $constraint = new Timezone(message: 'myMessage'); @@ -141,9 +137,7 @@ public static function getInvalidTimezones(): iterable yield ['foobar']; } - /** - * @dataProvider getInvalidGroupedTimezones - */ + #[DataProvider('getInvalidGroupedTimezones')] public function testInvalidGroupedTimezones(string $timezone, int $zone) { $constraint = new Timezone( @@ -184,9 +178,7 @@ public function testInvalidGroupedTimezoneNamed() ->assertRaised(); } - /** - * @dataProvider getValidGroupedTimezonesByCountry - */ + #[DataProvider('getValidGroupedTimezonesByCountry')] public function testValidGroupedTimezonesByCountry(string $timezone, string $country) { $constraint = new Timezone( @@ -221,9 +213,7 @@ public static function getValidGroupedTimezonesByCountry(): iterable yield ['Pacific/Kiritimati', 'KI']; } - /** - * @dataProvider getInvalidGroupedTimezonesByCountry - */ + #[DataProvider('getInvalidGroupedTimezonesByCountry')] public function testInvalidGroupedTimezonesByCountry(string $timezone, string $countryCode) { $constraint = new Timezone( @@ -265,9 +255,7 @@ public function testGroupedTimezonesWithInvalidCountry() ->assertRaised(); } - /** - * @dataProvider getDeprecatedTimezones - */ + #[DataProvider('getDeprecatedTimezones')] public function testDeprecatedTimezonesAreValidWithBC(string $timezone) { $constraint = new Timezone(\DateTimeZone::ALL_WITH_BC); @@ -277,9 +265,7 @@ public function testDeprecatedTimezonesAreValidWithBC(string $timezone) $this->assertNoViolation(); } - /** - * @dataProvider getDeprecatedTimezones - */ + #[DataProvider('getDeprecatedTimezones')] public function testDeprecatedTimezonesAreInvalidWithoutBC(string $timezone) { $constraint = new Timezone(message: 'myMessage'); @@ -310,9 +296,7 @@ public static function getDeprecatedTimezones(): iterable yield ['US/Pacific']; } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testIntlCompatibility() { $reflector = new \ReflectionExtension('intl'); diff --git a/Tests/Constraints/TypeValidatorTest.php b/Tests/Constraints/TypeValidatorTest.php index 3dbf23f7f..93841bc30 100644 --- a/Tests/Constraints/TypeValidatorTest.php +++ b/Tests/Constraints/TypeValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\Validator\Constraints\Type; @@ -60,9 +61,7 @@ public function testEmptyIsInvalidIfNoString() ->assertRaised(); } - /** - * @dataProvider getValidValues - */ + #[DataProvider('getValidValues')] public function testValidValues($value, $type) { $constraint = new Type(type: $type); @@ -120,9 +119,7 @@ public static function getValidValues() ]; } - /** - * @dataProvider getInvalidValues - */ + #[DataProvider('getInvalidValues')] public function testInvalidValues($value, $type, $valueAsString) { $constraint = new Type( @@ -192,9 +189,7 @@ public static function getInvalidValues() ]; } - /** - * @dataProvider getValidValuesMultipleTypes - */ + #[DataProvider('getValidValuesMultipleTypes')] public function testValidValuesMultipleTypes($value, array $types) { $constraint = new Type(type: $types); diff --git a/Tests/Constraints/UlidValidatorTest.php b/Tests/Constraints/UlidValidatorTest.php index 172ace189..592e0a94e 100644 --- a/Tests/Constraints/UlidValidatorTest.php +++ b/Tests/Constraints/UlidValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Ulid; use Symfony\Component\Validator\Constraints\UlidValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -67,9 +68,7 @@ public function testValidUlidAsRfc4122() $this->assertNoViolation(); } - /** - * @dataProvider getInvalidUlids - */ + #[DataProvider('getInvalidUlids')] public function testInvalidUlid(string $ulid, string $code) { $constraint = new Ulid(message: 'testMessage'); @@ -96,9 +95,7 @@ public static function getInvalidUlids(): array ]; } - /** - * @dataProvider getInvalidBase58Ulids - */ + #[DataProvider('getInvalidBase58Ulids')] public function testInvalidBase58Ulid(string $ulid, string $code) { $constraint = new Ulid(message: 'testMessage', format: Ulid::FORMAT_BASE_58); @@ -124,9 +121,7 @@ public static function getInvalidBase58Ulids(): array ]; } - /** - * @dataProvider getInvalidRfc4122Ulids - */ + #[DataProvider('getInvalidRfc4122Ulids')] public function testInvalidInvalid4122Ulid(string $ulid, string $code) { $constraint = new Ulid(message: 'testMessage', format: Ulid::FORMAT_RFC_4122); diff --git a/Tests/Constraints/UniqueValidatorTest.php b/Tests/Constraints/UniqueValidatorTest.php index 12efb7698..fd4641b71 100644 --- a/Tests/Constraints/UniqueValidatorTest.php +++ b/Tests/Constraints/UniqueValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Unique; use Symfony\Component\Validator\Constraints\UniqueValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; @@ -31,9 +32,7 @@ public function testExpectsUniqueConstraintCompatibleType() $this->validator->validate('', new Unique()); } - /** - * @dataProvider getValidValues - */ + #[DataProvider('getValidValues')] public function testValidValues($value) { $this->validator->validate($value, new Unique()); @@ -58,9 +57,7 @@ public static function getValidValues() ]; } - /** - * @dataProvider getInvalidValues - */ + #[DataProvider('getInvalidValues')] public function testInvalidValues($value, $expectedMessageParam) { $constraint = new Unique(message: 'myMessage'); @@ -97,9 +94,7 @@ public function testInvalidValueNamed() ->assertRaised(); } - /** - * @dataProvider getCallback - */ + #[DataProvider('getCallback')] public function testExpectsUniqueObjects($callback) { $object1 = new \stdClass(); @@ -121,9 +116,7 @@ public function testExpectsUniqueObjects($callback) $this->assertNoViolation(); } - /** - * @dataProvider getCallback - */ + #[DataProvider('getCallback')] public function testExpectsNonUniqueObjects($callback) { $object1 = new \stdClass(); @@ -215,9 +208,7 @@ public function testCollectionFieldsAreOptional() $this->assertNoViolation(); } - /** - * @dataProvider getInvalidFieldNames - */ + #[DataProvider('getInvalidFieldNames')] public function testCollectionFieldNamesMustBeString(string $type, mixed $field) { $this->expectException(UnexpectedTypeException::class); @@ -235,9 +226,7 @@ public static function getInvalidFieldNames(): array ]; } - /** - * @dataProvider getInvalidCollectionValues - */ + #[DataProvider('getInvalidCollectionValues')] public function testInvalidCollectionValues(array $value, array $fields, string $expectedMessageParam) { $this->validator->validate($value, new Unique( diff --git a/Tests/Constraints/UrlValidatorTest.php b/Tests/Constraints/UrlValidatorTest.php index 5eaca7161..51fbd8e0a 100644 --- a/Tests/Constraints/UrlValidatorTest.php +++ b/Tests/Constraints/UrlValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Url; use Symfony\Component\Validator\Constraints\UrlValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -50,9 +51,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Url(requireTld: true)); } - /** - * @dataProvider getValidUrls - */ + #[DataProvider('getValidUrls')] public function testValidUrls($url) { $this->validator->validate($url, new Url(requireTld: false)); @@ -60,9 +59,7 @@ public function testValidUrls($url) $this->assertNoViolation(); } - /** - * @dataProvider getValidUrls - */ + #[DataProvider('getValidUrls')] public function testValidUrlsWithNewLine($url) { $this->validator->validate($url."\n", new Url(requireTld: false)); @@ -73,9 +70,7 @@ public function testValidUrlsWithNewLine($url) ->assertRaised(); } - /** - * @dataProvider getValidUrlsWithWhitespaces - */ + #[DataProvider('getValidUrlsWithWhitespaces')] public function testValidUrlsWithWhitespaces($url) { $this->validator->validate($url, new Url( @@ -86,10 +81,8 @@ public function testValidUrlsWithWhitespaces($url) $this->assertNoViolation(); } - /** - * @dataProvider getValidRelativeUrls - * @dataProvider getValidUrls - */ + #[DataProvider('getValidRelativeUrls')] + #[DataProvider('getValidUrls')] public function testValidRelativeUrl($url) { $constraint = new Url( @@ -102,10 +95,8 @@ public function testValidRelativeUrl($url) $this->assertNoViolation(); } - /** - * @dataProvider getValidRelativeUrls - * @dataProvider getValidUrls - */ + #[DataProvider('getValidRelativeUrls')] + #[DataProvider('getValidUrls')] public function testValidRelativeUrlWithNewLine(string $url) { $constraint = new Url(relativeProtocol: true, requireTld: false); @@ -226,9 +217,7 @@ public static function getValidUrlsWithWhitespaces() ]; } - /** - * @dataProvider getInvalidUrls - */ + #[DataProvider('getInvalidUrls')] public function testInvalidUrls($url) { $constraint = new Url( @@ -244,10 +233,8 @@ public function testInvalidUrls($url) ->assertRaised(); } - /** - * @dataProvider getInvalidRelativeUrls - * @dataProvider getInvalidUrls - */ + #[DataProvider('getInvalidRelativeUrls')] + #[DataProvider('getInvalidUrls')] public function testInvalidRelativeUrl($url) { $constraint = new Url( @@ -328,9 +315,7 @@ public static function getInvalidUrls() ]; } - /** - * @dataProvider getValidCustomUrls - */ + #[DataProvider('getValidCustomUrls')] public function testCustomProtocolIsValid($url, $requireTld) { $constraint = new Url( @@ -352,9 +337,7 @@ public static function getValidCustomUrls() ]; } - /** - * @dataProvider getUrlsForRequiredTld - */ + #[DataProvider('getUrlsForRequiredTld')] public function testRequiredTld(string $url, bool $requireTld, bool $isValid) { $constraint = new Url(requireTld: $requireTld); diff --git a/Tests/Constraints/UuidValidatorTest.php b/Tests/Constraints/UuidValidatorTest.php index 84edc6612..ad3f1e303 100644 --- a/Tests/Constraints/UuidValidatorTest.php +++ b/Tests/Constraints/UuidValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Uuid; use Symfony\Component\Validator\Constraints\UuidValidator; @@ -57,9 +58,7 @@ public function testExpectsStringCompatibleType() $this->validator->validate(new \stdClass(), new Uuid()); } - /** - * @dataProvider getValidStrictUuids - */ + #[DataProvider('getValidStrictUuids')] public function testValidStrictUuids($uuid, $versions = null) { $constraint = new Uuid(); @@ -88,9 +87,7 @@ public static function getValidStrictUuids() ]; } - /** - * @dataProvider getValidStrictUuidsWithWhitespaces - */ + #[DataProvider('getValidStrictUuidsWithWhitespaces')] public function testValidStrictUuidsWithWhitespaces($uuid, $versions = null) { $constraint = new Uuid(normalizer: 'trim'); @@ -126,9 +123,7 @@ public function testValidStrictUuidWithWhitespacesNamed() $this->assertNoViolation(); } - /** - * @dataProvider getInvalidStrictUuids - */ + #[DataProvider('getInvalidStrictUuids')] public function testInvalidStrictUuids($uuid, $code, $versions = null) { $constraint = new Uuid(message: 'testMessage'); @@ -188,9 +183,7 @@ public static function getInvalidStrictUuids() ]; } - /** - * @dataProvider getValidNonStrictUuids - */ + #[DataProvider('getValidNonStrictUuids')] public function testValidNonStrictUuids($uuid) { $constraint = new Uuid(strict: false); @@ -217,9 +210,7 @@ public static function getValidNonStrictUuids() ]; } - /** - * @dataProvider getInvalidNonStrictUuids - */ + #[DataProvider('getInvalidNonStrictUuids')] public function testInvalidNonStrictUuids($uuid, $code) { $constraint = new Uuid( @@ -261,9 +252,7 @@ public function testInvalidNonStrictUuidNamed() ->assertRaised(); } - /** - * @dataProvider getUuidForTimeBasedAssertions - */ + #[DataProvider('getUuidForTimeBasedAssertions')] public function testTimeBasedUuid(string $uid, bool $expectedTimeBased) { $constraint = new Uuid(versions: Uuid::TIME_BASED_VERSIONS); diff --git a/Tests/Constraints/ValidComparisonToValueTrait.php b/Tests/Constraints/ValidComparisonToValueTrait.php index c4c70d8ce..c5de9b3f8 100644 --- a/Tests/Constraints/ValidComparisonToValueTrait.php +++ b/Tests/Constraints/ValidComparisonToValueTrait.php @@ -11,11 +11,11 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; + trait ValidComparisonToValueTrait { - /** - * @dataProvider provideAllValidComparisons - */ + #[DataProvider('provideAllValidComparisons')] public function testValidComparisonToValue($dirtyValue, $comparisonValue) { $constraint = $this->createConstraint(['value' => $comparisonValue]); diff --git a/Tests/Constraints/WeekValidatorTest.php b/Tests/Constraints/WeekValidatorTest.php index 0a5f0936c..e825d494d 100644 --- a/Tests/Constraints/WeekValidatorTest.php +++ b/Tests/Constraints/WeekValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Week; use Symfony\Component\Validator\Constraints\WeekValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -24,9 +25,7 @@ protected function createValidator(): WeekValidator return new WeekValidator(); } - /** - * @dataProvider provideWeekNumber - */ + #[DataProvider('provideWeekNumber')] public function testWeekIsValidWeekNumber(string|\Stringable $value, bool $expectedViolation) { $constraint = new Week(); @@ -96,9 +95,7 @@ public function testWithNewLine() ->assertRaised(); } - /** - * @dataProvider provideInvalidValues - */ + #[DataProvider('provideInvalidValues')] public function testInvalidValues(string $value) { $this->validator->validate($value, new Week()); @@ -108,9 +105,7 @@ public function testInvalidValues(string $value) ->assertRaised(); } - /** - * @dataProvider provideInvalidTypes - */ + #[DataProvider('provideInvalidTypes')] public function testNonStringValues(mixed $value) { $this->expectException(UnexpectedValueException::class); diff --git a/Tests/Constraints/WhenTest.php b/Tests/Constraints/WhenTest.php index fc5f5e88b..d919b0310 100644 --- a/Tests/Constraints/WhenTest.php +++ b/Tests/Constraints/WhenTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Length; @@ -122,9 +123,7 @@ public function testAttributes() self::assertSame(['foo'], $quuxConstraint->groups); } - /** - * @requires PHP 8.5 - */ + #[RequiresPhp('8.5')] public function testAttributesWithClosure() { $loader = new AttributeLoader(); diff --git a/Tests/Constraints/WordCountTest.php b/Tests/Constraints/WordCountTest.php index 50ed8081d..3f995c050 100644 --- a/Tests/Constraints/WordCountTest.php +++ b/Tests/Constraints/WordCountTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\WordCount; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -18,9 +19,7 @@ use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; -/** - * @requires extension intl - */ +#[RequiresPhpExtension('intl')] class WordCountTest extends TestCase { public function testLocaleIsSet() diff --git a/Tests/Constraints/WordCountValidatorTest.php b/Tests/Constraints/WordCountValidatorTest.php index ce1256f92..850f67403 100644 --- a/Tests/Constraints/WordCountValidatorTest.php +++ b/Tests/Constraints/WordCountValidatorTest.php @@ -11,15 +11,15 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Validator\Constraints\WordCount; use Symfony\Component\Validator\Constraints\WordCountValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; use Symfony\Component\Validator\Tests\Constraints\Fixtures\StringableValue; -/** - * @requires extension intl - */ +#[RequiresPhpExtension('intl')] class WordCountValidatorTest extends ConstraintValidatorTestCase { protected function createValidator(): WordCountValidator @@ -27,9 +27,7 @@ protected function createValidator(): WordCountValidator return new WordCountValidator(); } - /** - * @dataProvider provideValidValues - */ + #[DataProvider('provideValidValues')] public function testValidWordCount(string|\Stringable|null $value, int $expectedWordCount) { $this->validator->validate($value, new WordCount(min: $expectedWordCount, max: $expectedWordCount)); @@ -63,9 +61,7 @@ public function testTooLong() ->assertRaised(); } - /** - * @dataProvider provideInvalidTypes - */ + #[DataProvider('provideInvalidTypes')] public function testNonStringValues(mixed $value) { $this->expectException(UnexpectedValueException::class); diff --git a/Tests/Constraints/YamlValidatorTest.php b/Tests/Constraints/YamlValidatorTest.php index a31892667..cc81da996 100644 --- a/Tests/Constraints/YamlValidatorTest.php +++ b/Tests/Constraints/YamlValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Validator\Constraints\Yaml; use Symfony\Component\Validator\Constraints\YamlValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -26,9 +27,7 @@ protected function createValidator(): YamlValidator return new YamlValidator(); } - /** - * @dataProvider getValidValues - */ + #[DataProvider('getValidValues')] public function testYamlIsValid($value) { $this->validator->validate($value, new Yaml()); @@ -42,9 +41,7 @@ public function testYamlWithFlags() $this->assertNoViolation(); } - /** - * @dataProvider getInvalidValues - */ + #[DataProvider('getInvalidValues')] public function testInvalidValues($value, $message, $line) { $constraint = new Yaml( diff --git a/Tests/DependencyInjection/AddAutoMappingConfigurationPassTest.php b/Tests/DependencyInjection/AddAutoMappingConfigurationPassTest.php index 9a6817966..7f4b36da1 100644 --- a/Tests/DependencyInjection/AddAutoMappingConfigurationPassTest.php +++ b/Tests/DependencyInjection/AddAutoMappingConfigurationPassTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Validator\DependencyInjection\AddAutoMappingConfigurationPass; @@ -36,9 +37,7 @@ public function testNoValidatorBuilder() $this->assertCount(1, $container->getDefinitions()); } - /** - * @dataProvider mappingProvider - */ + #[DataProvider('mappingProvider')] public function testProcess(string $namespace, array $services, string $expectedRegexp) { $container = new ContainerBuilder(); diff --git a/Tests/Mapping/Loader/PropertyInfoLoaderTest.php b/Tests/Mapping/Loader/PropertyInfoLoaderTest.php index ae5253a3f..dc11ea7aa 100644 --- a/Tests/Mapping/Loader/PropertyInfoLoaderTest.php +++ b/Tests/Mapping/Loader/PropertyInfoLoaderTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Mapping\Loader; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; @@ -224,9 +225,7 @@ public function getTypes(string $class, string $property, array $context = []): $this->assertCount(0, $noAutoMappingConstraints, 'DisableAutoMapping constraint is not added in the list'); } - /** - * @dataProvider regexpProvider - */ + #[DataProvider('regexpProvider')] public function testClassValidator(bool $expected, ?string $classValidatorRegexp = null) { $propertyListExtractor = $this->createMock(PropertyListExtractorInterface::class); diff --git a/Tests/Mapping/Loader/YamlFileLoaderTest.php b/Tests/Mapping/Loader/YamlFileLoaderTest.php index 5356e9414..e5f3db9f7 100644 --- a/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Mapping\Loader; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; @@ -49,9 +50,7 @@ public function testLoadClassMetadataReturnsFalseIfEmpty() $this->assertSame([], $r->getValue($loader)); } - /** - * @dataProvider provideInvalidYamlFiles - */ + #[DataProvider('provideInvalidYamlFiles')] public function testInvalidYamlFiles($path) { $loader = new YamlFileLoader(__DIR__.'/'.$path); diff --git a/Tests/Resources/TranslationFilesTest.php b/Tests/Resources/TranslationFilesTest.php index 326ed4fc4..acb102993 100644 --- a/Tests/Resources/TranslationFilesTest.php +++ b/Tests/Resources/TranslationFilesTest.php @@ -11,14 +11,13 @@ namespace Symfony\Component\Validator\Tests\Resources; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Translation\Util\XliffUtils; class TranslationFilesTest extends TestCase { - /** - * @dataProvider provideTranslationFiles - */ + #[DataProvider('provideTranslationFiles')] public function testTranslationFileIsValid($filePath) { $document = new \DOMDocument(); @@ -29,9 +28,7 @@ public function testTranslationFileIsValid($filePath) $this->assertCount(0, $errors, \sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message')))); } - /** - * @dataProvider provideTranslationFiles - */ + #[DataProvider('provideTranslationFiles')] public function testTranslationFileIsValidWithoutEntityLoader($filePath) { $document = new \DOMDocument(); diff --git a/Tests/Util/PropertyPathTest.php b/Tests/Util/PropertyPathTest.php index f7f33d476..9ba408c0f 100644 --- a/Tests/Util/PropertyPathTest.php +++ b/Tests/Util/PropertyPathTest.php @@ -11,14 +11,13 @@ namespace Symfony\Component\Validator\Tests\Util; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Util\PropertyPath; class PropertyPathTest extends TestCase { - /** - * @dataProvider provideAppendPaths - */ + #[DataProvider('provideAppendPaths')] public function testAppend($basePath, $subPath, $expectedPath, $message) { $this->assertSame($expectedPath, PropertyPath::append($basePath, $subPath), $message); diff --git a/Tests/Validator/RecursiveValidatorTest.php b/Tests/Validator/RecursiveValidatorTest.php index 1ae14ba30..328a67c40 100644 --- a/Tests/Validator/RecursiveValidatorTest.php +++ b/Tests/Validator/RecursiveValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Validator; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Component\Translation\IdentityTranslator; @@ -120,7 +121,7 @@ public function testValidate() $violations = $this->validate('Bernhard', $constraint, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -156,7 +157,7 @@ public function testClassConstraint() $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -195,7 +196,7 @@ public function testPropertyConstraint() $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -234,7 +235,7 @@ public function testGetterConstraint() $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -271,7 +272,7 @@ public function testArray() $violations = $this->validate($array, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -308,7 +309,7 @@ public function testRecursiveArray() $violations = $this->validate($array, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -345,7 +346,7 @@ public function testTraversable() $violations = $this->validate($traversable, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -384,7 +385,7 @@ public function testRecursiveTraversable() $violations = $this->validate($traversable, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -422,7 +423,7 @@ public function testReferenceClassConstraint() $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -463,7 +464,7 @@ public function testReferencePropertyConstraint() $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -504,7 +505,7 @@ public function testReferenceGetterConstraint() $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -525,7 +526,7 @@ public function testsIgnoreNullReference() $violations = $this->validate($entity); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -541,9 +542,7 @@ public function testFailOnScalarReferences() $this->validate($entity); } - /** - * @dataProvider getConstraintMethods - */ + #[DataProvider('getConstraintMethods')] public function testArrayReference($constraintMethod) { $entity = new Entity(); @@ -570,7 +569,7 @@ public function testArrayReference($constraintMethod) $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -582,9 +581,7 @@ public function testArrayReference($constraintMethod) $this->assertNull($violations[0]->getCode()); } - /** - * @dataProvider getConstraintMethods - */ + #[DataProvider('getConstraintMethods')] public function testRecursiveArrayReference($constraintMethod) { $entity = new Entity(); @@ -611,7 +608,7 @@ public function testRecursiveArrayReference($constraintMethod) $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -643,13 +640,11 @@ public function testOnlyCascadedArraysAreTraversed() $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } - /** - * @dataProvider getConstraintMethods - */ + #[DataProvider('getConstraintMethods')] public function testArrayTraversalCannotBeDisabled($constraintMethod) { $entity = new Entity(); @@ -666,13 +661,11 @@ public function testArrayTraversalCannotBeDisabled($constraintMethod) $violations = $this->validate($entity); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } - /** - * @dataProvider getConstraintMethods - */ + #[DataProvider('getConstraintMethods')] public function testRecursiveArrayTraversalCannotBeDisabled($constraintMethod) { $entity = new Entity(); @@ -690,13 +683,11 @@ public function testRecursiveArrayTraversalCannotBeDisabled($constraintMethod) $violations = $this->validate($entity); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } - /** - * @dataProvider getConstraintMethods - */ + #[DataProvider('getConstraintMethods')] public function testIgnoreScalarsDuringArrayTraversal($constraintMethod) { $entity = new Entity(); @@ -706,13 +697,11 @@ public function testIgnoreScalarsDuringArrayTraversal($constraintMethod) $violations = $this->validate($entity); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } - /** - * @dataProvider getConstraintMethods - */ + #[DataProvider('getConstraintMethods')] public function testIgnoreNullDuringArrayTraversal($constraintMethod) { $entity = new Entity(); @@ -722,7 +711,7 @@ public function testIgnoreNullDuringArrayTraversal($constraintMethod) $violations = $this->validate($entity); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -752,7 +741,7 @@ public function testTraversableReference() $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -781,7 +770,7 @@ public function testDisableTraversableTraversal() $violations = $this->validate($entity); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -829,7 +818,7 @@ public function testEnableRecursiveTraversableTraversal() $violations = $this->validate($entity, null, 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -877,7 +866,7 @@ public function testValidateProperty() $violations = $this->validateProperty($entity, 'firstName', 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -940,7 +929,7 @@ public function testValidatePropertyValue() 'Group' ); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -989,7 +978,7 @@ public function testValidatePropertyValueWithClassName() 'Group' ); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1028,7 +1017,7 @@ public function testValidateObjectOnlyOncePerGroup() $violations = $this->validate($entity); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } @@ -1048,7 +1037,7 @@ public function testValidateDifferentObjectsSeparately() $violations = $this->validate($entity); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(2, $violations); } @@ -1071,7 +1060,7 @@ public function testValidateSingleGroup() $violations = $this->validate($entity, null, 'Group 2'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } @@ -1094,7 +1083,7 @@ public function testValidateMultipleGroups() $violations = $this->validate($entity, null, ['Group 1', 'Group 2']); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(2, $violations); } @@ -1127,7 +1116,7 @@ public function testReplaceDefaultGroupByGroupSequenceObject() $violations = $this->validate($entity, null, 'Default'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Violation in Group 2', $violations[0]->getMessage()); } @@ -1161,7 +1150,7 @@ public function testReplaceDefaultGroupByGroupSequenceArray() $violations = $this->validate($entity, null, 'Default'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Violation in Group 2', $violations[0]->getMessage()); } @@ -1193,7 +1182,7 @@ public function testPropagateDefaultGroupToReferenceWhenReplacingDefaultGroup() $violations = $this->validate($entity, null, 'Default'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Violation in Default group', $violations[0]->getMessage()); } @@ -1223,14 +1212,12 @@ public function testValidateCustomGroupWhenDefaultGroupWasReplaced() $violations = $this->validate($entity, null, 'Other Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Violation in other group', $violations[0]->getMessage()); } - /** - * @dataProvider getTestReplaceDefaultGroup - */ + #[DataProvider('getTestReplaceDefaultGroup')] public function testReplaceDefaultGroup($sequence, array $assertViolations) { $entity = new GroupSequenceProviderEntity($sequence); @@ -1261,7 +1248,7 @@ public function testReplaceDefaultGroup($sequence, array $assertViolations) $violations = $this->validate($entity, null, 'Default'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(\count($assertViolations), $violations); foreach ($assertViolations as $key => $message) { $this->assertSame($message, $violations[$key]->getMessage()); @@ -1364,7 +1351,7 @@ public function testGroupSequenceAbortsAfterFailedGroup() $sequence = new GroupSequence(['Group 1', 'Group 2', 'Group 3']); $violations = $this->validator->validate($entity, new Valid(), $sequence); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message 1', $violations[0]->getMessage()); } @@ -1394,7 +1381,7 @@ public function testGroupSequenceIncludesReferences() $sequence = new GroupSequence(['Group 1', 'Entity']); $violations = $this->validator->validate($entity, new Valid(), $sequence); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Reference violation 1', $violations[0]->getMessage()); } @@ -1412,7 +1399,7 @@ public function testValidateInSeparateContext() ->validate($value->reference, new Valid(), 'Group') ; - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1453,7 +1440,7 @@ public function testValidateInSeparateContext() $violations = $this->validator->validate($entity, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Separate violation', $violations[0]->getMessage()); } @@ -1509,7 +1496,7 @@ public function testValidateInContext() $violations = $this->validator->validate($entity, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1572,7 +1559,7 @@ public function testValidateArrayInContext() $violations = $this->validator->validate($entity, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1610,7 +1597,7 @@ public function testTraverseTraversableByDefault() $violations = $this->validate($traversable, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1642,7 +1629,7 @@ public function testTraversalEnabledOnClass() $violations = $this->validate($traversable, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } @@ -1666,7 +1653,7 @@ public function testTraversalDisabledOnClass() $violations = $this->validate($traversable, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1700,7 +1687,7 @@ public function testReferenceTraversalDisabledOnClass() $violations = $this->validate($entity, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1727,7 +1714,7 @@ public function testReferenceTraversalEnabledOnReferenceDisabledOnClass() $violations = $this->validate($entity, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1754,7 +1741,7 @@ public function testReferenceTraversalDisabledOnReferenceEnabledOnClass() $violations = $this->validate($entity, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1774,7 +1761,7 @@ public function testReferenceCascadeDisabledByDefault() $violations = $this->validate($entity, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1796,7 +1783,7 @@ public function testReferenceCascadeEnabledIgnoresUntyped() $violations = $this->validate($entity, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1826,7 +1813,7 @@ public function testTypedReferenceCascadeEnabled() $violations = $this->validate($entity, new Valid(), 'Group'); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertInstanceOf(Callback::class, $violations->get(0)->getConstraint()); } @@ -1848,7 +1835,7 @@ public function testAddCustomizedViolation() $violations = $this->validator->validate($entity); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1875,7 +1862,7 @@ public function testNoDuplicateValidationIfClassConstraintInMultipleGroups() $violations = $this->validator->validate($entity, new Valid(), ['Group 1', 'Group 2']); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } @@ -1894,7 +1881,7 @@ public function testNoDuplicateValidationIfPropertyConstraintInMultipleGroups() $violations = $this->validator->validate($entity, new Valid(), ['Group 1', 'Group 2']); - /** @var ConstraintViolationInterface[] $violations */ + /* @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } From 4b7566fa836567c50ff28b3c98dbd9105277338d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 4 Aug 2025 09:53:42 +0200 Subject: [PATCH 21/57] CS fixes --- Constraints/File.php | 5 +++-- Constraints/Type.php | 2 +- Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php | 3 ++- Validator/RecursiveContextualValidator.php | 3 ++- Violation/ConstraintViolationBuilderInterface.php | 4 +++- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Constraints/File.php b/Constraints/File.php index 0e436dc9e..169e94154 100644 --- a/Constraints/File.php +++ b/Constraints/File.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Constraints; +use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -21,7 +22,7 @@ * * A file can be one of the following: * - A string (or object with a __toString() method) path to an existing file; - * - A valid {@see \Symfony\Component\HttpFoundation\File\File File} object (including objects of {@see \Symfony\Component\HttpFoundation\File\UploadedFile UploadedFile} class). + * - A valid {@see \Symfony\Component\HttpFoundation\File\File} object (including objects of {@see UploadedFile} class). * * @property int $maxSize * @@ -105,7 +106,7 @@ class File extends Constraint * @param string[]|null $groups * @param array|string|null $extensions A list of valid extensions to check. Related media types are also enforced ({@see https://symfony.com/doc/current/reference/constraints/File.html#extensions}) * @param string|null $filenameCharset The charset to be used when computing filename length (defaults to null) - * @param self::FILENAME_COUNT_*|null $filenameCountUnit The character count unit used for checking the filename length (defaults to {@see File::FILENAME_COUNT_BYTES}) + * @param self::FILENAME_COUNT_*|null $filenameCountUnit The character count unit used for checking the filename length (defaults to {@see self::FILENAME_COUNT_BYTES}) * * @see https://www.iana.org/assignments/media-types/media-types.xhtml Existing media types */ diff --git a/Constraints/Type.php b/Constraints/Type.php index 4c119a8c7..a2050e11d 100644 --- a/Constraints/Type.php +++ b/Constraints/Type.php @@ -33,7 +33,7 @@ class Type extends Constraint public string|array|null $type = null; /** - * @param string|list|null $type The type(s) to enforce on the value + * @param string|list|null $type The type(s) to enforce on the value * @param string[]|null $groups */ #[HasNamedArguments] diff --git a/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php b/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php index 68f279ecf..afd650581 100644 --- a/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php +++ b/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php @@ -20,6 +20,7 @@ use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; +use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity; use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\EntityParent; @@ -140,7 +141,7 @@ public function testMetadataCacheWithRuntimeConstraint() public function testGroupsFromParent() { - $reader = new \Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader(); + $reader = new StaticMethodLoader(); $factory = new LazyLoadingMetadataFactory($reader); $metadata = $factory->getMetadataFor('Symfony\Component\Validator\Tests\Fixtures\EntityStaticCarTurbo'); $groups = []; diff --git a/Validator/RecursiveContextualValidator.php b/Validator/RecursiveContextualValidator.php index 9805bdcd4..55af3fc90 100644 --- a/Validator/RecursiveContextualValidator.php +++ b/Validator/RecursiveContextualValidator.php @@ -27,6 +27,7 @@ use Symfony\Component\Validator\Exception\UnexpectedValueException; use Symfony\Component\Validator\Exception\UnsupportedMetadataException; use Symfony\Component\Validator\Exception\ValidatorException; +use Symfony\Component\Validator\GroupSequenceProviderInterface; use Symfony\Component\Validator\Mapping\CascadingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadataInterface; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; @@ -443,7 +444,7 @@ private function validateClassNode(object $object, ?string $cacheKey, ClassMetad } else { // The group sequence is dynamically obtained from the validated // object - /** @var \Symfony\Component\Validator\GroupSequenceProviderInterface $object */ + /** @var GroupSequenceProviderInterface $object */ $group = $object->getGroupSequence(); } $defaultOverridden = true; diff --git a/Violation/ConstraintViolationBuilderInterface.php b/Violation/ConstraintViolationBuilderInterface.php index 195dec924..4c0de8913 100644 --- a/Violation/ConstraintViolationBuilderInterface.php +++ b/Violation/ConstraintViolationBuilderInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Violation; +use Symfony\Contracts\Translation\TranslatorInterface; + /** * Builds {@link \Symfony\Component\Validator\ConstraintViolationInterface} * objects. @@ -69,7 +71,7 @@ public function disableTranslation(): static; * * @return $this * - * @see \Symfony\Contracts\Translation\TranslatorInterface + * @see TranslatorInterface */ public function setTranslationDomain(string $translationDomain): static; From 5345db52c1ddbfcf1448d4cbc1fdef285759cbde Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 4 Aug 2025 14:33:15 +0200 Subject: [PATCH 22/57] [Ldap][Messenger][Validator][Workflow] Add methods to interfaces as planned --- CHANGELOG.md | 1 + Mapping/ClassMetadataInterface.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d89833318..e3357c72c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 8.0 --- + * Add method `getGroupProvider()` to `ClassMetadataInterface` * Remove the `getRequiredOptions()` and `getDefaultOption()` methods from the `All`, `AtLeastOneOf`, `CardScheme`, `Collection`, `CssColor`, `Expression`, `Regex`, `Sequentially`, `Type`, and `When` constraints * Remove support for evaluating options in the base `Constraint` class. Initialize properties in the constructor of the concrete constraint diff --git a/Mapping/ClassMetadataInterface.php b/Mapping/ClassMetadataInterface.php index 6625e37e6..e74085e6f 100644 --- a/Mapping/ClassMetadataInterface.php +++ b/Mapping/ClassMetadataInterface.php @@ -30,8 +30,6 @@ * @see GroupSequence * @see GroupSequenceProviderInterface * @see TraversalStrategy - * - * @method string|null getGroupProvider() */ interface ClassMetadataInterface extends MetadataInterface { @@ -66,6 +64,8 @@ public function getGroupSequence(): ?GroupSequence; */ public function isGroupSequenceProvider(): bool; + public function getGroupProvider(): ?string; + /** * Check if there's any metadata attached to the given named property. * From d580ab0d7a232104c841613b4addde42d0346747 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Sun, 10 Aug 2025 00:28:14 +0200 Subject: [PATCH 23/57] chore: heredoc indentation as of PHP 7.3 https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc --- Command/DebugCommand.php | 6 +- Tests/Command/DebugCommandTest.php | 260 +++++++++++++------------- Tests/ConstraintViolationListTest.php | 24 +-- Tests/ConstraintViolationTest.php | 30 +-- 4 files changed, 160 insertions(+), 160 deletions(-) diff --git a/Command/DebugCommand.php b/Command/DebugCommand.php index 70b508d09..e6a076c97 100644 --- a/Command/DebugCommand.php +++ b/Command/DebugCommand.php @@ -50,10 +50,10 @@ protected function configure(): void ->addArgument('class', InputArgument::REQUIRED, 'A fully qualified class name or a path') ->addOption('show-all', null, InputOption::VALUE_NONE, 'Show all classes even if they have no validation constraints') ->setHelp(<<<'EOF' -The %command.name% 'App\Entity\Dummy' command dumps the validators for the dummy class. + The %command.name% 'App\Entity\Dummy' command dumps the validators for the dummy class. -The %command.name% src/ command dumps the validators for the `src` directory. -EOF + The %command.name% src/ command dumps the validators for the `src` directory. + EOF ) ; } diff --git a/Tests/Command/DebugCommandTest.php b/Tests/Command/DebugCommandTest.php index 660905eba..ce2ff76fd 100644 --- a/Tests/Command/DebugCommandTest.php +++ b/Tests/Command/DebugCommandTest.php @@ -33,49 +33,49 @@ public function testOutputWithClassArgument() $this->assertSame(<< "1 + 1 = 2", | -| | | | "message" => "This value is not valid.", | -| | | | "negate" => true, | -| | | | "payload" => null, | -| | | | "values" => [] | -| | | | ] | -| code | property options | | [ | -| | | | "cascadeStrategy" => "None", | -| | | | "autoMappingStrategy" => "None", | -| | | | "traversalStrategy" => "None" | -| | | | ] | -| code | Symfony\Component\Validator\Constraints\NotBlank | Default, DummyClassOne | [ | -| | | | "allowNull" => false, | -| | | | "message" => "This value should not be blank.", | -| | | | "normalizer" => null, | -| | | | "payload" => null | -| | | | ] | -| email | property options | | [ | -| | | | "cascadeStrategy" => "None", | -| | | | "autoMappingStrategy" => "None", | -| | | | "traversalStrategy" => "None" | -| | | | ] | -| email | Symfony\Component\Validator\Constraints\Email | Default, DummyClassOne | [ | -| | | | "message" => "This value is not a valid email address.", | -| | | | "mode" => null, | -| | | | "normalizer" => null, | -| | | | "payload" => null | -| | | | ] | -| dummyClassTwo | property options | | [ | -| | | | "cascadeStrategy" => "Cascade", | -| | | | "autoMappingStrategy" => "None", | -| | | | "traversalStrategy" => "Implicit" | -| | | | ] | -+---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ - -TXT + Symfony\Component\Validator\Tests\Dummy\DummyClassOne + ----------------------------------------------------- + + +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ + | Property | Name | Groups | Options | + +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ + | - | Symfony\Component\Validator\Constraints\Expression | Default, DummyClassOne | [ | + | | | | "expression" => "1 + 1 = 2", | + | | | | "message" => "This value is not valid.", | + | | | | "negate" => true, | + | | | | "payload" => null, | + | | | | "values" => [] | + | | | | ] | + | code | property options | | [ | + | | | | "cascadeStrategy" => "None", | + | | | | "autoMappingStrategy" => "None", | + | | | | "traversalStrategy" => "None" | + | | | | ] | + | code | Symfony\Component\Validator\Constraints\NotBlank | Default, DummyClassOne | [ | + | | | | "allowNull" => false, | + | | | | "message" => "This value should not be blank.", | + | | | | "normalizer" => null, | + | | | | "payload" => null | + | | | | ] | + | email | property options | | [ | + | | | | "cascadeStrategy" => "None", | + | | | | "autoMappingStrategy" => "None", | + | | | | "traversalStrategy" => "None" | + | | | | ] | + | email | Symfony\Component\Validator\Constraints\Email | Default, DummyClassOne | [ | + | | | | "message" => "This value is not a valid email address.", | + | | | | "mode" => null, | + | | | | "normalizer" => null, | + | | | | "payload" => null | + | | | | ] | + | dummyClassTwo | property options | | [ | + | | | | "cascadeStrategy" => "Cascade", | + | | | | "autoMappingStrategy" => "None", | + | | | | "traversalStrategy" => "Implicit" | + | | | | ] | + +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ + + TXT , $tester->getDisplay(true) ); } @@ -89,91 +89,91 @@ public function testOutputWithPathArgument() $this->assertSame(<< "1 + 1 = 2", | -| | | | "message" => "This value is not valid.", | -| | | | "negate" => true, | -| | | | "payload" => null, | -| | | | "values" => [] | -| | | | ] | -| code | property options | | [ | -| | | | "cascadeStrategy" => "None", | -| | | | "autoMappingStrategy" => "None", | -| | | | "traversalStrategy" => "None" | -| | | | ] | -| code | Symfony\Component\Validator\Constraints\NotBlank | Default, DummyClassOne | [ | -| | | | "allowNull" => false, | -| | | | "message" => "This value should not be blank.", | -| | | | "normalizer" => null, | -| | | | "payload" => null | -| | | | ] | -| email | property options | | [ | -| | | | "cascadeStrategy" => "None", | -| | | | "autoMappingStrategy" => "None", | -| | | | "traversalStrategy" => "None" | -| | | | ] | -| email | Symfony\Component\Validator\Constraints\Email | Default, DummyClassOne | [ | -| | | | "message" => "This value is not a valid email address.", | -| | | | "mode" => null, | -| | | | "normalizer" => null, | -| | | | "payload" => null | -| | | | ] | -| dummyClassTwo | property options | | [ | -| | | | "cascadeStrategy" => "Cascade", | -| | | | "autoMappingStrategy" => "None", | -| | | | "traversalStrategy" => "Implicit" | -| | | | ] | -+---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ - -Symfony\Component\Validator\Tests\Dummy\DummyClassTwo ------------------------------------------------------ - -+---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ -| Property | Name | Groups | Options | -+---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ -| - | Symfony\Component\Validator\Constraints\Expression | Default, DummyClassTwo | [ | -| | | | "expression" => "1 + 1 = 2", | -| | | | "message" => "This value is not valid.", | -| | | | "negate" => true, | -| | | | "payload" => null, | -| | | | "values" => [] | -| | | | ] | -| code | property options | | [ | -| | | | "cascadeStrategy" => "None", | -| | | | "autoMappingStrategy" => "None", | -| | | | "traversalStrategy" => "None" | -| | | | ] | -| code | Symfony\Component\Validator\Constraints\NotBlank | Default, DummyClassTwo | [ | -| | | | "allowNull" => false, | -| | | | "message" => "This value should not be blank.", | -| | | | "normalizer" => null, | -| | | | "payload" => null | -| | | | ] | -| email | property options | | [ | -| | | | "cascadeStrategy" => "None", | -| | | | "autoMappingStrategy" => "None", | -| | | | "traversalStrategy" => "None" | -| | | | ] | -| email | Symfony\Component\Validator\Constraints\Email | Default, DummyClassTwo | [ | -| | | | "message" => "This value is not a valid email address.", | -| | | | "mode" => null, | -| | | | "normalizer" => null, | -| | | | "payload" => null | -| | | | ] | -| dummyClassOne | property options | | [ | -| | | | "cascadeStrategy" => "None", | -| | | | "autoMappingStrategy" => "Disabled", | -| | | | "traversalStrategy" => "None" | -| | | | ] | -+---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ - -TXT + Symfony\Component\Validator\Tests\Dummy\DummyClassOne + ----------------------------------------------------- + + +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ + | Property | Name | Groups | Options | + +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ + | - | Symfony\Component\Validator\Constraints\Expression | Default, DummyClassOne | [ | + | | | | "expression" => "1 + 1 = 2", | + | | | | "message" => "This value is not valid.", | + | | | | "negate" => true, | + | | | | "payload" => null, | + | | | | "values" => [] | + | | | | ] | + | code | property options | | [ | + | | | | "cascadeStrategy" => "None", | + | | | | "autoMappingStrategy" => "None", | + | | | | "traversalStrategy" => "None" | + | | | | ] | + | code | Symfony\Component\Validator\Constraints\NotBlank | Default, DummyClassOne | [ | + | | | | "allowNull" => false, | + | | | | "message" => "This value should not be blank.", | + | | | | "normalizer" => null, | + | | | | "payload" => null | + | | | | ] | + | email | property options | | [ | + | | | | "cascadeStrategy" => "None", | + | | | | "autoMappingStrategy" => "None", | + | | | | "traversalStrategy" => "None" | + | | | | ] | + | email | Symfony\Component\Validator\Constraints\Email | Default, DummyClassOne | [ | + | | | | "message" => "This value is not a valid email address.", | + | | | | "mode" => null, | + | | | | "normalizer" => null, | + | | | | "payload" => null | + | | | | ] | + | dummyClassTwo | property options | | [ | + | | | | "cascadeStrategy" => "Cascade", | + | | | | "autoMappingStrategy" => "None", | + | | | | "traversalStrategy" => "Implicit" | + | | | | ] | + +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ + + Symfony\Component\Validator\Tests\Dummy\DummyClassTwo + ----------------------------------------------------- + + +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ + | Property | Name | Groups | Options | + +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ + | - | Symfony\Component\Validator\Constraints\Expression | Default, DummyClassTwo | [ | + | | | | "expression" => "1 + 1 = 2", | + | | | | "message" => "This value is not valid.", | + | | | | "negate" => true, | + | | | | "payload" => null, | + | | | | "values" => [] | + | | | | ] | + | code | property options | | [ | + | | | | "cascadeStrategy" => "None", | + | | | | "autoMappingStrategy" => "None", | + | | | | "traversalStrategy" => "None" | + | | | | ] | + | code | Symfony\Component\Validator\Constraints\NotBlank | Default, DummyClassTwo | [ | + | | | | "allowNull" => false, | + | | | | "message" => "This value should not be blank.", | + | | | | "normalizer" => null, | + | | | | "payload" => null | + | | | | ] | + | email | property options | | [ | + | | | | "cascadeStrategy" => "None", | + | | | | "autoMappingStrategy" => "None", | + | | | | "traversalStrategy" => "None" | + | | | | ] | + | email | Symfony\Component\Validator\Constraints\Email | Default, DummyClassTwo | [ | + | | | | "message" => "This value is not a valid email address.", | + | | | | "mode" => null, | + | | | | "normalizer" => null, | + | | | | "payload" => null | + | | | | ] | + | dummyClassOne | property options | | [ | + | | | | "cascadeStrategy" => "None", | + | | | | "autoMappingStrategy" => "Disabled", | + | | | | "traversalStrategy" => "None" | + | | | | ] | + +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ + + TXT , $tester->getDisplay(true) ); } @@ -188,8 +188,8 @@ public function testOutputWithInvalidClassArgument() $tester->execute(['class' => 'App\\NotFoundResource'], ['decorated' => false]); $this->assertStringContainsString(<<getDisplay(true) ); } diff --git a/Tests/ConstraintViolationListTest.php b/Tests/ConstraintViolationListTest.php index ee7d53112..bc9472510 100644 --- a/Tests/ConstraintViolationListTest.php +++ b/Tests/ConstraintViolationListTest.php @@ -108,18 +108,18 @@ public function testToString() ]); $expected = <<<'EOF' -Root: - Error 1 -Root.foo.bar: - Error 2 -Root[baz]: - Error 3 -foo.bar: - Error 4 -[baz]: - Error 5 - -EOF; + Root: + Error 1 + Root.foo.bar: + Error 2 + Root[baz]: + Error 3 + foo.bar: + Error 4 + [baz]: + Error 5 + + EOF; $this->assertEquals($expected, (string) $this->list); } diff --git a/Tests/ConstraintViolationTest.php b/Tests/ConstraintViolationTest.php index dbac96a8a..2df314885 100644 --- a/Tests/ConstraintViolationTest.php +++ b/Tests/ConstraintViolationTest.php @@ -30,9 +30,9 @@ public function testToStringHandlesArrays() ); $expected = <<<'EOF' -Root.property.path: - Array -EOF; + Root.property.path: + Array + EOF; $this->assertSame($expected, (string) $violation); } @@ -49,9 +49,9 @@ public function testToStringHandlesArrayRoots() ); $expected = <<<'EOF' -Array.some_value: - 42 cannot be used here -EOF; + Array.some_value: + 42 cannot be used here + EOF; $this->assertSame($expected, (string) $violation); } @@ -70,9 +70,9 @@ public function testToStringHandlesCodes() ); $expected = <<<'EOF' -Array.some_value: - 42 cannot be used here (code 0) -EOF; + Array.some_value: + 42 cannot be used here (code 0) + EOF; $this->assertSame($expected, (string) $violation); } @@ -80,9 +80,9 @@ public function testToStringHandlesCodes() public function testToStringOmitsEmptyCodes() { $expected = <<<'EOF' -Array.some_value: - 42 cannot be used here -EOF; + Array.some_value: + 42 cannot be used here + EOF; $violation = new ConstraintViolation( '42 cannot be used here', @@ -124,9 +124,9 @@ public function testMessageCanBeStringableObject() ); $expected = <<<'EOF' -Root.property.path: - toString -EOF; + Root.property.path: + toString + EOF; $this->assertSame($expected, (string) $violation); $this->assertSame($message, $violation->getMessage()); } From 52576823ca32bf1a825468bfd31a517c39059141 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 1 Aug 2025 14:58:41 +0200 Subject: [PATCH 24/57] run tests with PHPUnit 12.3 --- Tests/Constraints/LengthValidatorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Constraints/LengthValidatorTest.php b/Tests/Constraints/LengthValidatorTest.php index 86f90a69c..21d9b2807 100644 --- a/Tests/Constraints/LengthValidatorTest.php +++ b/Tests/Constraints/LengthValidatorTest.php @@ -117,7 +117,7 @@ public static function getThreeCharactersWithWhitespaces() } #[DataProvider('getFiveOrMoreCharacters')] - public function testValidValuesMin(int|string $value) + public function testValidValuesMin(int|string $value, int $valueLength) { $constraint = new Length(min: 5); $this->validator->validate($value, $constraint); @@ -126,7 +126,7 @@ public function testValidValuesMin(int|string $value) } #[DataProvider('getThreeOrLessCharacters')] - public function testValidValuesMax(int|string $value) + public function testValidValuesMax(int|string $value, int $valueLength) { $constraint = new Length(max: 3); $this->validator->validate($value, $constraint); From 7b33be5c0691d1af19213fda63f2db658d689ee5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 12 Aug 2025 15:30:12 +0200 Subject: [PATCH 25/57] Fix tests --- Test/ConstraintValidatorTestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Test/ConstraintValidatorTestCase.php b/Test/ConstraintValidatorTestCase.php index 2fe70eaef..d112f86f7 100644 --- a/Test/ConstraintValidatorTestCase.php +++ b/Test/ConstraintValidatorTestCase.php @@ -97,7 +97,7 @@ protected function tearDown(): void { $this->restoreDefaultTimezone(); - if (class_exists(\Locale::class)) { + if (class_exists(\Locale::class) && isset($this->defaultLocale)) { \Locale::setDefault($this->defaultLocale); } } From ff739aab79f49028df323eefb3a4266b8d6e1938 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Sun, 10 Aug 2025 00:12:49 +0200 Subject: [PATCH 26/57] chore: PHP CS Fixer - update heredoc handling --- Tests/Command/DebugCommandTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tests/Command/DebugCommandTest.php b/Tests/Command/DebugCommandTest.php index ce2ff76fd..35f74a0c0 100644 --- a/Tests/Command/DebugCommandTest.php +++ b/Tests/Command/DebugCommandTest.php @@ -75,8 +75,8 @@ public function testOutputWithClassArgument() | | | | ] | +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ - TXT - , $tester->getDisplay(true) + TXT, + $tester->getDisplay(true) ); } @@ -173,8 +173,8 @@ public function testOutputWithPathArgument() | | | | ] | +---------------+----------------------------------------------------+------------------------+------------------------------------------------------------+ - TXT - , $tester->getDisplay(true) + TXT, + $tester->getDisplay(true) ); } @@ -189,8 +189,8 @@ public function testOutputWithInvalidClassArgument() $this->assertStringContainsString(<<getDisplay(true) + TXT, + $tester->getDisplay(true) ); } } From 697c805d8a7fc3adcee67c840cbfe148936af5bc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 14 Aug 2025 13:54:49 +0200 Subject: [PATCH 27/57] More cleanups related to internal sleep/wakeup usages --- Constraint.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Constraint.php b/Constraint.php index 5563500eb..c70a953ba 100644 --- a/Constraint.php +++ b/Constraint.php @@ -313,11 +313,22 @@ public function getTargets(): string|array * * @internal */ - public function __sleep(): array + public function __serialize(): array { // Initialize "groups" option if it is not set $this->groups; - return array_keys(get_object_vars($this)); + $data = []; + $class = $this::class; + foreach ((array) $this as $k => $v) { + $data[match (true) { + '' === $k || "\0" !== $k[0] => $k, + str_starts_with($k, "\0*\0") => substr($k, 3), + str_starts_with($k, "\0{$class}\0") => substr($k, 2 + \strlen($class)), + default => $k, + }] = $v; + } + + return $data; } } From 0c0fcbdaad41cad0b7ff8f5af31c572e349ed255 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 14 Aug 2025 15:15:05 +0200 Subject: [PATCH 28/57] [Validator] Deprecate implementing `__sleep/wakeup()` on GenericMetadata implementations --- CHANGELOG.md | 1 + Mapping/ClassMetadata.php | 51 ++++++++++++++++++++++++++++++++----- Mapping/GenericMetadata.php | 34 ++++++++++++++++++++++--- Mapping/MemberMetadata.php | 45 ++++++++++++++++++++++++++++++-- 4 files changed, 120 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c95fc1b84..9bc83027b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.4 --- + * Deprecate implementing `__sleep/wakeup()` on `GenericMetadata` implementations; use `__(un)serialize()` instead * Deprecate passing a list of choices to the first argument of the `Choice` constraint. Use the `choices` option instead * Add the `min` and `max` parameter to the `Length` constraint violation * Deprecate `getRequiredOptions()` and `getDefaultOption()` methods of the `All`, `AtLeastOneOf`, `CardScheme`, `Collection`, diff --git a/Mapping/ClassMetadata.php b/Mapping/ClassMetadata.php index d812255c4..582f75c5b 100644 --- a/Mapping/ClassMetadata.php +++ b/Mapping/ClassMetadata.php @@ -119,14 +119,53 @@ public function __construct(string $class) } } - public function __sleep(): array + public function __serialize(): array { - $parentProperties = parent::__sleep(); + if (self::class === (new \ReflectionMethod($this, '__sleep'))->class) { + return [ + 'constraints' => $this->constraints, + 'constraintsByGroup' => $this->constraintsByGroup, + 'traversalStrategy' => $this->traversalStrategy, + 'autoMappingStrategy' => $this->autoMappingStrategy, + 'getters' => $this->getters, + 'groupSequence' => $this->groupSequence, + 'groupSequenceProvider' => $this->groupSequenceProvider, + 'groupProvider' => $this->groupProvider, + 'members' => $this->members, + 'name' => $this->name, + 'properties' => $this->properties, + 'defaultGroup' => $this->defaultGroup, + ]; + } + + trigger_deprecation('symfony/validator', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); + + $data = []; + foreach ($this->__sleep() as $key) { + try { + if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) { + $data[$key] = $r->getValue($this); + } + } catch (\ReflectionException) { + $data[$key] = $this->$key; + } + } - // Don't store the cascading strategy. Classes never cascade. - unset($parentProperties[array_search('cascadingStrategy', $parentProperties)]); + return $data; + } + + /** + * @deprecated since Symfony 7.4, will be removed in 8.0 + */ + public function __sleep(): array + { + trigger_deprecation('symfony/validator', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); - return array_merge($parentProperties, [ + return [ + 'constraints', + 'constraintsByGroup', + 'traversalStrategy', + 'autoMappingStrategy', 'getters', 'groupSequence', 'groupSequenceProvider', @@ -135,7 +174,7 @@ public function __sleep(): array 'name', 'properties', 'defaultGroup', - ]); + ]; } public function getClassName(): string diff --git a/Mapping/GenericMetadata.php b/Mapping/GenericMetadata.php index 43992255c..b5f0005dd 100644 --- a/Mapping/GenericMetadata.php +++ b/Mapping/GenericMetadata.php @@ -83,13 +83,41 @@ class GenericMetadata implements MetadataInterface */ public int $autoMappingStrategy = AutoMappingStrategy::NONE; + public function __serialize(): array + { + if (self::class === (new \ReflectionMethod($this, '__sleep'))->class) { + return [ + 'constraints' => $this->constraints, + 'constraintsByGroup' => $this->constraintsByGroup, + 'cascadingStrategy' => $this->cascadingStrategy, + 'traversalStrategy' => $this->traversalStrategy, + 'autoMappingStrategy' => $this->autoMappingStrategy, + ]; + } + + trigger_deprecation('symfony/validator', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); + + $data = []; + foreach ($this->__sleep() as $key) { + try { + if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) { + $data[$key] = $r->getValue($this); + } + } catch (\ReflectionException) { + $data[$key] = $this->$key; + } + } + + return $data; + } + /** - * Returns the names of the properties that should be serialized. - * - * @return string[] + * @deprecated since Symfony 7.4, will be replaced by `__serialize()` in 8.0 */ public function __sleep(): array { + trigger_deprecation('symfony/validator', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); + return [ 'constraints', 'constraintsByGroup', diff --git a/Mapping/MemberMetadata.php b/Mapping/MemberMetadata.php index 6df8add12..076548ec4 100644 --- a/Mapping/MemberMetadata.php +++ b/Mapping/MemberMetadata.php @@ -76,13 +76,54 @@ public function addConstraint(Constraint $constraint): static return $this; } + public function __serialize(): array + { + if (self::class === (new \ReflectionMethod($this, '__sleep'))->class) { + return [ + 'constraints' => $this->constraints, + 'constraintsByGroup' => $this->constraintsByGroup, + 'cascadingStrategy' => $this->cascadingStrategy, + 'traversalStrategy' => $this->traversalStrategy, + 'autoMappingStrategy' => $this->autoMappingStrategy, + 'class' => $this->class, + 'name' => $this->name, + 'property' => $this->property, + ]; + } + + trigger_deprecation('symfony/validator', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); + + $data = []; + foreach ($this->__sleep() as $key) { + try { + if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) { + $data[$key] = $r->getValue($this); + } + } catch (\ReflectionException) { + $data[$key] = $this->$key; + } + } + + return $data; + } + + /** + * @deprecated since Symfony 7.4, will be replaced by `__serialize()` in 8.0 + */ public function __sleep(): array { - return array_merge(parent::__sleep(), [ + trigger_deprecation('symfony/validator', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); + + return [ + 'constraints', + 'constraintsByGroup', + 'cascadingStrategy', + 'traversalStrategy', + 'autoMappingStrategy', 'class', 'name', 'property', - ]); + ]; } /** From dfa835d9f3a72eb820d3a9777999f4e1db4fedde Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 14 Aug 2025 16:45:04 +0200 Subject: [PATCH 29/57] [Mime] Deprecate implementing `__sleep/wakeup()` on `AbstractPart` implementations --- Mapping/ClassMetadata.php | 2 +- Mapping/GenericMetadata.php | 2 +- Mapping/MemberMetadata.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Mapping/ClassMetadata.php b/Mapping/ClassMetadata.php index 582f75c5b..c1580f93c 100644 --- a/Mapping/ClassMetadata.php +++ b/Mapping/ClassMetadata.php @@ -121,7 +121,7 @@ public function __construct(string $class) public function __serialize(): array { - if (self::class === (new \ReflectionMethod($this, '__sleep'))->class) { + if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { return [ 'constraints' => $this->constraints, 'constraintsByGroup' => $this->constraintsByGroup, diff --git a/Mapping/GenericMetadata.php b/Mapping/GenericMetadata.php index b5f0005dd..9b184fa36 100644 --- a/Mapping/GenericMetadata.php +++ b/Mapping/GenericMetadata.php @@ -85,7 +85,7 @@ class GenericMetadata implements MetadataInterface public function __serialize(): array { - if (self::class === (new \ReflectionMethod($this, '__sleep'))->class) { + if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { return [ 'constraints' => $this->constraints, 'constraintsByGroup' => $this->constraintsByGroup, diff --git a/Mapping/MemberMetadata.php b/Mapping/MemberMetadata.php index 076548ec4..1b84d08d3 100644 --- a/Mapping/MemberMetadata.php +++ b/Mapping/MemberMetadata.php @@ -78,7 +78,7 @@ public function addConstraint(Constraint $constraint): static public function __serialize(): array { - if (self::class === (new \ReflectionMethod($this, '__sleep'))->class) { + if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { return [ 'constraints' => $this->constraints, 'constraintsByGroup' => $this->constraintsByGroup, From 125ecb7811cf2cbf78248ef7d5ff334d84419016 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 14 Aug 2025 17:18:52 +0200 Subject: [PATCH 30/57] [HttpKernel][Mime][Serializer][String][Validator] Replace `__sleep/wakeup()` by `__(un)serialize()` --- CHANGELOG.md | 1 + Mapping/ClassMetadata.php | 64 +++++++------------------------------ Mapping/GenericMetadata.php | 43 +++---------------------- Mapping/MemberMetadata.php | 52 +++++------------------------- 4 files changed, 26 insertions(+), 134 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77835dfd8..1bfe4a706 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Add method `getGroupProvider()` to `ClassMetadataInterface` + * Replace `__sleep/wakeup()` by `__(un)serialize()` on `GenericMetadata` implementations * Remove the `getRequiredOptions()` and `getDefaultOption()` methods from the `All`, `AtLeastOneOf`, `CardScheme`, `Collection`, `CssColor`, `Expression`, `Regex`, `Sequentially`, `Type`, and `When` constraints * Remove support for evaluating options in the base `Constraint` class. Initialize properties in the constructor of the concrete constraint diff --git a/Mapping/ClassMetadata.php b/Mapping/ClassMetadata.php index c1580f93c..668e5d190 100644 --- a/Mapping/ClassMetadata.php +++ b/Mapping/ClassMetadata.php @@ -121,59 +121,19 @@ public function __construct(string $class) public function __serialize(): array { - if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { - return [ - 'constraints' => $this->constraints, - 'constraintsByGroup' => $this->constraintsByGroup, - 'traversalStrategy' => $this->traversalStrategy, - 'autoMappingStrategy' => $this->autoMappingStrategy, - 'getters' => $this->getters, - 'groupSequence' => $this->groupSequence, - 'groupSequenceProvider' => $this->groupSequenceProvider, - 'groupProvider' => $this->groupProvider, - 'members' => $this->members, - 'name' => $this->name, - 'properties' => $this->properties, - 'defaultGroup' => $this->defaultGroup, - ]; - } - - trigger_deprecation('symfony/validator', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); - - $data = []; - foreach ($this->__sleep() as $key) { - try { - if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) { - $data[$key] = $r->getValue($this); - } - } catch (\ReflectionException) { - $data[$key] = $this->$key; - } - } - - return $data; - } - - /** - * @deprecated since Symfony 7.4, will be removed in 8.0 - */ - public function __sleep(): array - { - trigger_deprecation('symfony/validator', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); - return [ - 'constraints', - 'constraintsByGroup', - 'traversalStrategy', - 'autoMappingStrategy', - 'getters', - 'groupSequence', - 'groupSequenceProvider', - 'groupProvider', - 'members', - 'name', - 'properties', - 'defaultGroup', + 'constraints' => $this->constraints, + 'constraintsByGroup' => $this->constraintsByGroup, + 'traversalStrategy' => $this->traversalStrategy, + 'autoMappingStrategy' => $this->autoMappingStrategy, + 'getters' => $this->getters, + 'groupSequence' => $this->groupSequence, + 'groupSequenceProvider' => $this->groupSequenceProvider, + 'groupProvider' => $this->groupProvider, + 'members' => $this->members, + 'name' => $this->name, + 'properties' => $this->properties, + 'defaultGroup' => $this->defaultGroup, ]; } diff --git a/Mapping/GenericMetadata.php b/Mapping/GenericMetadata.php index 9b184fa36..b5fc3be50 100644 --- a/Mapping/GenericMetadata.php +++ b/Mapping/GenericMetadata.php @@ -85,45 +85,12 @@ class GenericMetadata implements MetadataInterface public function __serialize(): array { - if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { - return [ - 'constraints' => $this->constraints, - 'constraintsByGroup' => $this->constraintsByGroup, - 'cascadingStrategy' => $this->cascadingStrategy, - 'traversalStrategy' => $this->traversalStrategy, - 'autoMappingStrategy' => $this->autoMappingStrategy, - ]; - } - - trigger_deprecation('symfony/validator', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); - - $data = []; - foreach ($this->__sleep() as $key) { - try { - if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) { - $data[$key] = $r->getValue($this); - } - } catch (\ReflectionException) { - $data[$key] = $this->$key; - } - } - - return $data; - } - - /** - * @deprecated since Symfony 7.4, will be replaced by `__serialize()` in 8.0 - */ - public function __sleep(): array - { - trigger_deprecation('symfony/validator', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); - return [ - 'constraints', - 'constraintsByGroup', - 'cascadingStrategy', - 'traversalStrategy', - 'autoMappingStrategy', + 'constraints' => $this->constraints, + 'constraintsByGroup' => $this->constraintsByGroup, + 'cascadingStrategy' => $this->cascadingStrategy, + 'traversalStrategy' => $this->traversalStrategy, + 'autoMappingStrategy' => $this->autoMappingStrategy, ]; } diff --git a/Mapping/MemberMetadata.php b/Mapping/MemberMetadata.php index 1b84d08d3..d834fb58b 100644 --- a/Mapping/MemberMetadata.php +++ b/Mapping/MemberMetadata.php @@ -78,51 +78,15 @@ public function addConstraint(Constraint $constraint): static public function __serialize(): array { - if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { - return [ - 'constraints' => $this->constraints, - 'constraintsByGroup' => $this->constraintsByGroup, - 'cascadingStrategy' => $this->cascadingStrategy, - 'traversalStrategy' => $this->traversalStrategy, - 'autoMappingStrategy' => $this->autoMappingStrategy, - 'class' => $this->class, - 'name' => $this->name, - 'property' => $this->property, - ]; - } - - trigger_deprecation('symfony/validator', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); - - $data = []; - foreach ($this->__sleep() as $key) { - try { - if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) { - $data[$key] = $r->getValue($this); - } - } catch (\ReflectionException) { - $data[$key] = $this->$key; - } - } - - return $data; - } - - /** - * @deprecated since Symfony 7.4, will be replaced by `__serialize()` in 8.0 - */ - public function __sleep(): array - { - trigger_deprecation('symfony/validator', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); - return [ - 'constraints', - 'constraintsByGroup', - 'cascadingStrategy', - 'traversalStrategy', - 'autoMappingStrategy', - 'class', - 'name', - 'property', + 'constraints' => $this->constraints, + 'constraintsByGroup' => $this->constraintsByGroup, + 'cascadingStrategy' => $this->cascadingStrategy, + 'traversalStrategy' => $this->traversalStrategy, + 'autoMappingStrategy' => $this->autoMappingStrategy, + 'class' => $this->class, + 'name' => $this->name, + 'property' => $this->property, ]; } From a9eb369e14981da4a1a2c87e9da9bb7807f602b8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 18 Aug 2025 09:51:41 +0200 Subject: [PATCH 31/57] [Validator] Optimize serialized metadata and cleanup tests --- Constraint.php | 2 -- Mapping/ClassMetadata.php | 15 ++++------- Mapping/GenericMetadata.php | 18 ++++++++----- Mapping/MemberMetadata.php | 16 ++--------- Tests/Constraints/BicValidatorTest.php | 4 +-- Tests/Constraints/CardSchemeTest.php | 6 ++--- Tests/Constraints/CharsetTest.php | 4 +-- Tests/Constraints/ChoiceTest.php | 8 +++--- Tests/Constraints/CidrTest.php | 6 ++--- Tests/Constraints/CountTest.php | 6 ++--- Tests/Constraints/CountryTest.php | 6 ++--- Tests/Constraints/CssColorTest.php | 6 ++--- Tests/Constraints/CurrencyTest.php | 4 +-- Tests/Constraints/DateTest.php | 4 +-- Tests/Constraints/DateTimeTest.php | 6 ++--- Tests/Constraints/DivisibleByTest.php | 6 ++--- Tests/Constraints/EmailTest.php | 6 ++--- Tests/Constraints/EqualToTest.php | 6 ++--- Tests/Constraints/ExpressionSyntaxTest.php | 8 +++--- Tests/Constraints/ExpressionTest.php | 6 ++--- Tests/Constraints/FileTest.php | 6 ++--- Tests/Constraints/GreaterThanOrEqualTest.php | 6 ++--- Tests/Constraints/GreaterThanTest.php | 6 ++--- Tests/Constraints/HostnameTest.php | 6 ++--- Tests/Constraints/IbanValidatorTest.php | 2 +- Tests/Constraints/IdenticalToTest.php | 6 ++--- Tests/Constraints/ImageTest.php | 6 ++--- Tests/Constraints/IpTest.php | 6 ++--- Tests/Constraints/IsbnTest.php | 6 ++--- Tests/Constraints/IsinTest.php | 4 +-- Tests/Constraints/IssnTest.php | 6 ++--- Tests/Constraints/JsonTest.php | 4 +-- Tests/Constraints/LanguageTest.php | 6 ++--- Tests/Constraints/LengthTest.php | 6 ++--- Tests/Constraints/LessThanOrEqualTest.php | 6 ++--- Tests/Constraints/LessThanTest.php | 6 ++--- Tests/Constraints/LocaleTest.php | 6 ++--- Tests/Constraints/LuhnTest.php | 4 +-- Tests/Constraints/MacAddressTest.php | 6 ++--- Tests/Constraints/NegativeOrZeroTest.php | 4 +-- Tests/Constraints/NegativeTest.php | 4 +-- Tests/Constraints/NotBlankTest.php | 4 +-- .../NotCompromisedPasswordTest.php | 6 ++--- Tests/Constraints/NotEqualToTest.php | 6 ++--- Tests/Constraints/NotIdenticalToTest.php | 6 ++--- Tests/Constraints/PositiveOrZeroTest.php | 4 +-- Tests/Constraints/PositiveTest.php | 4 +-- Tests/Constraints/RegexTest.php | 6 ++--- Tests/Constraints/TimeTest.php | 4 +-- Tests/Constraints/TimezoneTest.php | 6 ++--- Tests/Constraints/TypeTest.php | 6 ++--- Tests/Constraints/UlidTest.php | 4 +-- Tests/Constraints/UniqueTest.php | 6 ++--- Tests/Constraints/UrlTest.php | 8 +++--- Tests/Constraints/UuidTest.php | 6 ++--- Tests/Constraints/ValidTest.php | 4 +-- Tests/Constraints/WeekTest.php | 4 +-- Tests/Constraints/WhenTest.php | 12 ++++----- Tests/Constraints/WordCountTest.php | 6 ++--- Tests/Constraints/YamlTest.php | 6 ++--- Tests/Mapping/ClassMetadataTest.php | 27 +++++-------------- .../Mapping/Loader/PropertyInfoLoaderTest.php | 2 +- Tests/Mapping/PropertyMetadataTest.php | 6 +++-- 63 files changed, 186 insertions(+), 212 deletions(-) diff --git a/Constraint.php b/Constraint.php index c70a953ba..47dd9b42d 100644 --- a/Constraint.php +++ b/Constraint.php @@ -310,8 +310,6 @@ public function getTargets(): string|array /** * Optimizes the serialized value to minimize storage space. - * - * @internal */ public function __serialize(): array { diff --git a/Mapping/ClassMetadata.php b/Mapping/ClassMetadata.php index c1580f93c..0e52e5fef 100644 --- a/Mapping/ClassMetadata.php +++ b/Mapping/ClassMetadata.php @@ -122,11 +122,9 @@ public function __construct(string $class) public function __serialize(): array { if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { - return [ - 'constraints' => $this->constraints, - 'constraintsByGroup' => $this->constraintsByGroup, - 'traversalStrategy' => $this->traversalStrategy, - 'autoMappingStrategy' => $this->autoMappingStrategy, + return array_filter([ + 'traversalStrategy' => TraversalStrategy::IMPLICIT !== $this->traversalStrategy ? $this->traversalStrategy : null, + ] + parent::__serialize() + [ 'getters' => $this->getters, 'groupSequence' => $this->groupSequence, 'groupSequenceProvider' => $this->groupSequenceProvider, @@ -135,7 +133,7 @@ public function __serialize(): array 'name' => $this->name, 'properties' => $this->properties, 'defaultGroup' => $this->defaultGroup, - ]; + ]); } trigger_deprecation('symfony/validator', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); @@ -377,11 +375,8 @@ public function mergeConstraints(self $source): void $member = clone $member; foreach ($member->getConstraints() as $constraint) { - if (\in_array($constraint::DEFAULT_GROUP, $constraint->groups, true)) { - $member->constraintsByGroup[$this->getDefaultGroup()][] = $constraint; - } - $constraint->addImplicitGroupName($this->getDefaultGroup()); + $member->addConstraint($constraint); } if ($member instanceof MemberMetadata && !$member->isPrivate($this->name)) { diff --git a/Mapping/GenericMetadata.php b/Mapping/GenericMetadata.php index 9b184fa36..f2e6074b7 100644 --- a/Mapping/GenericMetadata.php +++ b/Mapping/GenericMetadata.php @@ -86,13 +86,13 @@ class GenericMetadata implements MetadataInterface public function __serialize(): array { if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { - return [ + return array_filter([ 'constraints' => $this->constraints, 'constraintsByGroup' => $this->constraintsByGroup, - 'cascadingStrategy' => $this->cascadingStrategy, - 'traversalStrategy' => $this->traversalStrategy, - 'autoMappingStrategy' => $this->autoMappingStrategy, - ]; + 'cascadingStrategy' => CascadingStrategy::NONE !== $this->cascadingStrategy ? $this->cascadingStrategy : null, + 'traversalStrategy' => TraversalStrategy::NONE !== $this->traversalStrategy ? $this->traversalStrategy : null, + 'autoMappingStrategy' => AutoMappingStrategy::NONE !== $this->autoMappingStrategy ? $this->autoMappingStrategy : null, + ]); } trigger_deprecation('symfony/validator', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this)); @@ -183,10 +183,14 @@ public function addConstraint(Constraint $constraint): static return $this; } - $this->constraints[] = $constraint; + if (!\in_array($constraint, $this->constraints, true)) { + $this->constraints[] = $constraint; + } foreach ($constraint->groups as $group) { - $this->constraintsByGroup[$group][] = $constraint; + if (!\in_array($constraint, $this->constraintsByGroup[$group] ??= [], true)) { + $this->constraintsByGroup[$group][] = $constraint; + } } return $this; diff --git a/Mapping/MemberMetadata.php b/Mapping/MemberMetadata.php index 1b84d08d3..4ac029219 100644 --- a/Mapping/MemberMetadata.php +++ b/Mapping/MemberMetadata.php @@ -79,7 +79,7 @@ public function addConstraint(Constraint $constraint): static public function __serialize(): array { if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { - return [ + return parent::__serialize() + [ 'constraints' => $this->constraints, 'constraintsByGroup' => $this->constraintsByGroup, 'cascadingStrategy' => $this->cascadingStrategy, @@ -127,7 +127,7 @@ public function __sleep(): array } /** - * Returns the name of the member. + * Returns the name of the property or its getter. */ public function getName(): string { @@ -144,33 +144,21 @@ public function getPropertyName(): string return $this->property; } - /** - * Returns whether this member is public. - */ public function isPublic(object|string $objectOrClassName): bool { return $this->getReflectionMember($objectOrClassName)->isPublic(); } - /** - * Returns whether this member is protected. - */ public function isProtected(object|string $objectOrClassName): bool { return $this->getReflectionMember($objectOrClassName)->isProtected(); } - /** - * Returns whether this member is private. - */ public function isPrivate(object|string $objectOrClassName): bool { return $this->getReflectionMember($objectOrClassName)->isPrivate(); } - /** - * Returns the reflection instance for accessing the member's value. - */ public function getReflectionMember(object|string $objectOrClassName): \ReflectionMethod|\ReflectionProperty { $className = \is_string($objectOrClassName) ? $objectOrClassName : $objectOrClassName::class; diff --git a/Tests/Constraints/BicValidatorTest.php b/Tests/Constraints/BicValidatorTest.php index 6c1f275e9..2bb14a327 100644 --- a/Tests/Constraints/BicValidatorTest.php +++ b/Tests/Constraints/BicValidatorTest.php @@ -79,7 +79,7 @@ public function testInvalidComparisonToPropertyPathFromAttribute() $classMetadata = new ClassMetadata(BicDummy::class); (new AttributeLoader())->loadClassMetadata($classMetadata); - [$constraint] = $classMetadata->properties['bic1']->constraints; + [$constraint] = $classMetadata->getPropertyMetadata('bic1')[0]->getConstraints(); $this->setObject(new BicDummy()); @@ -130,7 +130,7 @@ public function testInvalidComparisonToValueFromAttribute() $classMetadata = new ClassMetadata(BicDummy::class); (new AttributeLoader())->loadClassMetadata($classMetadata); - [$constraint] = $classMetadata->properties['bic1']->constraints; + [$constraint] = $classMetadata->getPropertyMetadata('bic1')[0]->getConstraints(); $this->validator->validate('UNCRIT2B912', $constraint); diff --git a/Tests/Constraints/CardSchemeTest.php b/Tests/Constraints/CardSchemeTest.php index cdd78a7d4..6c59556af 100644 --- a/Tests/Constraints/CardSchemeTest.php +++ b/Tests/Constraints/CardSchemeTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame([CardScheme::MASTERCARD, CardScheme::VISA], $aConstraint->schemes); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame([CardScheme::AMEX], $bConstraint->schemes); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'CardSchemeDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame([CardScheme::DINERS], $cConstraint->schemes); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/Tests/Constraints/CharsetTest.php b/Tests/Constraints/CharsetTest.php index 1b23a2ea7..4091c5ec3 100644 --- a/Tests/Constraints/CharsetTest.php +++ b/Tests/Constraints/CharsetTest.php @@ -47,10 +47,10 @@ public function testAttributes() $loader = new AttributeLoader(); $this->assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); $this->assertSame('UTF-8', $aConstraint->encodings); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); $this->assertSame(['ASCII', 'UTF-8'], $bConstraint->encodings); } } diff --git a/Tests/Constraints/ChoiceTest.php b/Tests/Constraints/ChoiceTest.php index a74991575..89adb5228 100644 --- a/Tests/Constraints/ChoiceTest.php +++ b/Tests/Constraints/ChoiceTest.php @@ -37,24 +37,24 @@ public function testAttributes() self::assertTrue($loader->loadClassMetadata($metadata)); /** @var Choice $aConstraint */ - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame([1, 2], $aConstraint->choices); self::assertSame(['Default', 'ChoiceDummy'], $aConstraint->groups); /** @var Choice $bConstraint */ - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(['foo', 'bar'], $bConstraint->choices); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'ChoiceDummy'], $bConstraint->groups); /** @var Choice $cConstraint */ - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame([1, 2], $aConstraint->choices); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); /** @var Choice $stringIndexedConstraint */ - [$stringIndexedConstraint] = $metadata->properties['stringIndexed']->getConstraints(); + [$stringIndexedConstraint] = $metadata->getPropertyMetadata('stringIndexed')[0]->getConstraints(); self::assertSame(['one' => 1, 'two' => 2], $stringIndexedConstraint->choices); } } diff --git a/Tests/Constraints/CidrTest.php b/Tests/Constraints/CidrTest.php index 9653cba73..a6dd780fb 100644 --- a/Tests/Constraints/CidrTest.php +++ b/Tests/Constraints/CidrTest.php @@ -131,19 +131,19 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(Ip::ALL, $aConstraint->version); self::assertSame(0, $aConstraint->netmaskMin); self::assertSame(128, $aConstraint->netmaskMax); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(Ip::V6, $bConstraint->version); self::assertSame('myMessage', $bConstraint->message); self::assertSame(10, $bConstraint->netmaskMin); self::assertSame(126, $bConstraint->netmaskMax); self::assertSame(['Default', 'CidrDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/CountTest.php b/Tests/Constraints/CountTest.php index 42843e12d..0f59baf8c 100644 --- a/Tests/Constraints/CountTest.php +++ b/Tests/Constraints/CountTest.php @@ -24,12 +24,12 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(42, $aConstraint->min); self::assertSame(42, $aConstraint->max); self::assertNull($aConstraint->divisibleBy); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(1, $bConstraint->min); self::assertSame(4711, $bConstraint->max); self::assertNull($bConstraint->divisibleBy); @@ -37,7 +37,7 @@ public function testAttributes() self::assertSame('myMaxMessage', $bConstraint->maxMessage); self::assertSame(['Default', 'CountDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertNull($cConstraint->min); self::assertNull($cConstraint->max); self::assertSame(10, $cConstraint->divisibleBy); diff --git a/Tests/Constraints/CountryTest.php b/Tests/Constraints/CountryTest.php index 4bd85933d..201dfaa61 100644 --- a/Tests/Constraints/CountryTest.php +++ b/Tests/Constraints/CountryTest.php @@ -24,15 +24,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertFalse($aConstraint->alpha3); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertTrue($bConstraint->alpha3); self::assertSame(['Default', 'CountryDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/CssColorTest.php b/Tests/Constraints/CssColorTest.php index e1e3e2501..ebd657e71 100644 --- a/Tests/Constraints/CssColorTest.php +++ b/Tests/Constraints/CssColorTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame([CssColor::HEX_LONG, CssColor::HEX_SHORT], $aConstraint->formats); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame([CssColor::HEX_LONG], $bConstraint->formats); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'CssColorDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame([CssColor::HEX_SHORT], $cConstraint->formats); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/Tests/Constraints/CurrencyTest.php b/Tests/Constraints/CurrencyTest.php index 6cfb6bfc3..356799c45 100644 --- a/Tests/Constraints/CurrencyTest.php +++ b/Tests/Constraints/CurrencyTest.php @@ -24,11 +24,11 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'CurrencyDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/DateTest.php b/Tests/Constraints/DateTest.php index 83c75328e..cdff353da 100644 --- a/Tests/Constraints/DateTest.php +++ b/Tests/Constraints/DateTest.php @@ -24,11 +24,11 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'DateDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/DateTimeTest.php b/Tests/Constraints/DateTimeTest.php index 172d1a290..d8891fe5b 100644 --- a/Tests/Constraints/DateTimeTest.php +++ b/Tests/Constraints/DateTimeTest.php @@ -24,15 +24,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame('Y-m-d H:i:s', $aConstraint->format); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('d.m.Y', $bConstraint->format); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'DateTimeDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame('m/d/Y', $cConstraint->format); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/Tests/Constraints/DivisibleByTest.php b/Tests/Constraints/DivisibleByTest.php index bfe0a6cac..7c9275ea9 100644 --- a/Tests/Constraints/DivisibleByTest.php +++ b/Tests/Constraints/DivisibleByTest.php @@ -24,16 +24,16 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'DivisibleByDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/Tests/Constraints/EmailTest.php b/Tests/Constraints/EmailTest.php index 2a6302eb4..b57784b89 100644 --- a/Tests/Constraints/EmailTest.php +++ b/Tests/Constraints/EmailTest.php @@ -79,16 +79,16 @@ public function testAttribute() $metadata = new ClassMetadata(EmailDummy::class); (new AttributeLoader())->loadClassMetadata($metadata); - [$aConstraint] = $metadata->properties['a']->constraints; + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertNull($aConstraint->mode); self::assertNull($aConstraint->normalizer); - [$bConstraint] = $metadata->properties['b']->constraints; + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(Email::VALIDATION_MODE_HTML5, $bConstraint->mode); self::assertSame('trim', $bConstraint->normalizer); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/EqualToTest.php b/Tests/Constraints/EqualToTest.php index 56e40dbdd..ae0f97cfd 100644 --- a/Tests/Constraints/EqualToTest.php +++ b/Tests/Constraints/EqualToTest.php @@ -24,16 +24,16 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'EqualToDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/Tests/Constraints/ExpressionSyntaxTest.php b/Tests/Constraints/ExpressionSyntaxTest.php index 56caa358e..745a49c10 100644 --- a/Tests/Constraints/ExpressionSyntaxTest.php +++ b/Tests/Constraints/ExpressionSyntaxTest.php @@ -42,7 +42,7 @@ public static function provideServiceValidatedConstraints(): iterable $metadata = new ClassMetadata(ExpressionSyntaxDummy::class); self::assertTrue((new AttributeLoader())->loadClassMetadata($metadata)); - yield 'attribute' => [$metadata->properties['b']->constraints[0]]; + yield 'attribute' => [$metadata->getPropertyMetadata('b')[0]->getConstraints()[0]]; } #[IgnoreDeprecations] @@ -59,16 +59,16 @@ public function testAttributes() $metadata = new ClassMetadata(ExpressionSyntaxDummy::class); self::assertTrue((new AttributeLoader())->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertNull($aConstraint->service); self::assertNull($aConstraint->allowedVariables); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('my_service', $bConstraint->service); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'ExpressionSyntaxDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['foo', 'bar'], $cConstraint->allowedVariables); self::assertSame(['my_group'], $cConstraint->groups); } diff --git a/Tests/Constraints/ExpressionTest.php b/Tests/Constraints/ExpressionTest.php index 61d11fb8a..d8f9fee9c 100644 --- a/Tests/Constraints/ExpressionTest.php +++ b/Tests/Constraints/ExpressionTest.php @@ -26,18 +26,18 @@ public function testAttributes() $metadata = new ClassMetadata(ExpressionDummy::class); self::assertTrue((new AttributeLoader())->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame('value == "1"', $aConstraint->expression); self::assertSame([], $aConstraint->values); self::assertTrue($aConstraint->negate); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('value == "1"', $bConstraint->expression); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'ExpressionDummy'], $bConstraint->groups); self::assertTrue($bConstraint->negate); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame('value == someVariable', $cConstraint->expression); self::assertSame(['someVariable' => 42], $cConstraint->values); self::assertSame(['foo'], $cConstraint->groups); diff --git a/Tests/Constraints/FileTest.php b/Tests/Constraints/FileTest.php index bcf03517a..2926ecec6 100644 --- a/Tests/Constraints/FileTest.php +++ b/Tests/Constraints/FileTest.php @@ -165,15 +165,15 @@ public function testAttributes() $metadata = new ClassMetadata(FileDummy::class); self::assertTrue((new AttributeLoader())->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertNull($aConstraint->maxSize); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(100, $bConstraint->maxSize); self::assertSame('myMessage', $bConstraint->notFoundMessage); self::assertSame(['Default', 'FileDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(100000, $cConstraint->maxSize); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/Tests/Constraints/GreaterThanOrEqualTest.php b/Tests/Constraints/GreaterThanOrEqualTest.php index 270ac5296..b73a32885 100644 --- a/Tests/Constraints/GreaterThanOrEqualTest.php +++ b/Tests/Constraints/GreaterThanOrEqualTest.php @@ -24,16 +24,16 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'GreaterThanOrEqualDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/Tests/Constraints/GreaterThanTest.php b/Tests/Constraints/GreaterThanTest.php index 8dd797cf4..ea962837a 100644 --- a/Tests/Constraints/GreaterThanTest.php +++ b/Tests/Constraints/GreaterThanTest.php @@ -24,16 +24,16 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'GreaterThanDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/Tests/Constraints/HostnameTest.php b/Tests/Constraints/HostnameTest.php index f6189c8d9..a01c256a5 100644 --- a/Tests/Constraints/HostnameTest.php +++ b/Tests/Constraints/HostnameTest.php @@ -24,15 +24,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertTrue($aConstraint->requireTld); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertFalse($bConstraint->requireTld); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'HostnameDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/IbanValidatorTest.php b/Tests/Constraints/IbanValidatorTest.php index 6a349bcaa..f2a596606 100644 --- a/Tests/Constraints/IbanValidatorTest.php +++ b/Tests/Constraints/IbanValidatorTest.php @@ -456,7 +456,7 @@ public function testLoadFromAttribute() $classMetadata = new ClassMetadata(IbanDummy::class); (new AttributeLoader())->loadClassMetadata($classMetadata); - [$constraint] = $classMetadata->properties['iban']->constraints; + [$constraint] = $classMetadata->getPropertyMetadata('iban')[0]->getConstraints(); $this->validator->validate('DE89 3704 0044 0532 0130 01', $constraint); diff --git a/Tests/Constraints/IdenticalToTest.php b/Tests/Constraints/IdenticalToTest.php index 6eb7044c6..da91a174b 100644 --- a/Tests/Constraints/IdenticalToTest.php +++ b/Tests/Constraints/IdenticalToTest.php @@ -24,16 +24,16 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'IdenticalToDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/Tests/Constraints/ImageTest.php b/Tests/Constraints/ImageTest.php index df5b14c07..60641dd4c 100644 --- a/Tests/Constraints/ImageTest.php +++ b/Tests/Constraints/ImageTest.php @@ -24,20 +24,20 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertNull($aConstraint->minWidth); self::assertNull($aConstraint->maxWidth); self::assertNull($aConstraint->minHeight); self::assertNull($aConstraint->maxHeight); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(50, $bConstraint->minWidth); self::assertSame(200, $bConstraint->maxWidth); self::assertSame(50, $bConstraint->minHeight); self::assertSame(200, $bConstraint->maxHeight); self::assertSame(['Default', 'ImageDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(100000, $cConstraint->maxSize); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/Tests/Constraints/IpTest.php b/Tests/Constraints/IpTest.php index 01545c77c..7a9f64b13 100644 --- a/Tests/Constraints/IpTest.php +++ b/Tests/Constraints/IpTest.php @@ -55,16 +55,16 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(Ip::V4, $aConstraint->version); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(Ip::V6, $bConstraint->version); self::assertSame('myMessage', $bConstraint->message); self::assertSame('trim', $bConstraint->normalizer); self::assertSame(['Default', 'IpDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/IsbnTest.php b/Tests/Constraints/IsbnTest.php index d11088376..f11d67d1e 100644 --- a/Tests/Constraints/IsbnTest.php +++ b/Tests/Constraints/IsbnTest.php @@ -24,15 +24,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertNull($aConstraint->type); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(Isbn::ISBN_13, $bConstraint->type); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'IsbnDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/IsinTest.php b/Tests/Constraints/IsinTest.php index 05d24a32d..d182dfc9a 100644 --- a/Tests/Constraints/IsinTest.php +++ b/Tests/Constraints/IsinTest.php @@ -24,11 +24,11 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'IsinDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/IssnTest.php b/Tests/Constraints/IssnTest.php index c21648bd6..e32278a6e 100644 --- a/Tests/Constraints/IssnTest.php +++ b/Tests/Constraints/IssnTest.php @@ -24,17 +24,17 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertFalse($aConstraint->caseSensitive); self::assertFalse($aConstraint->requireHyphen); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertTrue($bConstraint->caseSensitive); self::assertTrue($bConstraint->requireHyphen); self::assertSame(['Default', 'IssnDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/JsonTest.php b/Tests/Constraints/JsonTest.php index 17208425f..34fdd5b23 100644 --- a/Tests/Constraints/JsonTest.php +++ b/Tests/Constraints/JsonTest.php @@ -24,11 +24,11 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'JsonDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/LanguageTest.php b/Tests/Constraints/LanguageTest.php index fe0c5e711..fbc83b4e3 100644 --- a/Tests/Constraints/LanguageTest.php +++ b/Tests/Constraints/LanguageTest.php @@ -24,15 +24,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertFalse($aConstraint->alpha3); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertTrue($bConstraint->alpha3); self::assertSame(['Default', 'LanguageDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/LengthTest.php b/Tests/Constraints/LengthTest.php index 8859e68a8..b72ecb7f0 100644 --- a/Tests/Constraints/LengthTest.php +++ b/Tests/Constraints/LengthTest.php @@ -95,11 +95,11 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(42, $aConstraint->min); self::assertSame(42, $aConstraint->max); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(1, $bConstraint->min); self::assertSame(4711, $bConstraint->max); self::assertSame('myMinMessage', $bConstraint->minMessage); @@ -108,7 +108,7 @@ public function testAttributes() self::assertSame('ISO-8859-15', $bConstraint->charset); self::assertSame(['Default', 'LengthDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/LessThanOrEqualTest.php b/Tests/Constraints/LessThanOrEqualTest.php index c738e8123..1784eaff9 100644 --- a/Tests/Constraints/LessThanOrEqualTest.php +++ b/Tests/Constraints/LessThanOrEqualTest.php @@ -24,16 +24,16 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'LessThanOrEqualDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/Tests/Constraints/LessThanTest.php b/Tests/Constraints/LessThanTest.php index 47dadaf6a..1d2429d2a 100644 --- a/Tests/Constraints/LessThanTest.php +++ b/Tests/Constraints/LessThanTest.php @@ -24,16 +24,16 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'LessThanDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/Tests/Constraints/LocaleTest.php b/Tests/Constraints/LocaleTest.php index b6beb13dd..d0664cda7 100644 --- a/Tests/Constraints/LocaleTest.php +++ b/Tests/Constraints/LocaleTest.php @@ -24,15 +24,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertTrue($aConstraint->canonicalize); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertFalse($bConstraint->canonicalize); self::assertSame(['Default', 'LocaleDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/LuhnTest.php b/Tests/Constraints/LuhnTest.php index f144785d2..ea9aecda1 100644 --- a/Tests/Constraints/LuhnTest.php +++ b/Tests/Constraints/LuhnTest.php @@ -24,11 +24,11 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'LuhnDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/MacAddressTest.php b/Tests/Constraints/MacAddressTest.php index 94cbfedd4..77c106883 100644 --- a/Tests/Constraints/MacAddressTest.php +++ b/Tests/Constraints/MacAddressTest.php @@ -34,17 +34,17 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame('myMessage', $aConstraint->message); self::assertEquals(trim(...), $aConstraint->normalizer); self::assertSame(MacAddress::ALL, $aConstraint->type); self::assertSame(['Default', 'MacAddressDummy'], $aConstraint->groups); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(MacAddress::LOCAL_UNICAST, $bConstraint->type); self::assertSame(['Default', 'MacAddressDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/NegativeOrZeroTest.php b/Tests/Constraints/NegativeOrZeroTest.php index 109713f07..40920a7be 100644 --- a/Tests/Constraints/NegativeOrZeroTest.php +++ b/Tests/Constraints/NegativeOrZeroTest.php @@ -24,12 +24,12 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(0, $aConstraint->value); self::assertNull($aConstraint->propertyPath); self::assertSame(['Default', 'NegativeOrZeroDummy'], $aConstraint->groups); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['foo'], $bConstraint->groups); } diff --git a/Tests/Constraints/NegativeTest.php b/Tests/Constraints/NegativeTest.php index 4a3c67da9..5e040f643 100644 --- a/Tests/Constraints/NegativeTest.php +++ b/Tests/Constraints/NegativeTest.php @@ -24,12 +24,12 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(0, $aConstraint->value); self::assertNull($aConstraint->propertyPath); self::assertSame(['Default', 'NegativeDummy'], $aConstraint->groups); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['foo'], $bConstraint->groups); } diff --git a/Tests/Constraints/NotBlankTest.php b/Tests/Constraints/NotBlankTest.php index 68a863473..60ff878c3 100644 --- a/Tests/Constraints/NotBlankTest.php +++ b/Tests/Constraints/NotBlankTest.php @@ -37,11 +37,11 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertFalse($aConstraint->allowNull); self::assertNull($aConstraint->normalizer); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertTrue($bConstraint->allowNull); self::assertSame('trim', $bConstraint->normalizer); self::assertSame('myMessage', $bConstraint->message); diff --git a/Tests/Constraints/NotCompromisedPasswordTest.php b/Tests/Constraints/NotCompromisedPasswordTest.php index 0ca6dcb2a..3be19c404 100644 --- a/Tests/Constraints/NotCompromisedPasswordTest.php +++ b/Tests/Constraints/NotCompromisedPasswordTest.php @@ -34,17 +34,17 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(1, $aConstraint->threshold); self::assertFalse($aConstraint->skipOnError); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(42, $bConstraint->threshold); self::assertTrue($bConstraint->skipOnError); self::assertSame(['Default', 'NotCompromisedPasswordDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/NotEqualToTest.php b/Tests/Constraints/NotEqualToTest.php index ff36b95cb..970c67ce5 100644 --- a/Tests/Constraints/NotEqualToTest.php +++ b/Tests/Constraints/NotEqualToTest.php @@ -24,16 +24,16 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'NotEqualToDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/Tests/Constraints/NotIdenticalToTest.php b/Tests/Constraints/NotIdenticalToTest.php index de34f05eb..96f13341b 100644 --- a/Tests/Constraints/NotIdenticalToTest.php +++ b/Tests/Constraints/NotIdenticalToTest.php @@ -24,16 +24,16 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(2, $aConstraint->value); self::assertNull($aConstraint->propertyPath); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(4711, $bConstraint->value); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'NotIdenticalToDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertNull($cConstraint->value); self::assertSame('b', $cConstraint->propertyPath); self::assertSame('myMessage', $cConstraint->message); diff --git a/Tests/Constraints/PositiveOrZeroTest.php b/Tests/Constraints/PositiveOrZeroTest.php index b13c803aa..847e41816 100644 --- a/Tests/Constraints/PositiveOrZeroTest.php +++ b/Tests/Constraints/PositiveOrZeroTest.php @@ -24,12 +24,12 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(0, $aConstraint->value); self::assertNull($aConstraint->propertyPath); self::assertSame(['Default', 'PositiveOrZeroDummy'], $aConstraint->groups); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['foo'], $bConstraint->groups); } diff --git a/Tests/Constraints/PositiveTest.php b/Tests/Constraints/PositiveTest.php index f06e61653..ee88893e5 100644 --- a/Tests/Constraints/PositiveTest.php +++ b/Tests/Constraints/PositiveTest.php @@ -24,12 +24,12 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(0, $aConstraint->value); self::assertNull($aConstraint->propertyPath); self::assertSame(['Default', 'PositiveDummy'], $aConstraint->groups); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['foo'], $bConstraint->groups); } diff --git a/Tests/Constraints/RegexTest.php b/Tests/Constraints/RegexTest.php index 3ce8fbf46..6fabc4958 100644 --- a/Tests/Constraints/RegexTest.php +++ b/Tests/Constraints/RegexTest.php @@ -122,19 +122,19 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame('/^[0-9]+$/', $aConstraint->pattern); self::assertTrue($aConstraint->match); self::assertNull($aConstraint->normalizer); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame('/^[0-9]+$/', $bConstraint->pattern); self::assertSame('[0-9]+', $bConstraint->htmlPattern); self::assertFalse($bConstraint->match); self::assertSame(['Default', 'RegexDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/TimeTest.php b/Tests/Constraints/TimeTest.php index 2e3132039..140b72d8f 100644 --- a/Tests/Constraints/TimeTest.php +++ b/Tests/Constraints/TimeTest.php @@ -24,11 +24,11 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'TimeDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/TimezoneTest.php b/Tests/Constraints/TimezoneTest.php index 4a3f4f6d1..5def3e361 100644 --- a/Tests/Constraints/TimezoneTest.php +++ b/Tests/Constraints/TimezoneTest.php @@ -70,16 +70,16 @@ public function testAttributes() $metadata = new ClassMetadata(TimezoneDummy::class); self::assertTrue((new AttributeLoader())->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(\DateTimeZone::ALL, $aConstraint->zone); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(\DateTimeZone::PER_COUNTRY, $bConstraint->zone); self::assertSame('DE', $bConstraint->countryCode); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'TimezoneDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/TypeTest.php b/Tests/Constraints/TypeTest.php index a9f68bc38..f9bee2df6 100644 --- a/Tests/Constraints/TypeTest.php +++ b/Tests/Constraints/TypeTest.php @@ -26,15 +26,15 @@ public function testAttributes() $metadata = new ClassMetadata(TypeDummy::class); self::assertTrue((new AttributeLoader())->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame('integer', $aConstraint->type); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(\DateTimeImmutable::class, $bConstraint->type); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'TypeDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['string', 'array'], $cConstraint->type); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); diff --git a/Tests/Constraints/UlidTest.php b/Tests/Constraints/UlidTest.php index 86cc32266..25be57edc 100644 --- a/Tests/Constraints/UlidTest.php +++ b/Tests/Constraints/UlidTest.php @@ -25,12 +25,12 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'UlidDummy'], $bConstraint->groups); self::assertSame(Ulid::FORMAT_BASE_58, $bConstraint->format); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/UniqueTest.php b/Tests/Constraints/UniqueTest.php index 94e7c42d4..6563d463c 100644 --- a/Tests/Constraints/UniqueTest.php +++ b/Tests/Constraints/UniqueTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'UniqueDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); - [$dConstraint] = $metadata->properties['d']->getConstraints(); + [$dConstraint] = $metadata->getPropertyMetadata('d')[0]->getConstraints(); self::assertSame('intval', $dConstraint->normalizer); } diff --git a/Tests/Constraints/UrlTest.php b/Tests/Constraints/UrlTest.php index a15caf263..297b2acc8 100644 --- a/Tests/Constraints/UrlTest.php +++ b/Tests/Constraints/UrlTest.php @@ -54,26 +54,26 @@ public function testAttributes() $metadata = new ClassMetadata(UrlDummy::class); self::assertTrue((new AttributeLoader())->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(['http', 'https'], $aConstraint->protocols); self::assertFalse($aConstraint->relativeProtocol); self::assertNull($aConstraint->normalizer); self::assertFalse($aConstraint->requireTld); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame(['ftp', 'gopher'], $bConstraint->protocols); self::assertSame('trim', $bConstraint->normalizer); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'UrlDummy'], $bConstraint->groups); self::assertFalse($bConstraint->requireTld); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertTrue($cConstraint->relativeProtocol); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); self::assertFalse($cConstraint->requireTld); - [$dConstraint] = $metadata->properties['d']->getConstraints(); + [$dConstraint] = $metadata->getPropertyMetadata('d')[0]->getConstraints(); self::assertSame(['http', 'https'], $dConstraint->protocols); self::assertFalse($dConstraint->relativeProtocol); self::assertNull($dConstraint->normalizer); diff --git a/Tests/Constraints/UuidTest.php b/Tests/Constraints/UuidTest.php index a2cc15ca6..60c537529 100644 --- a/Tests/Constraints/UuidTest.php +++ b/Tests/Constraints/UuidTest.php @@ -54,19 +54,19 @@ public function testAttributes() $metadata = new ClassMetadata(UuidDummy::class); self::assertTrue((new AttributeLoader())->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); self::assertSame(Uuid::ALL_VERSIONS, $aConstraint->versions); self::assertTrue($aConstraint->strict); self::assertNull($aConstraint->normalizer); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame([Uuid::V4_RANDOM, Uuid::V6_SORTABLE], $bConstraint->versions); self::assertFalse($bConstraint->strict); self::assertSame('trim', $bConstraint->normalizer); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'UuidDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/ValidTest.php b/Tests/Constraints/ValidTest.php index a862171f1..3ae0ef76e 100644 --- a/Tests/Constraints/ValidTest.php +++ b/Tests/Constraints/ValidTest.php @@ -41,11 +41,11 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertFalse($bConstraint->traverse); self::assertSame(['traverse_group'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } diff --git a/Tests/Constraints/WeekTest.php b/Tests/Constraints/WeekTest.php index 0fc9aac62..7daeafd23 100644 --- a/Tests/Constraints/WeekTest.php +++ b/Tests/Constraints/WeekTest.php @@ -81,11 +81,11 @@ public function testAttributes() $loader = new AttributeLoader(); $this->assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); $this->assertNull($aConstraint->min); $this->assertNull($aConstraint->max); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); $this->assertSame('2010-W01', $bConstraint->min); $this->assertSame('2010-W02', $bConstraint->max); } diff --git a/Tests/Constraints/WhenTest.php b/Tests/Constraints/WhenTest.php index d919b0310..7654a26b0 100644 --- a/Tests/Constraints/WhenTest.php +++ b/Tests/Constraints/WhenTest.php @@ -73,7 +73,7 @@ public function testAttributes() ], $classConstraint->constraints); self::assertSame([], $classConstraint->otherwise); - [$fooConstraint] = $metadata->properties['foo']->getConstraints(); + [$fooConstraint] = $metadata->getPropertyMetadata('foo')[0]->getConstraints(); self::assertInstanceOf(When::class, $fooConstraint); self::assertSame('true', $fooConstraint->expression); @@ -84,7 +84,7 @@ public function testAttributes() self::assertSame([], $fooConstraint->otherwise); self::assertSame(['Default', 'WhenTestWithAttributes'], $fooConstraint->groups); - [$barConstraint] = $metadata->properties['bar']->getConstraints(); + [$barConstraint] = $metadata->getPropertyMetadata('bar')[0]->getConstraints(); self::assertInstanceOf(When::class, $barConstraint); self::assertSame('false', $barConstraint->expression); @@ -95,7 +95,7 @@ public function testAttributes() self::assertSame([], $barConstraint->otherwise); self::assertSame(['foo'], $barConstraint->groups); - [$quxConstraint] = $metadata->properties['qux']->getConstraints(); + [$quxConstraint] = $metadata->getPropertyMetadata('qux')[0]->getConstraints(); self::assertInstanceOf(When::class, $quxConstraint); self::assertSame('true', $quxConstraint->expression); @@ -103,7 +103,7 @@ public function testAttributes() self::assertSame([], $quxConstraint->otherwise); self::assertSame(['foo'], $quxConstraint->groups); - [$bazConstraint] = $metadata->getters['baz']->getConstraints(); + [$bazConstraint] = $metadata->getPropertyMetadata('baz')[0]->getConstraints(); self::assertInstanceOf(When::class, $bazConstraint); self::assertSame('true', $bazConstraint->expression); @@ -114,7 +114,7 @@ public function testAttributes() self::assertSame([], $bazConstraint->otherwise); self::assertSame(['Default', 'WhenTestWithAttributes'], $bazConstraint->groups); - [$quuxConstraint] = $metadata->properties['quux']->getConstraints(); + [$quuxConstraint] = $metadata->getPropertyMetadata('quux')[0]->getConstraints(); self::assertInstanceOf(When::class, $quuxConstraint); self::assertSame('true', $quuxConstraint->expression); @@ -143,7 +143,7 @@ public function testAttributesWithClosure() ], $classConstraint->constraints); self::assertSame([], $classConstraint->otherwise); - [$fooConstraint] = $metadata->properties['foo']->getConstraints(); + [$fooConstraint] = $metadata->getPropertyMetadata('foo')[0]->getConstraints(); self::assertInstanceOf(When::class, $fooConstraint); self::assertInstanceOf(\Closure::class, $fooConstraint->expression); diff --git a/Tests/Constraints/WordCountTest.php b/Tests/Constraints/WordCountTest.php index 3f995c050..c6fd2ea10 100644 --- a/Tests/Constraints/WordCountTest.php +++ b/Tests/Constraints/WordCountTest.php @@ -110,17 +110,17 @@ public function testAttributes() $loader = new AttributeLoader(); $this->assertTrue($loader->loadClassMetadata($metadata)); - [$aConstraint] = $metadata->properties['a']->getConstraints(); + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); $this->assertSame(1, $aConstraint->min); $this->assertNull($aConstraint->max); $this->assertNull($aConstraint->locale); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); $this->assertSame(2, $bConstraint->min); $this->assertSame(5, $bConstraint->max); $this->assertNull($bConstraint->locale); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); $this->assertSame(3, $cConstraint->min); $this->assertNull($cConstraint->max); $this->assertSame('en', $cConstraint->locale); diff --git a/Tests/Constraints/YamlTest.php b/Tests/Constraints/YamlTest.php index c9529fc12..60d5d126e 100644 --- a/Tests/Constraints/YamlTest.php +++ b/Tests/Constraints/YamlTest.php @@ -28,15 +28,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'YamlDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); - [$cConstraint] = $metadata->properties['d']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('d')[0]->getConstraints(); self::assertSame(YamlParser::PARSE_CONSTANT | YamlParser::PARSE_CUSTOM_TAGS, $cConstraint->flags); } } diff --git a/Tests/Mapping/ClassMetadataTest.php b/Tests/Mapping/ClassMetadataTest.php index ce12b31d4..07da48c8d 100644 --- a/Tests/Mapping/ClassMetadataTest.php +++ b/Tests/Mapping/ClassMetadataTest.php @@ -180,24 +180,15 @@ public function testMergeConstraintsMergesMemberConstraints() $this->assertCount(2, $members); $this->assertEquals(self::CLASSNAME, $members[0]->getClassName()); $this->assertEquals([$constraintA2], $members[0]->getConstraints()); - $this->assertEquals( - [ - 'Default' => [$constraintA2], - 'Entity' => [$constraintA2], - ], - $members[0]->constraintsByGroup - ); + $this->assertEquals([$constraintA2], $members[0]->findConstraints('Default')); + $this->assertEquals([$constraintA2], $members[0]->findConstraints('Entity')); + $this->assertEquals(self::PARENTCLASS, $members[1]->getClassName()); $this->assertEquals([$constraintA1, $constraintB], $members[1]->getConstraints()); - $this->assertEquals( - [ - 'Default' => [$constraintA1], - 'Entity' => [$constraintA1], - 'EntityParent' => [$constraintA1], - 'foo' => [$constraintB], - ], - $members[1]->constraintsByGroup - ); + $this->assertEquals([$constraintA1], $members[1]->findConstraints('Default')); + $this->assertEquals([$constraintA1], $members[1]->findConstraints('Entity')); + $this->assertEquals([$constraintA1], $members[1]->findConstraints('EntityParent')); + $this->assertEquals([$constraintB], $members[1]->findConstraints('foo')); } public function testMemberMetadatas() @@ -337,7 +328,6 @@ public function testCascadeConstraint() $metadata->addConstraint(new Cascade()); $this->assertSame(CascadingStrategy::CASCADE, $metadata->getCascadingStrategy()); - $this->assertCount(4, $metadata->properties); $this->assertSame([ 'requiredChild', 'optionalChild', @@ -352,7 +342,6 @@ public function testCascadeConstraintWithUnionTypeProperties() $metadata->addConstraint(new Cascade()); $this->assertSame(CascadingStrategy::CASCADE, $metadata->getCascadingStrategy()); - $this->assertCount(5, $metadata->properties); $this->assertSame([ 'classes', 'classAndArray', @@ -368,7 +357,6 @@ public function testCascadeConstraintWithIntersectionTypeProperties() $metadata->addConstraint(new Cascade()); $this->assertSame(CascadingStrategy::CASCADE, $metadata->getCascadingStrategy()); - $this->assertCount(1, $metadata->properties); $this->assertSame([ 'classes', ], $metadata->getConstrainedProperties()); @@ -381,7 +369,6 @@ public function testCascadeConstraintWithExcludedProperties() $metadata->addConstraint(new Cascade(exclude: ['requiredChild', 'optionalChild'])); $this->assertSame(CascadingStrategy::CASCADE, $metadata->getCascadingStrategy()); - $this->assertCount(2, $metadata->properties); $this->assertSame([ 'staticChild', 'children', diff --git a/Tests/Mapping/Loader/PropertyInfoLoaderTest.php b/Tests/Mapping/Loader/PropertyInfoLoaderTest.php index dc11ea7aa..19c904544 100644 --- a/Tests/Mapping/Loader/PropertyInfoLoaderTest.php +++ b/Tests/Mapping/Loader/PropertyInfoLoaderTest.php @@ -298,7 +298,7 @@ public function getTypes(string $class, string $property, array $context = []): /** @var ClassMetadata $classMetadata */ $classMetadata = $validator->getMetadataFor(new PropertyInfoLoaderNoAutoMappingEntity()); $this->assertSame([], $classMetadata->getPropertyMetadata('string')); - $this->assertCount(2, $classMetadata->getPropertyMetadata('autoMappingExplicitlyEnabled')[0]->constraints); + $this->assertCount(2, $classMetadata->getPropertyMetadata('autoMappingExplicitlyEnabled')[0]->getConstraints()); $this->assertSame(AutoMappingStrategy::ENABLED, $classMetadata->getPropertyMetadata('autoMappingExplicitlyEnabled')[0]->getAutoMappingStrategy()); } } diff --git a/Tests/Mapping/PropertyMetadataTest.php b/Tests/Mapping/PropertyMetadataTest.php index bacd572c9..dbcdb0897 100644 --- a/Tests/Mapping/PropertyMetadataTest.php +++ b/Tests/Mapping/PropertyMetadataTest.php @@ -53,8 +53,10 @@ public function testGetPropertyValueFromOverriddenPrivateProperty() public function testGetPropertyValueFromRemovedProperty() { $entity = new Entity('foobar'); - $metadata = new PropertyMetadata(self::CLASSNAME, 'internal'); - $metadata->name = 'test'; + + // simulate out-of-sync metadata + $metadata = 'O:52:"Symfony\Component\Validator\Mapping\PropertyMetadata":3:{s:5:"class";s:65:"Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity";s:4:"name";s:7:"missing";s:8:"property";s:7:"missing";}'; + $metadata = unserialize($metadata); $this->expectException(ValidatorException::class); $metadata->getPropertyValue($entity); From 29a8a56879a09a800b88d9d098d615246d5c7d80 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 15 Aug 2025 14:18:53 +0200 Subject: [PATCH 32/57] [Validator][Serializer] Make internal properties private --- Mapping/ClassMetadata.php | 87 +++++++++++++------------------------ Mapping/GenericMetadata.php | 45 ++++--------------- Mapping/MemberMetadata.php | 28 ++---------- 3 files changed, 42 insertions(+), 118 deletions(-) diff --git a/Mapping/ClassMetadata.php b/Mapping/ClassMetadata.php index 0e52e5fef..b9ac2ec41 100644 --- a/Mapping/ClassMetadata.php +++ b/Mapping/ClassMetadata.php @@ -31,67 +31,36 @@ */ class ClassMetadata extends GenericMetadata implements ClassMetadataInterface { - /** - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getClassName()} instead. - */ - public string $name; - - /** - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getDefaultGroup()} instead. - */ - public string $defaultGroup; + private string $name; + private string $defaultGroup; /** * @var MemberMetadata[][] - * - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getPropertyMetadata()} instead. */ - public array $members = []; + private array $members = []; /** * @var PropertyMetadata[] - * - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getPropertyMetadata()} instead. */ - public array $properties = []; + private array $properties = []; /** * @var GetterMetadata[] - * - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getPropertyMetadata()} instead. - */ - public array $getters = []; - - /** - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getGroupSequence()} instead. */ - public ?GroupSequence $groupSequence = null; + private array $getters = []; - /** - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link isGroupSequenceProvider()} instead. - */ - public bool $groupSequenceProvider = false; + private ?GroupSequence $groupSequence = null; + private bool $groupSequenceProvider = false; + private ?string $groupProvider = null; /** - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getGroupProvider()} instead. + * The strategy for cascading objects. + * + * By default, objects are not cascaded. + * + * @var CascadingStrategy::* */ - public ?string $groupProvider = null; + private int $cascadingStrategy = CascadingStrategy::NONE; /** * The strategy for traversing traversable objects. @@ -99,12 +68,8 @@ class ClassMetadata extends GenericMetadata implements ClassMetadataInterface * By default, only instances of {@link \Traversable} are traversed. * * @var TraversalStrategy::* - * - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getTraversalStrategy()} instead. */ - public int $traversalStrategy = TraversalStrategy::IMPLICIT; + private int $traversalStrategy = TraversalStrategy::IMPLICIT; private \ReflectionClass $reflClass; @@ -123,6 +88,7 @@ public function __serialize(): array { if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { return array_filter([ + 'cascadingStrategy' => CascadingStrategy::NONE !== $this->cascadingStrategy ? $this->cascadingStrategy : null, 'traversalStrategy' => TraversalStrategy::IMPLICIT !== $this->traversalStrategy ? $this->traversalStrategy : null, ] + parent::__serialize() + [ 'getters' => $this->getters, @@ -215,13 +181,7 @@ public function addConstraint(Constraint $constraint): static $this->checkConstraint($constraint); if ($constraint instanceof Traverse) { - if ($constraint->traverse) { - // If traverse is true, traversal should be explicitly enabled - $this->traversalStrategy = TraversalStrategy::TRAVERSE; - } else { - // If traverse is false, traversal should be explicitly disabled - $this->traversalStrategy = TraversalStrategy::NONE; - } + $this->traversalStrategy = $constraint->traverse ? TraversalStrategy::TRAVERSE : TraversalStrategy::NONE; // The constraint is not added return $this; @@ -246,6 +206,14 @@ public function addConstraint(Constraint $constraint): static $constraint->addImplicitGroupName($this->getDefaultGroup()); + if ($constraint instanceof Valid && null === $constraint->groups) { + $this->cascadingStrategy = CascadingStrategy::CASCADE; + $this->traversalStrategy = $constraint->traverse ? TraversalStrategy::IMPLICIT : TraversalStrategy::NONE; + + // The constraint is not added + return $this; + } + parent::addConstraint($constraint); return $this; @@ -498,6 +466,11 @@ public function getCascadingStrategy(): int return $this->cascadingStrategy; } + public function getTraversalStrategy(): int + { + return $this->traversalStrategy; + } + private function addPropertyMetadata(PropertyMetadataInterface $metadata): void { $property = $metadata->getPropertyName(); diff --git a/Mapping/GenericMetadata.php b/Mapping/GenericMetadata.php index f2e6074b7..ce743e84b 100644 --- a/Mapping/GenericMetadata.php +++ b/Mapping/GenericMetadata.php @@ -30,21 +30,13 @@ class GenericMetadata implements MetadataInterface { /** * @var Constraint[] - * - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getConstraints()} and {@link findConstraints()} instead. */ - public array $constraints = []; + private array $constraints = []; /** * @var array - * - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link findConstraints()} instead. */ - public array $constraintsByGroup = []; + private array $constraintsByGroup = []; /** * The strategy for cascading objects. @@ -52,12 +44,8 @@ class GenericMetadata implements MetadataInterface * By default, objects are not cascaded. * * @var CascadingStrategy::* - * - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getCascadingStrategy()} instead. */ - public int $cascadingStrategy = CascadingStrategy::NONE; + private int $cascadingStrategy = CascadingStrategy::NONE; /** * The strategy for traversing traversable objects. @@ -65,23 +53,15 @@ class GenericMetadata implements MetadataInterface * By default, traversable objects are not traversed. * * @var TraversalStrategy::* - * - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getTraversalStrategy()} instead. */ - public int $traversalStrategy = TraversalStrategy::NONE; + private int $traversalStrategy = TraversalStrategy::NONE; /** * Is auto-mapping enabled? * * @var AutoMappingStrategy::* - * - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getAutoMappingStrategy()} instead. */ - public int $autoMappingStrategy = AutoMappingStrategy::NONE; + private int $autoMappingStrategy = AutoMappingStrategy::NONE; public function __serialize(): array { @@ -127,9 +107,6 @@ public function __sleep(): array ]; } - /** - * Clones this object. - */ public function __clone() { $constraints = $this->constraints; @@ -166,13 +143,9 @@ public function addConstraint(Constraint $constraint): static if ($constraint instanceof Valid && null === $constraint->groups) { $this->cascadingStrategy = CascadingStrategy::CASCADE; + $this->traversalStrategy = $constraint->traverse ? TraversalStrategy::IMPLICIT : TraversalStrategy::NONE; - if ($constraint->traverse) { - $this->traversalStrategy = TraversalStrategy::IMPLICIT; - } else { - $this->traversalStrategy = TraversalStrategy::NONE; - } - + // The constraint is not added return $this; } @@ -197,9 +170,9 @@ public function addConstraint(Constraint $constraint): static } /** - * Adds an list of constraints. + * Adds a list of constraints. * - * @param Constraint[] $constraints The constraints to add + * @param Constraint[] $constraints * * @return $this */ diff --git a/Mapping/MemberMetadata.php b/Mapping/MemberMetadata.php index 4ac029219..7487fa0ba 100644 --- a/Mapping/MemberMetadata.php +++ b/Mapping/MemberMetadata.php @@ -29,26 +29,9 @@ */ abstract class MemberMetadata extends GenericMetadata implements PropertyMetadataInterface { - /** - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getClassName()} instead. - */ - public string $class; - - /** - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getName()} instead. - */ - public string $name; - - /** - * @internal This property is public in order to reduce the size of the - * class' serialized representation. Do not access it. Use - * {@link getPropertyName()} instead. - */ - public string $property; + private string $class; + private string $name; + private string $property; /** * @var \ReflectionMethod[]|\ReflectionProperty[] @@ -80,11 +63,6 @@ public function __serialize(): array { if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) { return parent::__serialize() + [ - 'constraints' => $this->constraints, - 'constraintsByGroup' => $this->constraintsByGroup, - 'cascadingStrategy' => $this->cascadingStrategy, - 'traversalStrategy' => $this->traversalStrategy, - 'autoMappingStrategy' => $this->autoMappingStrategy, 'class' => $this->class, 'name' => $this->name, 'property' => $this->property, From de71466511ea159f1fe7d31ebaa5e958d0751d2a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 20 Aug 2025 12:31:41 +0200 Subject: [PATCH 33/57] Fix low-deps tests --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 3c8d4ba1b..de1c6c190 100644 --- a/composer.json +++ b/composer.json @@ -52,6 +52,7 @@ "symfony/intl": "<6.4", "symfony/property-info": "<6.4", "symfony/translation": "<6.4.3|>=7.0,<7.0.3", + "symfony/var-exporter": "<6.4.25|>=7.0,<7.3.3", "symfony/yaml": "<6.4" }, "autoload": { From 513ca464e7c811c1cdf3d7360ec5d4bd068657d5 Mon Sep 17 00:00:00 2001 From: Dawid Nowak Date: Sat, 23 Aug 2025 00:01:03 +0200 Subject: [PATCH 34/57] [DI]: removed unnecessary checks on `Definition`s and `Alias`es If it is "public", then for sure it is not "private". https://github.com/symfony/symfony/pull/61505#issuecomment-3227850921 --- Tests/DependencyInjection/AddConstraintValidatorsPassTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DependencyInjection/AddConstraintValidatorsPassTest.php b/Tests/DependencyInjection/AddConstraintValidatorsPassTest.php index 1b85c7e2a..69184b8fb 100644 --- a/Tests/DependencyInjection/AddConstraintValidatorsPassTest.php +++ b/Tests/DependencyInjection/AddConstraintValidatorsPassTest.php @@ -36,7 +36,7 @@ public function testThatConstraintValidatorServicesAreProcessed() $addConstraintValidatorsPass->process($container); $locator = $container->getDefinition((string) $validatorFactory->getArgument(0)); - $this->assertTrue(!$locator->isPublic() || $locator->isPrivate()); + $this->assertTrue($locator->isPrivate()); $expected = (new Definition(ServiceLocator::class, [[ Validator1::class => new ServiceClosureArgument(new Reference('my_constraint_validator_service1')), 'my_constraint_validator_alias1' => new ServiceClosureArgument(new Reference('my_constraint_validator_service1')), From 683e3ab4f2c20507b142e5745ce9abf4964038b3 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 27 Aug 2025 15:37:36 +0200 Subject: [PATCH 35/57] require a top-level domain by default in the Url constraint --- CHANGELOG.md | 1 + Constraints/Url.php | 6 +----- composer.json | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bfe4a706..13199d1df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 8.0 --- + * Change the default value of the `$requireTld` option of the `Url` constraint to `true` * Add method `getGroupProvider()` to `ClassMetadataInterface` * Replace `__sleep/wakeup()` by `__(un)serialize()` on `GenericMetadata` implementations * Remove the `getRequiredOptions()` and `getDefaultOption()` methods from the `All`, `AtLeastOneOf`, `CardScheme`, `Collection`, diff --git a/Constraints/Url.php b/Constraints/Url.php index 8cdcf54c6..3a0e853e8 100644 --- a/Constraints/Url.php +++ b/Constraints/Url.php @@ -34,7 +34,7 @@ class Url extends Constraint public string $tldMessage = 'This URL is missing a top-level domain.'; public array $protocols = ['http', 'https']; public bool $relativeProtocol = false; - public bool $requireTld = false; + public bool $requireTld = true; /** @var callable|null */ public $normalizer; @@ -61,10 +61,6 @@ public function __construct( parent::__construct(null, $groups, $payload); - if (null === $requireTld) { - trigger_deprecation('symfony/validator', '7.1', 'Not passing a value for the "requireTld" option to the Url constraint is deprecated. Its default value will change to "true".'); - } - $this->message = $message ?? $this->message; $this->protocols = $protocols ?? $this->protocols; $this->relativeProtocol = $relativeProtocol ?? $this->relativeProtocol; diff --git a/composer.json b/composer.json index ab0d10daa..58f874c8c 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,6 @@ ], "require": { "php": ">=8.4", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-mbstring": "^1.0", "symfony/translation-contracts": "^2.5|^3" From 74e760ca61f0c8332886b1e955e49ab79c4544f3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 30 Aug 2025 13:14:35 +0200 Subject: [PATCH 36/57] [Serializer][Validator] Add JSON schema for validating and autocompleting YAML config files --- Mapping/Loader/schema/validation.schema.json | 123 +++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 Mapping/Loader/schema/validation.schema.json diff --git a/Mapping/Loader/schema/validation.schema.json b/Mapping/Loader/schema/validation.schema.json new file mode 100644 index 000000000..0778929c4 --- /dev/null +++ b/Mapping/Loader/schema/validation.schema.json @@ -0,0 +1,123 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Symfony Validation Mapping Schema", + "description": "JSON schema for Symfony's validation mapping", + "type": "object", + "additionalProperties": false, + "properties": { + "namespaces": { + "type": "object", + "description": "Namespace aliases for constraint classes", + "additionalProperties": { + "type": "string", + "description": "Full namespace path" + } + } + }, + "patternProperties": { + "^[A-Za-z0-9\\\\_]+$": { + "type": "object", + "description": "Class metadata configuration", + "additionalProperties": false, + "properties": { + "group_sequence": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of validation group names" + }, + { + "type": "boolean" + } + ], + "description": "Validation group sequence or group sequence provider flag" + }, + "group_sequence_provider": { + "oneOf": [ + { + "type": "boolean", + "description": "Enable/disable group sequence provider" + }, + { + "type": "string", + "description": "Class name of the group sequence provider" + } + ] + }, + "constraints": { + "$ref": "#/definitions/constraintArray" + }, + "properties": { + "type": "object", + "description": "Property-level constraints", + "additionalProperties": { + "$ref": "#/definitions/constraintArrayOrNull" + } + }, + "getters": { + "type": "object", + "description": "Getter method constraints", + "additionalProperties": { + "$ref": "#/definitions/constraintArrayOrNull" + } + } + } + } + }, + "definitions": { + "constraintArray": { + "type": "array", + "description": "Array of constraints", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Constraint with options", + "minProperties": 1, + "maxProperties": 1, + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "array" + }, + { + "type": "object" + } + ] + } + }, + { + "type": "string", + "description": "Simple constraint name" + } + ] + } + }, + "constraintArrayOrNull": { + "oneOf": [ + { + "type": "null", + "description": "No constraints" + }, + { + "$ref": "#/definitions/constraintArray" + } + ] + } + } +} From af2056bcb87e35d50ed6b076bff4bfa31119fec6 Mon Sep 17 00:00:00 2001 From: symfonyaml Date: Fri, 29 Nov 2024 15:21:44 +0100 Subject: [PATCH 37/57] [Validator] Add the Video constraint for validating video files --- CHANGELOG.md | 1 + Constraints/Video.php | 254 ++++++++++++++++ Constraints/VideoValidator.php | 265 ++++++++++++++++ Tests/Constraints/Fixtures/test.mp4 | Bin 0 -> 1556 bytes Tests/Constraints/Fixtures/test_16by9.mp4 | Bin 0 -> 1563 bytes Tests/Constraints/Fixtures/test_4by3.mp4 | Bin 0 -> 1582 bytes Tests/Constraints/Fixtures/test_corrupted.mp4 | Bin 0 -> 999 bytes Tests/Constraints/Fixtures/test_landscape.mp4 | Bin 0 -> 1557 bytes Tests/Constraints/Fixtures/test_portrait.mp4 | Bin 0 -> 1556 bytes Tests/Constraints/VideoTest.php | 65 ++++ Tests/Constraints/VideoValidatorTest.php | 286 ++++++++++++++++++ composer.json | 1 + 12 files changed, 872 insertions(+) create mode 100644 Constraints/Video.php create mode 100644 Constraints/VideoValidator.php create mode 100644 Tests/Constraints/Fixtures/test.mp4 create mode 100644 Tests/Constraints/Fixtures/test_16by9.mp4 create mode 100644 Tests/Constraints/Fixtures/test_4by3.mp4 create mode 100644 Tests/Constraints/Fixtures/test_corrupted.mp4 create mode 100644 Tests/Constraints/Fixtures/test_landscape.mp4 create mode 100644 Tests/Constraints/Fixtures/test_portrait.mp4 create mode 100644 Tests/Constraints/VideoTest.php create mode 100644 Tests/Constraints/VideoValidatorTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bc83027b..52edebc7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.4 --- + * Add the `Video` constraint for validating video files * Deprecate implementing `__sleep/wakeup()` on `GenericMetadata` implementations; use `__(un)serialize()` instead * Deprecate passing a list of choices to the first argument of the `Choice` constraint. Use the `choices` option instead * Add the `min` and `max` parameter to the `Length` constraint violation diff --git a/Constraints/Video.php b/Constraints/Video.php new file mode 100644 index 000000000..796dfb94e --- /dev/null +++ b/Constraints/Video.php @@ -0,0 +1,254 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Constraints; + +use Symfony\Component\Process\ExecutableFinder; +use Symfony\Component\Process\Process; +use Symfony\Component\Validator\Attribute\HasNamedArguments; +use Symfony\Component\Validator\Exception\LogicException; + +/** + * @author Kev + * @author Nicolas Grekas + */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] +class Video extends File +{ + public const SIZE_NOT_DETECTED_ERROR = '5dab98df-43c8-481b-94f9-46a3c958285c'; + public const TOO_WIDE_ERROR = '9e18d6a4-aeda-4644-be8e-9e29dbfd6c4a'; + public const TOO_NARROW_ERROR = 'b267f54b-d994-46d4-9ca6-338fc4f7962f'; + public const TOO_HIGH_ERROR = '44f4c411-0199-48c2-b597-df1f5944ccde'; + public const TOO_LOW_ERROR = '0b6bc3ce-df90-40f9-90aa-5bbb840cb481'; + public const TOO_FEW_PIXEL_ERROR = '510ddf98-2eda-436e-be7e-b6f107bc0e22'; + public const TOO_MANY_PIXEL_ERROR = 'ff0a8ee8-951d-4c97-afe2-03c0d61a2a02'; + public const RATIO_TOO_BIG_ERROR = '5e6b9c21-d4d8-444d-9f4c-e3ff1e25a9a6'; + public const RATIO_TOO_SMALL_ERROR = '26985857-7447-49dc-b271-1477a76cc63c'; + public const SQUARE_NOT_ALLOWED_ERROR = '18500335-b868-4056-b2a2-aa2aeeb0cbdf'; + public const LANDSCAPE_NOT_ALLOWED_ERROR = 'cbf38fbc-04c0-457a-8c29-a6f3080e415a'; + public const PORTRAIT_NOT_ALLOWED_ERROR = '6c3e34a8-94d5-4434-9f20-fb9c0f3ab531'; + public const CORRUPTED_VIDEO_ERROR = '591b9c4d-d357-425f-8672-6b187816550e'; + public const MULTIPLE_VIDEO_STREAMS_ERROR = '2d1b2b2e-3f37-4fdd-9a2a-8b6b77b2a6a3'; + public const UNSUPPORTED_VIDEO_CODEC_ERROR = 'a9f2f6f7-2b5a-4f3c-b746-d3e2e9d1b2a1'; + public const UNSUPPORTED_VIDEO_CONTAINER_ERROR = 'b7c9d2a4-5e1f-4aa0-8f9d-1c3e2b4a6d7e'; + + // Include the mapping from the base class + + protected const ERROR_NAMES = [ + self::NOT_FOUND_ERROR => 'NOT_FOUND_ERROR', + self::NOT_READABLE_ERROR => 'NOT_READABLE_ERROR', + self::EMPTY_ERROR => 'EMPTY_ERROR', + self::TOO_LARGE_ERROR => 'TOO_LARGE_ERROR', + self::INVALID_MIME_TYPE_ERROR => 'INVALID_MIME_TYPE_ERROR', + self::FILENAME_TOO_LONG => 'FILENAME_TOO_LONG', + self::SIZE_NOT_DETECTED_ERROR => 'SIZE_NOT_DETECTED_ERROR', + self::TOO_WIDE_ERROR => 'TOO_WIDE_ERROR', + self::TOO_NARROW_ERROR => 'TOO_NARROW_ERROR', + self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR', + self::TOO_LOW_ERROR => 'TOO_LOW_ERROR', + self::TOO_FEW_PIXEL_ERROR => 'TOO_FEW_PIXEL_ERROR', + self::TOO_MANY_PIXEL_ERROR => 'TOO_MANY_PIXEL_ERROR', + self::RATIO_TOO_BIG_ERROR => 'RATIO_TOO_BIG_ERROR', + self::RATIO_TOO_SMALL_ERROR => 'RATIO_TOO_SMALL_ERROR', + self::SQUARE_NOT_ALLOWED_ERROR => 'SQUARE_NOT_ALLOWED_ERROR', + self::LANDSCAPE_NOT_ALLOWED_ERROR => 'LANDSCAPE_NOT_ALLOWED_ERROR', + self::PORTRAIT_NOT_ALLOWED_ERROR => 'PORTRAIT_NOT_ALLOWED_ERROR', + self::CORRUPTED_VIDEO_ERROR => 'CORRUPTED_VIDEO_ERROR', + self::MULTIPLE_VIDEO_STREAMS_ERROR => 'MULTIPLE_VIDEO_STREAMS_ERROR', + self::UNSUPPORTED_VIDEO_CODEC_ERROR => 'UNSUPPORTED_VIDEO_CODEC_ERROR', + self::UNSUPPORTED_VIDEO_CONTAINER_ERROR => 'UNSUPPORTED_VIDEO_CONTAINER_ERROR', + ]; + + public array|string $mimeTypes = 'video/*'; + public ?int $minWidth = null; + public ?int $maxWidth = null; + public ?int $maxHeight = null; + public ?int $minHeight = null; + public int|float|null $maxRatio = null; + public int|float|null $minRatio = null; + public int|float|null $minPixels = null; + public int|float|null $maxPixels = null; + public ?bool $allowSquare = true; + public ?bool $allowLandscape = true; + public ?bool $allowPortrait = true; + public array $allowedCodecs = ['h264', 'hevc', 'h265', 'vp9', 'av1', 'mpeg4', 'mpeg2video']; + public array $allowedContainers = ['mp4', 'mov', 'mkv', 'webm', 'avi']; + + // The constant for a wrong MIME type is taken from the parent class. + public string $mimeTypesMessage = 'This file is not a valid video.'; + public string $sizeNotDetectedMessage = 'The size of the video could not be detected.'; + public string $maxWidthMessage = 'The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.'; + public string $minWidthMessage = 'The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.'; + public string $maxHeightMessage = 'The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.'; + public string $minHeightMessage = 'The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.'; + public string $minPixelsMessage = 'The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels.'; + public string $maxPixelsMessage = 'The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels.'; + public string $maxRatioMessage = 'The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.'; + public string $minRatioMessage = 'The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.'; + public string $allowSquareMessage = 'The video is square ({{ width }}x{{ height }}px). Square videos are not allowed.'; + public string $allowLandscapeMessage = 'The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed.'; + public string $allowPortraitMessage = 'The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed.'; + public string $corruptedMessage = 'The video file is corrupted.'; + public string $multipleVideoStreamsMessage = 'The video contains multiple streams. Only one stream is allowed.'; + public string $unsupportedCodecMessage = 'Unsupported video codec "{{ codec }}".'; + public string $unsupportedContainerMessage = 'Unsupported video container "{{ container }}".'; + + /** + * @param positive-int|string|null $maxSize The max size of the underlying file + * @param bool|null $binaryFormat Pass true to use binary-prefixed units (KiB, MiB, etc.) or false to use SI-prefixed units (kB, MB) in displayed messages. Pass null to guess the format from the maxSize option. (defaults to null) + * @param non-empty-string[]|null $mimeTypes Acceptable media types + * @param positive-int|null $filenameMaxLength Maximum length of the file name + * @param string|null $disallowEmptyMessage Enable empty upload validation with this message in case of error + * @param string|null $uploadIniSizeErrorMessage Message if the file size exceeds the max size configured in php.ini + * @param string|null $uploadFormSizeErrorMessage Message if the file size exceeds the max size configured in the HTML input field + * @param string|null $uploadPartialErrorMessage Message if the file is only partially uploaded + * @param string|null $uploadNoTmpDirErrorMessage Message if there is no upload_tmp_dir in php.ini + * @param string|null $uploadCantWriteErrorMessage Message if the uploaded file can not be stored in the temporary directory + * @param string|null $uploadErrorMessage Message if an unknown error occurred on upload + * @param string[]|null $groups + * @param int<0, int>|null $minWidth Minimum video width + * @param positive-int|null $maxWidth Maximum video width + * @param positive-int|null $maxHeight Maximum video height + * @param int<0, int>|null $minHeight Minimum video weight + * @param positive-int|float|null $maxRatio Maximum video ratio + * @param int<0, max>|float|null $minRatio Minimum video ratio + * @param int<0, max>|float|null $minPixels Minimum amount of pixels + * @param positive-int|float|null $maxPixels Maximum amount of pixels + * @param bool|null $allowSquare Whether to allow a square video (defaults to true) + * @param bool|null $allowLandscape Whether to allow a landscape video (defaults to true) + * @param bool|null $allowPortrait Whether to allow a portrait video (defaults to true) + * @param string|null $sizeNotDetectedMessage Message if the system can not determine video size and there is a size constraint to validate + * @param string[]|null $allowedCodecs Allowed codec names + * @param string[]|null $allowedContainers Allowed container names + * + * @see https://www.iana.org/assignments/media-types/media-types.xhtml Existing media types + */ + #[HasNamedArguments] + public function __construct( + int|string|null $maxSize = null, + ?bool $binaryFormat = null, + array|string|null $mimeTypes = null, + ?int $filenameMaxLength = null, + ?int $minWidth = null, + ?int $maxWidth = null, + ?int $maxHeight = null, + ?int $minHeight = null, + int|float|null $maxRatio = null, + int|float|null $minRatio = null, + int|float|null $minPixels = null, + int|float|null $maxPixels = null, + ?bool $allowSquare = null, + ?bool $allowLandscape = null, + ?bool $allowPortrait = null, + ?array $allowedCodecs = null, + ?array $allowedContainers = null, + ?string $notFoundMessage = null, + ?string $notReadableMessage = null, + ?string $maxSizeMessage = null, + ?string $mimeTypesMessage = null, + ?string $disallowEmptyMessage = null, + ?string $filenameTooLongMessage = null, + ?string $uploadIniSizeErrorMessage = null, + ?string $uploadFormSizeErrorMessage = null, + ?string $uploadPartialErrorMessage = null, + ?string $uploadNoFileErrorMessage = null, + ?string $uploadNoTmpDirErrorMessage = null, + ?string $uploadCantWriteErrorMessage = null, + ?string $uploadExtensionErrorMessage = null, + ?string $uploadErrorMessage = null, + ?string $sizeNotDetectedMessage = null, + ?string $maxWidthMessage = null, + ?string $minWidthMessage = null, + ?string $maxHeightMessage = null, + ?string $minHeightMessage = null, + ?string $minPixelsMessage = null, + ?string $maxPixelsMessage = null, + ?string $maxRatioMessage = null, + ?string $minRatioMessage = null, + ?string $allowSquareMessage = null, + ?string $allowLandscapeMessage = null, + ?string $allowPortraitMessage = null, + ?string $corruptedMessage = null, + ?string $multipleVideoStreamsMessage = null, + ?string $unsupportedCodecMessage = null, + ?string $unsupportedContainerMessage = null, + ?array $groups = null, + mixed $payload = null, + ) { + static $hasFfprobe; + if (!$hasFfprobe) { + if (!class_exists(Process::class)) { + throw new LogicException('The Process component is required to use the Video constraint. Try running "composer require symfony/process".'); + } + if (!$hasFfprobe ??= (new ExecutableFinder())->find('ffprobe')) { + throw new LogicException('The ffprobe binary is required to use the Video constraint.'); + } + } + + parent::__construct( + null, + $maxSize, + $binaryFormat, + $mimeTypes, + $filenameMaxLength, + $notFoundMessage, + $notReadableMessage, + $maxSizeMessage, + $mimeTypesMessage, + $disallowEmptyMessage, + $filenameTooLongMessage, + $uploadIniSizeErrorMessage, + $uploadFormSizeErrorMessage, + $uploadPartialErrorMessage, + $uploadNoFileErrorMessage, + $uploadNoTmpDirErrorMessage, + $uploadCantWriteErrorMessage, + $uploadExtensionErrorMessage, + $uploadErrorMessage, + $groups, + $payload + ); + + $this->minWidth = $minWidth ?? $this->minWidth; + $this->maxWidth = $maxWidth ?? $this->maxWidth; + $this->maxHeight = $maxHeight ?? $this->maxHeight; + $this->minHeight = $minHeight ?? $this->minHeight; + $this->maxRatio = $maxRatio ?? $this->maxRatio; + $this->minRatio = $minRatio ?? $this->minRatio; + $this->minPixels = $minPixels ?? $this->minPixels; + $this->maxPixels = $maxPixels ?? $this->maxPixels; + $this->allowSquare = $allowSquare ?? $this->allowSquare; + $this->allowLandscape = $allowLandscape ?? $this->allowLandscape; + $this->allowPortrait = $allowPortrait ?? $this->allowPortrait; + $this->allowedCodecs = $allowedCodecs ?? $this->allowedCodecs; + $this->allowedContainers = $allowedContainers ?? $this->allowedContainers; + $this->sizeNotDetectedMessage = $sizeNotDetectedMessage ?? $this->sizeNotDetectedMessage; + $this->maxWidthMessage = $maxWidthMessage ?? $this->maxWidthMessage; + $this->minWidthMessage = $minWidthMessage ?? $this->minWidthMessage; + $this->maxHeightMessage = $maxHeightMessage ?? $this->maxHeightMessage; + $this->minHeightMessage = $minHeightMessage ?? $this->minHeightMessage; + $this->minPixelsMessage = $minPixelsMessage ?? $this->minPixelsMessage; + $this->maxPixelsMessage = $maxPixelsMessage ?? $this->maxPixelsMessage; + $this->maxRatioMessage = $maxRatioMessage ?? $this->maxRatioMessage; + $this->minRatioMessage = $minRatioMessage ?? $this->minRatioMessage; + $this->allowSquareMessage = $allowSquareMessage ?? $this->allowSquareMessage; + $this->allowLandscapeMessage = $allowLandscapeMessage ?? $this->allowLandscapeMessage; + $this->allowPortraitMessage = $allowPortraitMessage ?? $this->allowPortraitMessage; + $this->corruptedMessage = $corruptedMessage ?? $this->corruptedMessage; + $this->multipleVideoStreamsMessage = $multipleVideoStreamsMessage ?? $this->multipleVideoStreamsMessage; + $this->unsupportedCodecMessage = $unsupportedCodecMessage ?? $this->unsupportedCodecMessage; + $this->unsupportedContainerMessage = $unsupportedContainerMessage ?? $this->unsupportedContainerMessage; + + if (!\in_array('video/*', (array) $this->mimeTypes, true) && null === $mimeTypesMessage) { + $this->mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.'; + } + } +} diff --git a/Constraints/VideoValidator.php b/Constraints/VideoValidator.php new file mode 100644 index 000000000..afbe30b5f --- /dev/null +++ b/Constraints/VideoValidator.php @@ -0,0 +1,265 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Constraints; + +use Symfony\Component\Process\Process; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\UnexpectedTypeException; + +/** + * @author Kev + * @author Nicolas Grekas + */ +class VideoValidator extends FileValidator +{ + public function validate(mixed $value, Constraint $constraint): void + { + if (!$constraint instanceof Video) { + throw new UnexpectedTypeException($constraint, Video::class); + } + + $violations = \count($this->context->getViolations()); + + parent::validate($value, $constraint); + + $failed = \count($this->context->getViolations()) !== $violations; + + if ($failed || null === $value || '' === $value) { + return; + } + + if (null === $constraint->minWidth && null === $constraint->maxWidth + && null === $constraint->minHeight && null === $constraint->maxHeight + && null === $constraint->minPixels && null === $constraint->maxPixels + && null === $constraint->minRatio && null === $constraint->maxRatio + && $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait + ) { + return; + } + + $process = new Process([ + 'ffprobe', + '-v', 'error', + '-select_streams', 'v', + '-show_entries', 'stream=index,codec_type,codec_name,width,height', + '-show_entries', 'format=format_name', + '-of', 'json', + (string) $value, + ]); + $process->run(); + + if (!$process->isSuccessful()) { + $this->context->buildViolation($constraint->corruptedMessage) + ->setCode(Video::CORRUPTED_VIDEO_ERROR) + ->addViolation(); + + return; + } + + $meta = json_decode($process->getOutput(), true) ?: []; + $streams = $meta['streams'] ?? []; + $formats = explode(',', strtolower($meta['format']['format_name'] ?? 'unknown')); + + if (!($streams[0]['width'] ?? false) || !($streams[0]['height'] ?? false)) { + $this->context->buildViolation($constraint->sizeNotDetectedMessage) + ->setCode(Video::SIZE_NOT_DETECTED_ERROR) + ->addViolation(); + + return; + } + + $width = $streams[0]['width']; + $height = $streams[0]['height']; + + if (1 !== \count($streams)) { + $this->context->buildViolation($constraint->multipleVideoStreamsMessage) + ->setCode(Video::MULTIPLE_VIDEO_STREAMS_ERROR) + ->addViolation(); + + return; + } + + if ($constraint->allowedCodecs) { + foreach ($streams as $stream) { + $codec = strtolower($stream['codec_name'] ?? 'unknown'); + if (!\in_array($codec, $constraint->allowedCodecs, true)) { + $this->context->buildViolation($constraint->unsupportedCodecMessage) + ->setParameter('{{ codec }}', $codec) + ->setCode(Video::UNSUPPORTED_VIDEO_CODEC_ERROR) + ->addViolation(); + + return; + } + } + } + + if ($constraint->allowedContainers && !array_intersect($formats, $constraint->allowedContainers)) { + $this->context->buildViolation($constraint->unsupportedContainerMessage) + ->setParameter('{{ container }}', $formats[0]) + ->setCode(Video::UNSUPPORTED_VIDEO_CONTAINER_ERROR) + ->addViolation(); + + return; + } + + if ($constraint->minWidth) { + if ($constraint->minWidth < 0) { + throw new ConstraintDefinitionException(\sprintf('"%s" is not a valid minimum width.', $constraint->minWidth)); + } + + if ($width < $constraint->minWidth) { + $this->context->buildViolation($constraint->minWidthMessage) + ->setParameter('{{ width }}', $width) + ->setParameter('{{ min_width }}', $constraint->minWidth) + ->setCode(Video::TOO_NARROW_ERROR) + ->addViolation(); + + return; + } + } + + if ($constraint->maxWidth) { + if ($constraint->maxWidth < 0) { + throw new ConstraintDefinitionException(\sprintf('"%s" is not a valid maximum width.', $constraint->maxWidth)); + } + + if ($width > $constraint->maxWidth) { + $this->context->buildViolation($constraint->maxWidthMessage) + ->setParameter('{{ width }}', $width) + ->setParameter('{{ max_width }}', $constraint->maxWidth) + ->setCode(Video::TOO_WIDE_ERROR) + ->addViolation(); + + return; + } + } + + if ($constraint->minHeight) { + if ($constraint->minHeight < 0) { + throw new ConstraintDefinitionException(\sprintf('"%s" is not a valid minimum height.', $constraint->minHeight)); + } + + if ($height < $constraint->minHeight) { + $this->context->buildViolation($constraint->minHeightMessage) + ->setParameter('{{ height }}', $height) + ->setParameter('{{ min_height }}', $constraint->minHeight) + ->setCode(Video::TOO_LOW_ERROR) + ->addViolation(); + + return; + } + } + + if ($constraint->maxHeight) { + if ($constraint->maxHeight < 0) { + throw new ConstraintDefinitionException(\sprintf('"%s" is not a valid maximum height.', $constraint->maxHeight)); + } + + if ($height > $constraint->maxHeight) { + $this->context->buildViolation($constraint->maxHeightMessage) + ->setParameter('{{ height }}', $height) + ->setParameter('{{ max_height }}', $constraint->maxHeight) + ->setCode(Video::TOO_HIGH_ERROR) + ->addViolation(); + } + } + + $pixels = $width * $height; + + if (null !== $constraint->minPixels) { + if ($constraint->minPixels < 0) { + throw new ConstraintDefinitionException(\sprintf('"%s" is not a valid minimum amount of pixels.', $constraint->minPixels)); + } + + if ($pixels < $constraint->minPixels) { + $this->context->buildViolation($constraint->minPixelsMessage) + ->setParameter('{{ pixels }}', $pixels) + ->setParameter('{{ min_pixels }}', $constraint->minPixels) + ->setParameter('{{ height }}', $height) + ->setParameter('{{ width }}', $width) + ->setCode(Video::TOO_FEW_PIXEL_ERROR) + ->addViolation(); + } + } + + if (null !== $constraint->maxPixels) { + if ($constraint->maxPixels < 0) { + throw new ConstraintDefinitionException(\sprintf('"%s" is not a valid maximum amount of pixels.', $constraint->maxPixels)); + } + + if ($pixels > $constraint->maxPixels) { + $this->context->buildViolation($constraint->maxPixelsMessage) + ->setParameter('{{ pixels }}', $pixels) + ->setParameter('{{ max_pixels }}', $constraint->maxPixels) + ->setParameter('{{ height }}', $height) + ->setParameter('{{ width }}', $width) + ->setCode(Video::TOO_MANY_PIXEL_ERROR) + ->addViolation(); + } + } + + $ratio = round($height > 0 ? $width / $height : 0, 2); + + if (null !== $constraint->minRatio) { + if (!is_numeric((string) $constraint->minRatio)) { + throw new ConstraintDefinitionException(\sprintf('"%s" is not a valid minimum ratio.', $constraint->minRatio)); + } + + if ($ratio < round($constraint->minRatio, 2)) { + $this->context->buildViolation($constraint->minRatioMessage) + ->setParameter('{{ ratio }}', $ratio) + ->setParameter('{{ min_ratio }}', round($constraint->minRatio, 2)) + ->setCode(Video::RATIO_TOO_SMALL_ERROR) + ->addViolation(); + } + } + + if (null !== $constraint->maxRatio) { + if (!is_numeric((string) $constraint->maxRatio)) { + throw new ConstraintDefinitionException(\sprintf('"%s" is not a valid maximum ratio.', $constraint->maxRatio)); + } + + if ($ratio > round($constraint->maxRatio, 2)) { + $this->context->buildViolation($constraint->maxRatioMessage) + ->setParameter('{{ ratio }}', $ratio) + ->setParameter('{{ max_ratio }}', round($constraint->maxRatio, 2)) + ->setCode(Video::RATIO_TOO_BIG_ERROR) + ->addViolation(); + } + } + + if (!$constraint->allowSquare && $width == $height) { + $this->context->buildViolation($constraint->allowSquareMessage) + ->setParameter('{{ width }}', $width) + ->setParameter('{{ height }}', $height) + ->setCode(Video::SQUARE_NOT_ALLOWED_ERROR) + ->addViolation(); + } + + if (!$constraint->allowLandscape && $width > $height) { + $this->context->buildViolation($constraint->allowLandscapeMessage) + ->setParameter('{{ width }}', $width) + ->setParameter('{{ height }}', $height) + ->setCode(Video::LANDSCAPE_NOT_ALLOWED_ERROR) + ->addViolation(); + } + + if (!$constraint->allowPortrait && $width < $height) { + $this->context->buildViolation($constraint->allowPortraitMessage) + ->setParameter('{{ width }}', $width) + ->setParameter('{{ height }}', $height) + ->setCode(Video::PORTRAIT_NOT_ALLOWED_ERROR) + ->addViolation(); + } + } +} diff --git a/Tests/Constraints/Fixtures/test.mp4 b/Tests/Constraints/Fixtures/test.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..d251e5def93d168fcf46d04c43f060b16b32348d GIT binary patch literal 1556 zcmZux&5ImG6tCGOF$511R!v|dC9Ws4v)wbhlg&WGhBY_`1uy0xLQ~yUJ>5)y)Kt~X z&g39Dc+jH=Ui=3X6ugNC!9#A6qhP>`2oez@0l`Hi*7U6I45(k`n?+vTx{L>&0ss3d4} zsiM4!2Z7)9x*iv$$fs5X-lX02CcfY1g$hzN;dT^3y2`bkA{1+AWZ*YF1YzMtHc>Jp zL?02M5oKQmeuu}YsR|Jy)aTBqJkKno{mH(J9fWvT1Rjnc zO&)WAp$@AgvC0Lz+@%Hqgp*g*K&04&Cpw#FF^;lSc)T=qia0BTqhn;HQzjR1fj6)k;?k1 zi(sp?D#L!IVVx^ALI-LJ?4Y&hEyS?MN;unCl`0;gMvqQu1U1wsnso-IF;Zlw0es}cS28W zpgy%fIPrX%w1x+C9i14!_?{coIoDSl7ig6G6rIZR)Vx5)8z$OP(pm6Lm0LX8nt-st zt+5*47BUmC@Is!h{Q&9%_RgI;ZabB^sU1%t@`?8xMNE;qKUi*m@{TW6O8A)l}59|@dj6?3jxL)kru^b!5vW3E40 zFV1Gzbbxx;_=}yN{lYHw!9V`&wTBOn&)r6==<=*Lp84p)4-IxU{o~g=z1L^Q$As{l z7FL5(7Wy`DX%|g?A!Up{cG0?e01%gc2PAKzu9yVSGJeT7V7oOpt=(PNp^K}zuJ-pJ zMgx1u@$F!ZzZ^ElzxQYNTC^>smjFY|n=G9Kq_q_iA D5(Q-P literal 0 HcmV?d00001 diff --git a/Tests/Constraints/Fixtures/test_16by9.mp4 b/Tests/Constraints/Fixtures/test_16by9.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..deb4587f8e6398b40fd93aa1a56e29210ae0d400 GIT binary patch literal 1563 zcmZuxPiS047@tkBsEFneq+kjoRuJrN-rG$!ap6Hq8X82Q7kd!lF>hwxzQ?}zW->Fo z+3m$11bgt}#fx`QC>})cR1gVx6Hn5jAgNF)f*$lxLAw6tZPKi!kYn~iu_>a~y%@?>hHgzk1Jm;=9g=85U_)1P*Jy>;)-?pGgOxJ~c8 z^!p#2Fj#%_%FgBH8ohXR8gxXferuEqsR~xLl_a#h(L;=7mvWgWGE2CiC=>_93?9ft1nH*C)On^41wiCEwkBx}JRsbh#w9Lm+#6DsO zkJzxPFQc$ad1h3}Vz`FX8Cev$1=<{M3hn^-UKs^Qfr)FXl2JRn5Qa2m*2UTma_uc< z0rqsP($q>9tx=a5IQTe)QUjLZ5TD3wk#nSSEC^_2>MM9&GUwCCD<@6CU<7$m3=Nya zT$P$RoH;t=49hEofT3aDCN->-7QIShJps-|)COjPXJhZuQxp6CZ%P9 zuKKEQh}xZ2K=*ttQP9F`+S5L6&Dl8Wz6ODHQlo{r#)$A7FhRs(dzikTCAp6GyCQGA zN0z4Feg5O0KOcN><&%xYA720Vrn>j{;G1_330ZuhRB8mfq8w!ce2y0HLw}z%i2t3? ze-03zI&Ym=J`OG58`?oL22j4^2KAkbbB0IJ{N1PM)IE>A_qoHn4ycEs?t;oXS zyR8Wkj^fs_8n;T3GiYcjPS?H#@fLaOp!REKqA)eW=D)~e?DLS6w=!?GE6B2 zSRR#i(D}5_iymGzFdE#w*q(1@M7&_IM!P=1c#l1ny}*=1j7LvUdUf z^7Ma;nfzowJDuXtL)7iYU*zfOAvxCv|M25i|GE6I@oZy>qFbciF5bQL#n%mTCj0G| zgWXHh2M>IdCC#h`e;?}x)-vAiQKO%~PKaORtabGe0PBp9)t1LAsEvC7@|n)BW$3Qe z8nW>Hkq$DhX0qBg08WO&G4QubS#z&`aeh!3u3=jHUOu8`K6?!>f98}Acn*K+K8R0% Qyun84`etjR+X{o=U%5;q{YGt)h@J6Q)BHms|AP*5Z}h}u?nRZln5A2n4q zUlC*v9u!Xs3Zj32f=EQcQx3v{2T$U~fDj}gk$@t}VNZ^~>Y2@sYaUbeUcHZBy^rc4 zgwV*0Wul9WkOg8nR)Y;fH{r@2?5)!j57oN<(boy$>+cB{&Ds9YkS{)y#5Ql z_T-;`jT)^DTBTv31a(_Ys+vyAp_@EtG1h`%uLg(ui!bdyU)`V=F73dRix7sLLXJ}r z8QO51X0_ooTqt8>WV>D;4u`ct!bOp?yjG}A-QH4*O_su^kR~Z|-KHT6Sm?P_iO6eG zE`qcOyPn&2+74woOUGJx&ZyaTMy}hWnebvUqPibII!~n@BNV%@xaZa!1Yx6DG7{Xk zh%O?0#qy5u+!hUERbsD{p7e_-(!zKf)Wiw_7AGx=E{k#Sk99gtLZot}aA>Z|E5amW#-@?vMyQm*3Hl)I zD>nASB9qME9HK);u_Ols92K)Zkz$$9=vCm$G311M4akf$X^RN_AYs~Gk|Y4(-`mJg0`&)RPvs{rN57W1^B>Q;3 zb@A>y#Q$gcZSns8+Bes~I(Pe{J3l{m`ryOr?hg+wzViAf7k+x)8r9GRl632rnHRz<4uDVGF<8E%PHxtj5W!9p{Bvi5DLx5>qWGOil) zRFx7o`;i{WmS3_T?H#^53dOM|Qgolkp>Pi?Clufqm|to^~hO6gRtJf%&L zLO#$&9}UF%d~5%wz%9*VPBo`c_8vsLEdAeOsz2UWCKDXmK;5a_ArDM`BWF9{AAI`s z-(O!pti+W!_t7q5x5|C*J^EvXoQZGUIM{o3a(HM_9+6B-@G90i))JoctkKIWgxEz^ zv?+%GvCIfrZCiO2wS`sy*-Yox5^R@C3t6}^vq2XYQ(funKo0ucFz{D1QF3d3Vt!B< ou3}Q!Uf!i@GJOr_zA%LaJd6K%3t|%>FR($hxm7#gs=1EyFE)*DwEzGB literal 0 HcmV?d00001 diff --git a/Tests/Constraints/Fixtures/test_corrupted.mp4 b/Tests/Constraints/Fixtures/test_corrupted.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..a03d940035dad9a62831a6b566cdd4c36a0a1ebd GIT binary patch literal 999 zcmZuw&ubG=5S~r2l;RuFLA<==y)>b_*=6^2(|W4V zLl0hx;KhGHK|xP~;6dooKfr<)5u_rh2f?1Y&g^DQj2-s9`QCir&g{+WBccT;i+?DtUL{6up`%$&o_{~r#9l6*$Lq&8`Yk&sXC|DB~7AR zltKk~DoQ)RDa3}%C~vIM-Z-MqkztOQe)k538*t|!zOU31wjU$hsJ|&DzefGG_(0f_ zG@5k!gD!%6=)_5r#~~%aqDZ)+@Fi);h(EjO+bqG_QlQ#4;&*`x(t(iX6@6mp$tH8A z5e+Paw8;KfB=PZHh$1|!V%Dbi3+AFvaA6(&{*y~TcNcc{uvIWiTW)KA`K1Oky>Fin ztn1P7F{Q|PJn+y{8CvT>db*kJu9~Wv z*_j-~gNWCFc<~=l(1TtCK~Tt14;};qUR02X_yvMFXePhvnaPf89@F(+y^r6k_g>Wy zLTGAdDmStuq)8md7qAKUOSS70LLN!A5U_nyCd`6=aQ4i6{@!=je*WyI+x<`8x%4f) z{mgH_PlN6*ZBZ_@pnkVQb;s*^bT5g!jCEn?x8bn!;!D?_Z|%}6*N@kdX%%6@zAGQq+y39 zA}%B!hJMfMd6ZSGm>Cgz(@xKu`hJI&BFw~;nsE$ipDHs$DAq_Pq2KlpgoT#*R3wo@ z^brwhRt-excPY=bELnt5pIR-7A~%o@rUwbP5csGJJsg20H)JKkz`x}CG-bv{$_#Vm zJQe^W70EO;!iKxlW*Pwwr;u{UGHjv~ohfpTqpTDjt#qA&=Owf574W=USh{e42b z^#*xte(&!O?}@jA=|AU+U%!6sO!v!wZxXVxRZ2O5Q&CQ`1bmG)?!bPBG>H41(0?{i zpV}Xucs@*O;sHH}P7Gmu)eh^N8*7eBG?)7noyzmjyg*;-FNnk%?6yT=@MvoS!VTzUSyJd)!s4FeN_PCZd!Bt(C53Q44S^A*5H=@e4Z42p z3(3N^o!}n0V34z)AM1iHbd-205Gk^5d=k)%o4K4&qV8 zi~@IQ+_#BayX^Ag86oZ?TgKKCfVlEIbn-R|<4ypr;#YhVwi^pm^Q)yDIxZKw+TVj5 zj}yzlUnxb+o%!kYDPgjjDdigZfLi(DDqMWuN(cB9{>~kUOHN*3lXUN(z29y7o_8N} C-)0~H literal 0 HcmV?d00001 diff --git a/Tests/Constraints/Fixtures/test_portrait.mp4 b/Tests/Constraints/Fixtures/test_portrait.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..d4528785dea2dbaea6fe5fc098a2eed42ea0c574 GIT binary patch literal 1556 zcmZuxO^72!6s}}&5%J(*ltD%)aTgD6GTq5cW(+jUI=h&If*|fegtoe>I^CqZt5Q|T zBzq7KD|q$d#fv9V(1TtCL0DlA9z1$*!Gk{_D}w7ma8Db*>LfekxQ}$bSMPoAy?XCe zg%CnhH`lpUB_U1XIlc~?^03sqAtB`9)JO^2_oZMC{L^y}EfydDc;)x6f4epK^8JfH z&|A;^d1uz??a~(I%19day3}-oUO@Lm(qpU#!=Meo&daY{d9k%iFI_zXQb-QNk<#-* zrjB-kpxf#Moe;{*Io;pcIX*saPjewv!K$`0!yTWcow>3AMroI;%JwN|3FA>njZC91 z6*4IlA4Oq5=m(Tlte9IF1+#8Hn1x}NmNLrZjM_;8X`gC4hbz|Dh$w6aaKb{%d?rQg zBZlyZ4XcJS3VW1iMwKjvYe=1uMUh)b2eSjg9RxluqX0)>;+m>t)Cn(!Ax)Wev9_aJ zd&DxpSjQ?&t#r{Yb(w*Kk5ec$Vi`8^iOv=|$5GabfL5kX!Sj+ie~i3x(i99J=#ye% z*gWQ{)XZVe(IID8ULgd4hIveCSSc-fmBe}uITuj}G80VuB9b`Cne|C>BkQt`Wj@SY z0-MsZiib+Wx>Rboj^rG%qt0Hi65}$j0JdCKl21@$;7@6oZ>W(rgSX-F{c644@Q9m~ zmI=D*tHLJgblU+P`&y!)joUQVK5os~Eb2WEg>_P+g}KIva2+r~#A0Ji-_Me~jr+SL z-@Q&AU)=lWvwQNL@Xn2ozWwmopI#j*-06+2QmH90MLEp`_$k`B4f}1O=C{&DyV(iNe$p7XKR8vgcR*>m0C36w+fF5)(=xY);EMXr0Of zLFdKNwk>cCma4jpM<=GB*aO?RU|mu`{>D1H9*B?ex&K1~_jEeuTGJ#0i2n2Rf5cLM zvTiLF*z64lXb5-t{3K z)68mcpT>WixU{P-Kk+6Z{v%t~)f0fY#vOWj8-;N%fY$zNz6sm4rK$Pd$_^b@OI?i* zASV;y82Ia@thqNoeR@imtYKRFM&74ZzPt(-K5@zidOV literal 0 HcmV?d00001 diff --git a/Tests/Constraints/VideoTest.php b/Tests/Constraints/VideoTest.php new file mode 100644 index 000000000..e84fd0ee1 --- /dev/null +++ b/Tests/Constraints/VideoTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Constraints; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Process\ExecutableFinder; +use Symfony\Component\Validator\Constraints\Video; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; + +class VideoTest extends TestCase +{ + public static function setUpBeforeClass(): void + { + if (!(new ExecutableFinder())->find('ffprobe')) { + self::markTestSkipped('The ffprobe binary is required to run this test.'); + } + } + + public function testAttributes() + { + $metadata = new ClassMetadata(VideoDummy::class); + $loader = new AttributeLoader(); + self::assertTrue($loader->loadClassMetadata($metadata)); + + [$aConstraint] = $metadata->getPropertyMetadata('a')[0]->getConstraints(); + self::assertNull($aConstraint->minWidth); + self::assertNull($aConstraint->maxWidth); + self::assertNull($aConstraint->minHeight); + self::assertNull($aConstraint->maxHeight); + + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); + self::assertSame(50, $bConstraint->minWidth); + self::assertSame(200, $bConstraint->maxWidth); + self::assertSame(50, $bConstraint->minHeight); + self::assertSame(200, $bConstraint->maxHeight); + self::assertSame(['Default', 'VideoDummy'], $bConstraint->groups); + + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); + self::assertSame(100000, $cConstraint->maxSize); + self::assertSame(['my_group'], $cConstraint->groups); + self::assertSame('some attached data', $cConstraint->payload); + } +} + +class VideoDummy +{ + #[Video] + private $a; + + #[Video(minWidth: 50, maxWidth: 200, minHeight: 50, maxHeight: 200)] + private $b; + + #[Video(maxSize: '100K', groups: ['my_group'], payload: 'some attached data')] + private $c; +} diff --git a/Tests/Constraints/VideoValidatorTest.php b/Tests/Constraints/VideoValidatorTest.php new file mode 100644 index 000000000..fc5177940 --- /dev/null +++ b/Tests/Constraints/VideoValidatorTest.php @@ -0,0 +1,286 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Constraints; + +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use Symfony\Component\Process\ExecutableFinder; +use Symfony\Component\Validator\Constraints\Video; +use Symfony\Component\Validator\Constraints\VideoValidator; +use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; + +#[RequiresPhpExtension('fileinfo')] +class VideoValidatorTest extends ConstraintValidatorTestCase +{ + public static function setUpBeforeClass(): void + { + if (!(new ExecutableFinder())->find('ffprobe')) { + self::markTestSkipped('The ffprobe binary is required to run this test.'); + } + } + + protected function createValidator(): VideoValidator + { + return new VideoValidator(); + } + + public function testNullIsValid() + { + $this->validator->validate(null, new Video()); + + $this->assertNoViolation(); + } + + public function testEmptyStringIsValid() + { + $this->validator->validate('', new Video()); + + $this->assertNoViolation(); + } + + public function testValidVideo() + { + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', new Video()); + + $this->assertNoViolation(); + } + + public function testFileNotFound() + { + $constraint = new Video(notFoundMessage: 'myMessage'); + $this->validator->validate('foobar', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ file }}', '"foobar"') + ->setCode(Video::NOT_FOUND_ERROR) + ->assertRaised(); + } + + public function testValidSize() + { + $constraint = new Video( + minWidth: 1, + maxWidth: 2, + minHeight: 1, + maxHeight: 2, + ); + + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->assertNoViolation(); + } + + public function testWidthTooSmall() + { + $constraint = new Video(minWidth: 3, minWidthMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ width }}', '2') + ->setParameter('{{ min_width }}', '3') + ->setCode(Video::TOO_NARROW_ERROR) + ->assertRaised(); + } + + public function testWidthTooBig() + { + $constraint = new Video(maxWidth: 1, maxWidthMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ width }}', '2') + ->setParameter('{{ max_width }}', '1') + ->setCode(Video::TOO_WIDE_ERROR) + ->assertRaised(); + } + + public function testHeightTooSmall() + { + $constraint = new Video(minHeight: 3, minHeightMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ height }}', '2') + ->setParameter('{{ min_height }}', '3') + ->setCode(Video::TOO_LOW_ERROR) + ->assertRaised(); + } + + public function testHeightTooBig() + { + $constraint = new Video(maxHeight: 1, maxHeightMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ height }}', '2') + ->setParameter('{{ max_height }}', '1') + ->setCode(Video::TOO_HIGH_ERROR) + ->assertRaised(); + } + + public function testPixelsTooFew() + { + $constraint = new Video(minPixels: 5, minPixelsMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ pixels }}', '4') + ->setParameter('{{ min_pixels }}', '5') + ->setParameter('{{ height }}', '2') + ->setParameter('{{ width }}', '2') + ->setCode(Video::TOO_FEW_PIXEL_ERROR) + ->assertRaised(); + } + + public function testPixelsTooMany() + { + $constraint = new Video(maxPixels: 3, maxPixelsMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ pixels }}', '4') + ->setParameter('{{ max_pixels }}', '3') + ->setParameter('{{ height }}', '2') + ->setParameter('{{ width }}', '2') + ->setCode(Video::TOO_MANY_PIXEL_ERROR) + ->assertRaised(); + } + + public function testRatioTooSmall() + { + $constraint = new Video(minRatio: 2, minRatioMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ ratio }}', 1) + ->setParameter('{{ min_ratio }}', 2) + ->setCode(Video::RATIO_TOO_SMALL_ERROR) + ->assertRaised(); + } + + public function testRatioTooBig() + { + $constraint = new Video(maxRatio: 0.5, maxRatioMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ ratio }}', 1) + ->setParameter('{{ max_ratio }}', 0.5) + ->setCode(Video::RATIO_TOO_BIG_ERROR) + ->assertRaised(); + } + + public function testMaxRatioUsesTwoDecimalsOnly() + { + $constraint = new Video(maxRatio: 1.33); + + $this->validator->validate(__DIR__.'/Fixtures/test_4by3.mp4', $constraint); + + $this->assertNoViolation(); + } + + public function testMinRatioUsesInputMoreDecimals() + { + $constraint = new Video(minRatio: 4 / 3); + + $this->validator->validate(__DIR__.'/Fixtures/test_4by3.mp4', $constraint); + + $this->assertNoViolation(); + } + + public function testMaxRatioUsesInputMoreDecimals() + { + $constraint = new Video(maxRatio: 16 / 9); + + $this->validator->validate(__DIR__.'/Fixtures/test_16by9.mp4', $constraint); + + $this->assertNoViolation(); + } + + public function testSquareNotAllowed() + { + $constraint = new Video(allowSquare: false, allowSquareMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ width }}', 2) + ->setParameter('{{ height }}', 2) + ->setCode(Video::SQUARE_NOT_ALLOWED_ERROR) + ->assertRaised(); + } + + public function testLandscapeNotAllowed() + { + $constraint = new Video(allowLandscape: false, allowLandscapeMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test_landscape.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ width }}', 2) + ->setParameter('{{ height }}', 1) + ->setCode(Video::LANDSCAPE_NOT_ALLOWED_ERROR) + ->assertRaised(); + } + + public function testPortraitNotAllowed() + { + $constraint = new Video(allowPortrait: false, allowPortraitMessage: 'myMessage'); + $this->validator->validate(__DIR__.'/Fixtures/test_portrait.mp4', $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ width }}', 1) + ->setParameter('{{ height }}', 2) + ->setCode(Video::PORTRAIT_NOT_ALLOWED_ERROR) + ->assertRaised(); + } + + public function testCorrupted() + { + $constraint = new Video(maxRatio: 1); + + $this->validator->validate(__DIR__.'/Fixtures/test_corrupted.mp4', $constraint); + + $this->buildViolation('The video file is corrupted.') + ->setCode(Video::CORRUPTED_VIDEO_ERROR) + ->assertRaised(); + } + + public function testInvalidMimeType() + { + $this->validator->validate(__DIR__.'/Fixtures/ccc.txt', $constraint = new Video()); + + $this->assertSame('video/*', $constraint->mimeTypes); + + $this->buildViolation('This file is not a valid video.') + ->setParameter('{{ file }}', \sprintf('"%s/Fixtures/ccc.txt"', __DIR__)) + ->setParameter('{{ type }}', '"text/plain"') + ->setParameter('{{ types }}', '"video/*"') + ->setParameter('{{ name }}', '"ccc.txt"') + ->setCode(Video::INVALID_MIME_TYPE_ERROR) + ->assertRaised(); + } + + public function testInvalidMimeTypeWithNarrowedSet() + { + $constraint = new Video(mimeTypes: [ + 'video/mkv', + 'video/mov', + ]); + $this->validator->validate(__DIR__.'/Fixtures/test.mp4', $constraint); + + $this->buildViolation('The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.') + ->setParameter('{{ file }}', \sprintf('"%s/Fixtures/test.mp4"', __DIR__)) + ->setParameter('{{ type }}', '"video/mp4"') + ->setParameter('{{ types }}', '"video/mkv", "video/mov"') + ->setParameter('{{ name }}', '"test.mp4"') + ->setCode(Video::INVALID_MIME_TYPE_ERROR) + ->assertRaised(); + } +} diff --git a/composer.json b/composer.json index de1c6c190..0af683361 100644 --- a/composer.json +++ b/composer.json @@ -36,6 +36,7 @@ "symfony/expression-language": "^6.4|^7.0|^8.0", "symfony/cache": "^6.4|^7.0|^8.0", "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", "symfony/property-access": "^6.4|^7.0|^8.0", "symfony/property-info": "^6.4|^7.0|^8.0", "symfony/string": "^6.4|^7.0|^8.0", From 1b35885e510c2b8ef82611e9b3a61ca8000ad1bf Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 25 Aug 2025 18:14:32 +0200 Subject: [PATCH 38/57] [Validator] Allow using attributes to declare compile-time constraint metadata --- CHANGELOG.md | 1 + Constraint.php | 1 + DependencyInjection/AttributeMetadataPass.php | 50 +++++++++++ Mapping/Loader/AttributeLoader.php | 21 +++++ Mapping/Loader/XmlFileLoader.php | 4 +- Mapping/Loader/YamlFileLoader.php | 2 +- .../AttributeMetadataPassTest.php | 73 +++++++++++++++ Tests/Mapping/Loader/AttributeLoaderTest.php | 88 ++++++++++++------- ValidatorBuilder.php | 25 +++++- 9 files changed, 225 insertions(+), 40 deletions(-) create mode 100644 DependencyInjection/AttributeMetadataPass.php create mode 100644 Tests/DependencyInjection/AttributeMetadataPassTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 52edebc7a..a444f23f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.4 --- + * Add `ValidatorBuilder::addAttributeMappings()` and `AttributeMetadataPass` to declare compile-time constraint metadata using attributes * Add the `Video` constraint for validating video files * Deprecate implementing `__sleep/wakeup()` on `GenericMetadata` implementations; use `__(un)serialize()` instead * Deprecate passing a list of choices to the first argument of the `Choice` constraint. Use the `choices` option instead diff --git a/Constraint.php b/Constraint.php index 47dd9b42d..31012450a 100644 --- a/Constraint.php +++ b/Constraint.php @@ -27,6 +27,7 @@ * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] abstract class Constraint { /** diff --git a/DependencyInjection/AttributeMetadataPass.php b/DependencyInjection/AttributeMetadataPass.php new file mode 100644 index 000000000..d87b15c2f --- /dev/null +++ b/DependencyInjection/AttributeMetadataPass.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * @author Nicolas Grekas + */ +final class AttributeMetadataPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + if (!$container->hasDefinition('validator.builder')) { + return; + } + + $resolve = $container->getParameterBag()->resolveValue(...); + $mappedClasses = []; + foreach ($container->getDefinitions() as $id => $definition) { + if (!$definition->hasTag('validator.attribute_metadata')) { + continue; + } + if (!$definition->hasTag('container.excluded')) { + throw new InvalidArgumentException(\sprintf('The resource "%s" tagged "validator.attribute_metadata" is missing the "container.excluded" tag.', $id)); + } + $mappedClasses[$resolve($definition->getClass())] = true; + } + + if (!$mappedClasses) { + return; + } + + ksort($mappedClasses); + + $container->getDefinition('validator.builder') + ->addMethodCall('addAttributeMappings', [array_keys($mappedClasses)]); + } +} diff --git a/Mapping/Loader/AttributeLoader.php b/Mapping/Loader/AttributeLoader.php index ddf0b78b7..24a474f88 100644 --- a/Mapping/Loader/AttributeLoader.php +++ b/Mapping/Loader/AttributeLoader.php @@ -27,8 +27,29 @@ */ class AttributeLoader implements LoaderInterface { + /** + * @param class-string[] $mappedClasses + */ + public function __construct( + private bool $allowAnyClass = true, + private array $mappedClasses = [], + ) { + } + + /** + * @return class-string[] + */ + public function getMappedClasses(): array + { + return $this->mappedClasses; + } + public function loadClassMetadata(ClassMetadata $metadata): bool { + if (!$this->allowAnyClass && !\in_array($metadata->getClassName(), $this->mappedClasses, true)) { + return false; + } + $reflClass = $metadata->getReflectionClass(); $className = $reflClass->name; $success = false; diff --git a/Mapping/Loader/XmlFileLoader.php b/Mapping/Loader/XmlFileLoader.php index 83a14b2e8..9bc8b449c 100644 --- a/Mapping/Loader/XmlFileLoader.php +++ b/Mapping/Loader/XmlFileLoader.php @@ -26,7 +26,7 @@ class XmlFileLoader extends FileLoader /** * The XML nodes of the mapping file. * - * @var \SimpleXMLElement[] + * @var array */ protected array $classes; @@ -55,7 +55,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool /** * Return the names of the classes mapped in this file. * - * @return string[] + * @return class-string[] */ public function getMappedClasses(): array { diff --git a/Mapping/Loader/YamlFileLoader.php b/Mapping/Loader/YamlFileLoader.php index 78d1b0ef9..047fa2194 100644 --- a/Mapping/Loader/YamlFileLoader.php +++ b/Mapping/Loader/YamlFileLoader.php @@ -56,7 +56,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool /** * Return the names of the classes mapped in this file. * - * @return string[] + * @return class-string[] */ public function getMappedClasses(): array { diff --git a/Tests/DependencyInjection/AttributeMetadataPassTest.php b/Tests/DependencyInjection/AttributeMetadataPassTest.php new file mode 100644 index 000000000..8909013fe --- /dev/null +++ b/Tests/DependencyInjection/AttributeMetadataPassTest.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Validator\DependencyInjection\AttributeMetadataPass; + +class AttributeMetadataPassTest extends TestCase +{ + public function testProcessWithNoValidatorBuilder() + { + $container = new ContainerBuilder(); + + // Should not throw any exception + (new AttributeMetadataPass())->process($container); + + $this->expectNotToPerformAssertions(); + } + + public function testProcessWithValidatorBuilderButNoTaggedServices() + { + $container = new ContainerBuilder(); + $container->register('validator.builder'); + + $pass = new AttributeMetadataPass(); + $pass->process($container); + + $methodCalls = $container->getDefinition('validator.builder')->getMethodCalls(); + $this->assertCount(0, $methodCalls); + } + + public function testProcessWithTaggedServices() + { + $container = new ContainerBuilder(); + $container->setParameter('user_entity.class', 'App\Entity\User'); + $container->register('validator.builder') + ->addMethodCall('addAttributeMappings', [[]]); + + $container->register('service1', '%user_entity.class%') + ->addTag('validator.attribute_metadata') + ->addTag('container.excluded'); + $container->register('service2', 'App\Entity\Product') + ->addTag('validator.attribute_metadata') + ->addTag('container.excluded'); + $container->register('service3', 'App\Entity\Order') + ->addTag('validator.attribute_metadata') + ->addTag('container.excluded'); + // Classes should be deduplicated + $container->register('service4', 'App\Entity\Order') + ->addTag('validator.attribute_metadata') + ->addTag('container.excluded'); + + (new AttributeMetadataPass())->process($container); + + $methodCalls = $container->getDefinition('validator.builder')->getMethodCalls(); + $this->assertCount(2, $methodCalls); + $this->assertEquals('addAttributeMappings', $methodCalls[1][0]); + + // Classes should be sorted alphabetically + $expectedClasses = ['App\Entity\Order', 'App\Entity\Product', 'App\Entity\User']; + $this->assertEquals([$expectedClasses], $methodCalls[1][1]); + } +} diff --git a/Tests/Mapping/Loader/AttributeLoaderTest.php b/Tests/Mapping/Loader/AttributeLoaderTest.php index 9285117f9..1a0cf4f96 100644 --- a/Tests/Mapping/Loader/AttributeLoaderTest.php +++ b/Tests/Mapping/Loader/AttributeLoaderTest.php @@ -30,21 +30,27 @@ use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; +use Symfony\Component\Validator\Tests\Dummy\DummyGroupProvider; +use Symfony\Component\Validator\Tests\Fixtures\Attribute\GroupProviderDto; +use Symfony\Component\Validator\Tests\Fixtures\CallbackClass; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; +use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity; +use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\EntityParent; +use Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\GroupSequenceProviderEntity; class AttributeLoaderTest extends TestCase { public function testLoadClassMetadataReturnsTrueIfSuccessful() { - $loader = $this->createAttributeLoader(); - $metadata = new ClassMetadata($this->getFixtureNamespace().'\Entity'); + $loader = new AttributeLoader(); + $metadata = new ClassMetadata(Entity::class); $this->assertTrue($loader->loadClassMetadata($metadata)); } public function testLoadClassMetadataReturnsFalseIfNotSuccessful() { - $loader = $this->createAttributeLoader(); + $loader = new AttributeLoader(); $metadata = new ClassMetadata('\stdClass'); $this->assertFalse($loader->loadClassMetadata($metadata)); @@ -52,17 +58,16 @@ public function testLoadClassMetadataReturnsFalseIfNotSuccessful() public function testLoadClassMetadata() { - $loader = $this->createAttributeLoader(); - $namespace = $this->getFixtureNamespace(); + $loader = new AttributeLoader(); - $metadata = new ClassMetadata($namespace.'\Entity'); + $metadata = new ClassMetadata(Entity::class); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata($namespace.'\Entity'); + $expected = new ClassMetadata(Entity::class); $expected->setGroupSequence(['Foo', 'Entity']); $expected->addConstraint(new ConstraintA()); - $expected->addConstraint(new Callback(['Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback'])); + $expected->addConstraint(new Callback([CallbackClass::class, 'callback'])); $expected->addConstraint(new Sequentially([ new Expression('this.getFirstName() != null'), ])); @@ -108,14 +113,13 @@ public function testLoadClassMetadata() */ public function testLoadParentClassMetadata() { - $loader = $this->createAttributeLoader(); - $namespace = $this->getFixtureNamespace(); + $loader = new AttributeLoader(); // Load Parent MetaData - $parent_metadata = new ClassMetadata($namespace.'\EntityParent'); + $parent_metadata = new ClassMetadata(EntityParent::class); $loader->loadClassMetadata($parent_metadata); - $expected_parent = new ClassMetadata($namespace.'\EntityParent'); + $expected_parent = new ClassMetadata(EntityParent::class); $expected_parent->addPropertyConstraint('other', new NotNull()); $expected_parent->getReflectionClass(); @@ -127,28 +131,27 @@ public function testLoadParentClassMetadata() */ public function testLoadClassMetadataAndMerge() { - $loader = $this->createAttributeLoader(); - $namespace = $this->getFixtureNamespace(); + $loader = new AttributeLoader(); // Load Parent MetaData - $parent_metadata = new ClassMetadata($namespace.'\EntityParent'); + $parent_metadata = new ClassMetadata(EntityParent::class); $loader->loadClassMetadata($parent_metadata); - $metadata = new ClassMetadata($namespace.'\Entity'); + $metadata = new ClassMetadata(Entity::class); $loader->loadClassMetadata($metadata); // Merge parent metaData. $metadata->mergeConstraints($parent_metadata); - $expected_parent = new ClassMetadata($namespace.'\EntityParent'); + $expected_parent = new ClassMetadata(EntityParent::class); $expected_parent->addPropertyConstraint('other', new NotNull()); $expected_parent->getReflectionClass(); - $expected = new ClassMetadata($namespace.'\Entity'); + $expected = new ClassMetadata(Entity::class); $expected->setGroupSequence(['Foo', 'Entity']); $expected->addConstraint(new ConstraintA()); - $expected->addConstraint(new Callback(['Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback'])); + $expected->addConstraint(new Callback([CallbackClass::class, 'callback'])); $expected->addConstraint(new Sequentially([ new Expression('this.getFirstName() != null'), ])); @@ -197,13 +200,12 @@ public function testLoadClassMetadataAndMerge() public function testLoadGroupSequenceProviderAttribute() { - $loader = $this->createAttributeLoader(); - $namespace = $this->getFixtureNamespace(); + $loader = new AttributeLoader(); - $metadata = new ClassMetadata($namespace.'\GroupSequenceProviderEntity'); + $metadata = new ClassMetadata(GroupSequenceProviderEntity::class); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata($namespace.'\GroupSequenceProviderEntity'); + $expected = new ClassMetadata(GroupSequenceProviderEntity::class); $expected->setGroupSequenceProvider(true); $expected->getReflectionClass(); @@ -212,32 +214,50 @@ public function testLoadGroupSequenceProviderAttribute() public function testLoadExternalGroupSequenceProvider() { - $loader = $this->createAttributeLoader(); - $namespace = $this->getFixtureAttributeNamespace(); + $loader = new AttributeLoader(); - $metadata = new ClassMetadata($namespace.'\GroupProviderDto'); + $metadata = new ClassMetadata(GroupProviderDto::class); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata($namespace.'\GroupProviderDto'); - $expected->setGroupProvider('Symfony\Component\Validator\Tests\Dummy\DummyGroupProvider'); + $expected = new ClassMetadata(GroupProviderDto::class); + $expected->setGroupProvider(DummyGroupProvider::class); $expected->setGroupSequenceProvider(true); $expected->getReflectionClass(); $this->assertEquals($expected, $metadata); } - protected function createAttributeLoader(): AttributeLoader + public function testGetMappedClasses() { - return new AttributeLoader(); + $classes = ['App\Entity\User', 'App\Entity\Product', 'App\Entity\Order']; + $loader = new AttributeLoader(false, $classes); + + $this->assertSame($classes, $loader->getMappedClasses()); } - protected function getFixtureNamespace(): string + public function testLoadClassMetadataReturnsFalseForUnmappedClass() { - return 'Symfony\Component\Validator\Tests\Fixtures\NestedAttribute'; + $loader = new AttributeLoader(false, ['App\Entity\User']); + $metadata = new ClassMetadata('App\Entity\Product'); + + $this->assertFalse($loader->loadClassMetadata($metadata)); } - protected function getFixtureAttributeNamespace(): string + public function testLoadClassMetadataReturnsFalseForClassWithoutAttributes() { - return 'Symfony\Component\Validator\Tests\Fixtures\Attribute'; + $loader = new AttributeLoader(false, ['stdClass']); + $metadata = new ClassMetadata('stdClass'); + + $this->assertFalse($loader->loadClassMetadata($metadata)); + } + + public function testLoadClassMetadataForMappedClassWithAttributes() + { + $loader = new AttributeLoader(false, [Entity::class]); + $metadata = new ClassMetadata(Entity::class); + + $this->assertTrue($loader->loadClassMetadata($metadata)); + + $this->assertNotEmpty($metadata->getConstraints()); } } diff --git a/ValidatorBuilder.php b/ValidatorBuilder.php index 917f1c57a..7c47ee8e5 100644 --- a/ValidatorBuilder.php +++ b/ValidatorBuilder.php @@ -44,6 +44,7 @@ class ValidatorBuilder private array $xmlMappings = []; private array $yamlMappings = []; private array $methodMappings = []; + private array $attributeMappings = []; private bool $enableAttributeMapping = false; private ?MetadataFactoryInterface $metadataFactory = null; private ConstraintValidatorFactoryInterface $validatorFactory; @@ -148,6 +149,24 @@ public function addYamlMappings(array $paths): static return $this; } + /** + * Adds a list of classes with mapping constraints as attributes. + * + * @param class-string[] $classes The paths to the mapping classes + * + * @return $this + */ + public function addAttributeMappings(array $classes): static + { + if (null !== $this->metadataFactory) { + throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); + } + + $this->attributeMappings = array_merge($this->attributeMappings, $classes); + + return $this; + } + /** * Enables constraint mapping using the given static method. * @@ -217,7 +236,7 @@ public function disableAttributeMapping(): static */ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory): static { - if (\count($this->xmlMappings) > 0 || \count($this->yamlMappings) > 0 || \count($this->methodMappings) > 0 || $this->enableAttributeMapping) { + if ($this->xmlMappings || $this->yamlMappings || $this->methodMappings || $this->attributeMappings || $this->enableAttributeMapping) { throw new ValidatorException('You cannot set a custom metadata factory after adding custom mappings. You should do either of both.'); } @@ -331,8 +350,8 @@ public function getLoaders(): array $loaders[] = new StaticMethodLoader($methodName); } - if ($this->enableAttributeMapping) { - $loaders[] = new AttributeLoader(); + if ($this->enableAttributeMapping || $this->attributeMappings) { + $loaders[] = new AttributeLoader($this->enableAttributeMapping, $this->attributeMappings); } return array_merge($loaders, $this->loaders); From 249bb3b3459ef6e94366222577f922cde98e7060 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 28 Aug 2025 10:05:29 +0200 Subject: [PATCH 39/57] [Validator] Add `#[ExtendsValidationFor]` to declare new constraints for a class --- Attribute/ExtendsValidationFor.php | 32 ++++++ CHANGELOG.md | 1 + DependencyInjection/AttributeMetadataPass.php | 30 +++++- Mapping/Loader/AttributeLoader.php | 18 +++- .../AttributeMetadataPassTest.php | 79 ++++++++++++++- Tests/Mapping/Loader/AttributeLoaderTest.php | 98 ++++++++++++++++++- ValidatorBuilder.php | 9 +- 7 files changed, 252 insertions(+), 15 deletions(-) create mode 100644 Attribute/ExtendsValidationFor.php diff --git a/Attribute/ExtendsValidationFor.php b/Attribute/ExtendsValidationFor.php new file mode 100644 index 000000000..1d7b50cbb --- /dev/null +++ b/Attribute/ExtendsValidationFor.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Attribute; + +/** + * Declares that constraints listed on the current class should be added to the given class. + * + * Classes that use this attribute should contain only properties and methods that + * exist on the target class (not necessarily all of them). + * + * @author Nicolas Grekas + */ +#[\Attribute(\Attribute::TARGET_CLASS)] +final class ExtendsValidationFor +{ + /** + * @param class-string $class + */ + public function __construct( + public string $class, + ) { + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md index a444f23f9..535edccd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.4 --- + * Add `#[ExtendsValidationFor]` to declare new constraints for a class * Add `ValidatorBuilder::addAttributeMappings()` and `AttributeMetadataPass` to declare compile-time constraint metadata using attributes * Add the `Video` constraint for validating video files * Deprecate implementing `__sleep/wakeup()` on `GenericMetadata` implementations; use `__(un)serialize()` instead diff --git a/DependencyInjection/AttributeMetadataPass.php b/DependencyInjection/AttributeMetadataPass.php index d87b15c2f..a337504a5 100644 --- a/DependencyInjection/AttributeMetadataPass.php +++ b/DependencyInjection/AttributeMetadataPass.php @@ -14,6 +14,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\Validator\Exception\MappingException; /** * @author Nicolas Grekas @@ -35,7 +36,14 @@ public function process(ContainerBuilder $container): void if (!$definition->hasTag('container.excluded')) { throw new InvalidArgumentException(\sprintf('The resource "%s" tagged "validator.attribute_metadata" is missing the "container.excluded" tag.', $id)); } - $mappedClasses[$resolve($definition->getClass())] = true; + $class = $resolve($definition->getClass()); + foreach ($definition->getTag('validator.attribute_metadata') as $attributes) { + if ($class !== $for = $attributes['for'] ?? $class) { + $this->checkSourceMapsToTarget($container, $class, $for); + } + + $mappedClasses[$for][$class] = true; + } } if (!$mappedClasses) { @@ -45,6 +53,24 @@ public function process(ContainerBuilder $container): void ksort($mappedClasses); $container->getDefinition('validator.builder') - ->addMethodCall('addAttributeMappings', [array_keys($mappedClasses)]); + ->addMethodCall('addAttributeMappings', [array_map('array_keys', $mappedClasses)]); + } + + private function checkSourceMapsToTarget(ContainerBuilder $container, string $source, string $target): void + { + $source = $container->getReflectionClass($source); + $target = $container->getReflectionClass($target); + + foreach ($source->getProperties() as $p) { + if ($p->class === $source->name && !($target->hasProperty($p->name) && $target->getProperty($p->name)->class === $target->name)) { + throw new MappingException(\sprintf('The property "%s" on "%s" is not present on "%s".', $p->name, $source->name, $target->name)); + } + } + + foreach ($source->getMethods() as $m) { + if ($m->class === $source->name && !($target->hasMethod($m->name) && $target->getMethod($m->name)->class === $target->name)) { + throw new MappingException(\sprintf('The method "%s" on "%s" is not present on "%s".', $m->name, $source->name, $target->name)); + } + } } } diff --git a/Mapping/Loader/AttributeLoader.php b/Mapping/Loader/AttributeLoader.php index 24a474f88..0852823aa 100644 --- a/Mapping/Loader/AttributeLoader.php +++ b/Mapping/Loader/AttributeLoader.php @@ -28,7 +28,7 @@ class AttributeLoader implements LoaderInterface { /** - * @param class-string[] $mappedClasses + * @param array $mappedClasses */ public function __construct( private bool $allowAnyClass = true, @@ -41,16 +41,26 @@ public function __construct( */ public function getMappedClasses(): array { - return $this->mappedClasses; + return array_keys($this->mappedClasses); } public function loadClassMetadata(ClassMetadata $metadata): bool { - if (!$this->allowAnyClass && !\in_array($metadata->getClassName(), $this->mappedClasses, true)) { + if (!$sourceClasses = $this->mappedClasses[$metadata->getClassName()] ??= $this->allowAnyClass ? [$metadata->getClassName()] : []) { return false; } - $reflClass = $metadata->getReflectionClass(); + $success = false; + foreach ($sourceClasses as $sourceClass) { + $reflClass = $metadata->getClassName() === $sourceClass ? $metadata->getReflectionClass() : new \ReflectionClass($sourceClass); + $success = $this->doLoadClassMetadata($reflClass, $metadata) || $success; + } + + return $success; + } + + public function doLoadClassMetadata(\ReflectionClass $reflClass, ClassMetadata $metadata): bool + { $className = $reflClass->name; $success = false; diff --git a/Tests/DependencyInjection/AttributeMetadataPassTest.php b/Tests/DependencyInjection/AttributeMetadataPassTest.php index 8909013fe..611db9343 100644 --- a/Tests/DependencyInjection/AttributeMetadataPassTest.php +++ b/Tests/DependencyInjection/AttributeMetadataPassTest.php @@ -13,7 +13,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\Validator\DependencyInjection\AttributeMetadataPass; +use Symfony\Component\Validator\Exception\MappingException; class AttributeMetadataPassTest extends TestCase { @@ -67,7 +69,82 @@ public function testProcessWithTaggedServices() $this->assertEquals('addAttributeMappings', $methodCalls[1][0]); // Classes should be sorted alphabetically - $expectedClasses = ['App\Entity\Order', 'App\Entity\Product', 'App\Entity\User']; + $expectedClasses = [ + 'App\Entity\Order' => ['App\Entity\Order'], + 'App\Entity\Product' => ['App\Entity\Product'], + 'App\Entity\User' => ['App\Entity\User'], + ]; $this->assertEquals([$expectedClasses], $methodCalls[1][1]); } + + public function testThrowsWhenMissingExcludedTag() + { + $container = new ContainerBuilder(); + $container->register('validator.builder'); + + $container->register('service_without_excluded', 'App\\Entity\\User') + ->addTag('validator.attribute_metadata'); + + $this->expectException(InvalidArgumentException::class); + (new AttributeMetadataPass())->process($container); + } + + public function testProcessWithForOptionAndMatchingMembers() + { + $sourceClass = _AttrMeta_Source::class; + $targetClass = _AttrMeta_Target::class; + + $container = new ContainerBuilder(); + $container->register('validator.builder'); + + $container->register('service.source', $sourceClass) + ->addTag('validator.attribute_metadata', ['for' => $targetClass]) + ->addTag('container.excluded'); + + (new AttributeMetadataPass())->process($container); + + $methodCalls = $container->getDefinition('validator.builder')->getMethodCalls(); + $this->assertNotEmpty($methodCalls); + $this->assertSame('addAttributeMappings', $methodCalls[0][0]); + $this->assertSame([$targetClass => [$sourceClass]], $methodCalls[0][1][0]); + } + + public function testProcessWithForOptionAndMissingMemberThrows() + { + $sourceClass = _AttrMeta_BadSource::class; + $targetClass = _AttrMeta_Target::class; + + $container = new ContainerBuilder(); + $container->register('validator.builder'); + + $container->register('service.source', $sourceClass) + ->addTag('validator.attribute_metadata', ['for' => $targetClass]) + ->addTag('container.excluded'); + + $this->expectException(MappingException::class); + (new AttributeMetadataPass())->process($container); + } +} + +class _AttrMeta_Source +{ + public string $name; + + public function getName() + { + } +} + +class _AttrMeta_Target +{ + public string $name; + + public function getName() + { + } +} + +class _AttrMeta_BadSource +{ + public string $extra; } diff --git a/Tests/Mapping/Loader/AttributeLoaderTest.php b/Tests/Mapping/Loader/AttributeLoaderTest.php index 1a0cf4f96..7113fc743 100644 --- a/Tests/Mapping/Loader/AttributeLoaderTest.php +++ b/Tests/Mapping/Loader/AttributeLoaderTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Validator\Tests\Mapping\Loader; use PHPUnit\Framework\TestCase; +use Symfony\Component\Validator\Attribute\ExtendsValidationFor; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\AtLeastOneOf; use Symfony\Component\Validator\Constraints\Callback; @@ -229,15 +230,19 @@ public function testLoadExternalGroupSequenceProvider() public function testGetMappedClasses() { - $classes = ['App\Entity\User', 'App\Entity\Product', 'App\Entity\Order']; + $classes = [ + 'App\Entity\User' => ['App\Entity\User'], + 'App\Entity\Product' => ['App\Entity\Product'], + 'App\Entity\Order' => ['App\Entity\Order'], + ]; $loader = new AttributeLoader(false, $classes); - $this->assertSame($classes, $loader->getMappedClasses()); + $this->assertSame(array_keys($classes), $loader->getMappedClasses()); } public function testLoadClassMetadataReturnsFalseForUnmappedClass() { - $loader = new AttributeLoader(false, ['App\Entity\User']); + $loader = new AttributeLoader(false, ['App\Entity\User' => ['App\Entity\User']]); $metadata = new ClassMetadata('App\Entity\Product'); $this->assertFalse($loader->loadClassMetadata($metadata)); @@ -245,7 +250,7 @@ public function testLoadClassMetadataReturnsFalseForUnmappedClass() public function testLoadClassMetadataReturnsFalseForClassWithoutAttributes() { - $loader = new AttributeLoader(false, ['stdClass']); + $loader = new AttributeLoader(false, ['stdClass' => ['stdClass']]); $metadata = new ClassMetadata('stdClass'); $this->assertFalse($loader->loadClassMetadata($metadata)); @@ -253,11 +258,94 @@ public function testLoadClassMetadataReturnsFalseForClassWithoutAttributes() public function testLoadClassMetadataForMappedClassWithAttributes() { - $loader = new AttributeLoader(false, [Entity::class]); + $loader = new AttributeLoader(false, [Entity::class => [Entity::class]]); $metadata = new ClassMetadata(Entity::class); $this->assertTrue($loader->loadClassMetadata($metadata)); $this->assertNotEmpty($metadata->getConstraints()); } + + public function testLoadClassMetadataFromExplicitAttributeMappings() + { + $targetClass = _AttrMap_Target::class; + $sourceClass = _AttrMap_Source::class; + + $loader = new AttributeLoader(false, [$targetClass => [$sourceClass]]); + $metadata = new ClassMetadata($targetClass); + + $this->assertTrue($loader->loadClassMetadata($metadata)); + $this->assertInstanceOf(NotBlank::class, $metadata->getPropertyMetadata('name', $sourceClass)[0]->getConstraints()[0]); + } + + public function testLoadClassMetadataWithClassLevelConstraints() + { + $targetClass = _AttrMap_Target::class; + $sourceClass = _AttrMap_ClassLevelSource::class; + + $loader = new AttributeLoader(false, [$targetClass => [$sourceClass]]); + $metadata = new ClassMetadata($targetClass); + + $this->assertTrue($loader->loadClassMetadata($metadata)); + + // Check that class-level constraints are added to the target + $constraints = $metadata->getConstraints(); + $this->assertCount(2, $constraints); + + // Check for Callback constraint + $callbackConstraint = null; + foreach ($constraints as $constraint) { + if ($constraint instanceof Callback) { + $callbackConstraint = $constraint; + break; + } + } + $this->assertInstanceOf(Callback::class, $callbackConstraint); + $this->assertEquals('validateClass', $callbackConstraint->callback); + + // Check for Expression constraint + $expressionConstraint = null; + foreach ($constraints as $constraint) { + if ($constraint instanceof Expression) { + $expressionConstraint = $constraint; + break; + } + } + $this->assertInstanceOf(Expression::class, $expressionConstraint); + $this->assertEquals('this.name != null', $expressionConstraint->expression); + + // Check that property constraints are also added + $this->assertInstanceOf(NotBlank::class, $metadata->getPropertyMetadata('name', $sourceClass)[0]->getConstraints()[0]); + } +} + +class _AttrMap_Target +{ + public string $name; + + public function getName() + { + return $this->name; + } + + public function validateClass() + { + // This method will be called by the Callback constraint + return true; + } +} + +#[ExtendsValidationFor(_AttrMap_Target::class)] +class _AttrMap_Source +{ + #[NotBlank] public string $name; +} + +#[ExtendsValidationFor(_AttrMap_Target::class)] +#[Callback('validateClass')] +#[Expression('this.name != null')] +class _AttrMap_ClassLevelSource +{ + #[NotBlank] + public string $name = ''; } diff --git a/ValidatorBuilder.php b/ValidatorBuilder.php index 7c47ee8e5..b51299016 100644 --- a/ValidatorBuilder.php +++ b/ValidatorBuilder.php @@ -150,9 +150,12 @@ public function addYamlMappings(array $paths): static } /** - * Adds a list of classes with mapping constraints as attributes. + * Adds classes with mapping constraints as attributes. * - * @param class-string[] $classes The paths to the mapping classes + * The keys are the classes on which the constraints should be added. + * The values are the classes that contain the constraints to add as attributes. + * + * @param array> $classes * * @return $this */ @@ -162,7 +165,7 @@ public function addAttributeMappings(array $classes): static throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } - $this->attributeMappings = array_merge($this->attributeMappings, $classes); + $this->attributeMappings = array_merge_recursive($this->attributeMappings, $classes); return $this; } From 5cccfdd134f5b7e7f1afcb4cab865e9140ef4efa Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 4 Sep 2025 09:40:30 +0200 Subject: [PATCH 40/57] fix tests --- Tests/Mapping/Loader/XmlFileLoaderTest.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Tests/Mapping/Loader/XmlFileLoaderTest.php b/Tests/Mapping/Loader/XmlFileLoaderTest.php index 3b37182de..199a10a2a 100644 --- a/Tests/Mapping/Loader/XmlFileLoaderTest.php +++ b/Tests/Mapping/Loader/XmlFileLoaderTest.php @@ -203,9 +203,8 @@ public function testLoadConstraintWithoutNamedArgumentsSupport() $loader->loadClassMetadata($metadata); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testLengthConstraintValueOptionTriggersDeprecation() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-exactly-value.xml'); @@ -214,7 +213,7 @@ public function testLengthConstraintValueOptionTriggersDeprecation() $this->expectUserDeprecationMessage(\sprintf('Since symfony/validator 7.3: Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', Length::class)); $loader->loadClassMetadata($metadata); - $constraints = $metadata->getPropertyMetadata('title')[0]->constraints; + $constraints = $metadata->getPropertyMetadata('title')[0]->getConstraints(); self::assertCount(1, $constraints); self::assertInstanceOf(Length::class, $constraints[0]); From 198faf4be227c436df366601b1a0109ef59e6e92 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 4 Sep 2025 11:40:24 +0200 Subject: [PATCH 41/57] [DependencyInjection][Validator] Remove needless code --- Constraint.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Constraint.php b/Constraint.php index 31012450a..47dd9b42d 100644 --- a/Constraint.php +++ b/Constraint.php @@ -27,7 +27,6 @@ * * @author Bernhard Schussek */ -#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] abstract class Constraint { /** From 0d123f3fb08c04a2e102386468bdbe0042fcaf97 Mon Sep 17 00:00:00 2001 From: Santiago San Martin Date: Sun, 7 Sep 2025 18:50:47 -0300 Subject: [PATCH 42/57] Use `>=` operator in `#[RequiresPhp]` attributes to allow compatible versions --- Tests/Constraints/WhenTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Constraints/WhenTest.php b/Tests/Constraints/WhenTest.php index 7654a26b0..f4dd94a0b 100644 --- a/Tests/Constraints/WhenTest.php +++ b/Tests/Constraints/WhenTest.php @@ -123,7 +123,7 @@ public function testAttributes() self::assertSame(['foo'], $quuxConstraint->groups); } - #[RequiresPhp('8.5')] + #[RequiresPhp('>=8.5')] public function testAttributesWithClosure() { $loader = new AttributeLoader(); From 012b1213352c30eafbeb111ac9201ba699c527f6 Mon Sep 17 00:00:00 2001 From: alekLexis Date: Tue, 27 May 2025 11:29:58 +0200 Subject: [PATCH 43/57] [Validator] Add option to allow ANY protocol in Assert\Url constraint --- Constraints/Url.php | 2 +- Constraints/UrlValidator.php | 9 +- Tests/Constraints/UrlValidatorTest.php | 109 +++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 2 deletions(-) diff --git a/Constraints/Url.php b/Constraints/Url.php index 8a7549cb9..01d365c6e 100644 --- a/Constraints/Url.php +++ b/Constraints/Url.php @@ -40,7 +40,7 @@ class Url extends Constraint public $normalizer; /** - * @param string[]|null $protocols The protocols considered to be valid for the URL (e.g. http, https, ftp, etc.) (defaults to ['http', 'https'] + * @param string[]|null $protocols The protocols considered to be valid for the URL (e.g. http, https, ftp, etc.) (defaults to ['http', 'https']; use ['*'] to allow any protocol or regex patterns like ['.*'] for custom matching) * @param bool|null $relativeProtocol Whether to accept URL without the protocol (i.e. //example.com) (defaults to false) * @param string[]|null $groups * @param bool|null $requireTld Whether to require the URL to include a top-level domain (defaults to false) diff --git a/Constraints/UrlValidator.php b/Constraints/UrlValidator.php index 0716b1173..3047dbb4e 100644 --- a/Constraints/UrlValidator.php +++ b/Constraints/UrlValidator.php @@ -73,8 +73,15 @@ public function validate(mixed $value, Constraint $constraint): void $value = ($constraint->normalizer)($value); } + if (['*'] === $constraint->protocols) { + // Use RFC 3986 compliant scheme pattern: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + $protocols = '[a-zA-Z][a-zA-Z0-9+.-]*'; + } else { + $protocols = implode('|', $constraint->protocols); + } + $pattern = $constraint->relativeProtocol ? str_replace('(%s):', '(?:(%s):)?', static::PATTERN) : static::PATTERN; - $pattern = \sprintf($pattern, implode('|', $constraint->protocols)); + $pattern = sprintf($pattern, $protocols); if (!preg_match($pattern, $value)) { $this->context->buildViolation($constraint->message) diff --git a/Tests/Constraints/UrlValidatorTest.php b/Tests/Constraints/UrlValidatorTest.php index 51fbd8e0a..a362b877f 100644 --- a/Tests/Constraints/UrlValidatorTest.php +++ b/Tests/Constraints/UrlValidatorTest.php @@ -109,6 +109,115 @@ public function testValidRelativeUrlWithNewLine(string $url) ->assertRaised(); } + /** + * Test that protocols: ['*'] allows any protocol + */ + public function testProtocolsWildcardAllowsAnyProtocol() + { + $constraint = new Url(protocols: ['*'], requireTld: false); + + $validUrls = [ + 'http://example.com/', + 'https://example.com/', + 'ftp://example.com', + 'custom://example.com', + 'myapp://example.com/path?query=1', + 'git+ssh://git@github.com/repo.git', + 'file://path/to/file', + 'scheme123://example.com', + 'a://example.com', + ]; + + foreach ($validUrls as $url) { + $this->validator->validate($url, $constraint); + $this->assertNoViolation(); + } + } + + /** + * Test that protocols: ['*'] still validates scheme format according to RFC 3986 + */ + public function testProtocolsWildcardRejectsInvalidSchemes() + { + $constraint = new Url(protocols: ['*'], requireTld: true); + + $invalidUrls = [ + '123://example.com', + '+scheme://example.com', + '-scheme://example.com', + '.scheme://example.com', + 'example.com', + '://example.com', + ]; + + foreach ($invalidUrls as $url) { + $this->setUp(); + $this->validator->validate($url, $constraint); + + $this->buildViolation($constraint->message) + ->setParameter('{{ value }}', '"'.$url.'"') + ->setCode(Url::INVALID_URL_ERROR) + ->assertRaised(); + } + } + + /** + * Test that protocols: ['*'] works with relativeProtocol + */ + public function testProtocolsWildcardWithRelativeProtocol() + { + $constraint = new Url(protocols: ['*'], relativeProtocol: true, requireTld: true); + + $this->validator->validate('custom://example.com', $constraint); + $this->assertNoViolation(); + + $this->validator->validate('//example.com', $constraint); + $this->assertNoViolation(); + } + + /** + * Test that protocols: ['*'] works with requireTld + */ + public function testProtocolsWildcardWithRequireTld() + { + $constraint = new Url(protocols: ['*'], requireTld: true); + + $this->validator->validate('custom://example.com', $constraint); + $this->assertNoViolation(); + + $this->validator->validate('custom://localhost', $constraint); + $this->buildViolation($constraint->tldMessage) + ->setParameter('{{ value }}', '"custom://localhost"') + ->setCode(Url::MISSING_TLD_ERROR) + ->assertRaised(); + } + + /** + * Test that protocols accepts regex patterns + */ + public function testProtocolsSupportsRegexPatterns() + { + $constraint = new Url(protocols: ['https?', 'custom.*'], requireTld: true); + + $validUrls = [ + 'http://example.com/', + 'https://example.com/', + 'custom://example.com', + 'customapp://example.com', + ]; + + foreach ($validUrls as $url) { + $this->validator->validate($url, $constraint); + $this->assertNoViolation(); + } + + $this->validator->validate('ftp://example.com', $constraint); + $this->buildViolation($constraint->message) + ->setParameter('{{ value }}', '"ftp://example.com"') + ->setCode(Url::INVALID_URL_ERROR) + ->assertRaised(); + } + public static function getValidRelativeUrls() { return [ From d47ec23589ff1c977b8792ab473f55f7d25e7890 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 22 Sep 2025 17:36:11 +0200 Subject: [PATCH 44/57] Remove useless comments --- Tests/Constraints/UrlValidatorTest.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Tests/Constraints/UrlValidatorTest.php b/Tests/Constraints/UrlValidatorTest.php index a362b877f..d697bf8ca 100644 --- a/Tests/Constraints/UrlValidatorTest.php +++ b/Tests/Constraints/UrlValidatorTest.php @@ -109,9 +109,6 @@ public function testValidRelativeUrlWithNewLine(string $url) ->assertRaised(); } - /** - * Test that protocols: ['*'] allows any protocol - */ public function testProtocolsWildcardAllowsAnyProtocol() { $constraint = new Url(protocols: ['*'], requireTld: false); @@ -134,9 +131,6 @@ public function testProtocolsWildcardAllowsAnyProtocol() } } - /** - * Test that protocols: ['*'] still validates scheme format according to RFC 3986 - */ public function testProtocolsWildcardRejectsInvalidSchemes() { $constraint = new Url(protocols: ['*'], requireTld: true); @@ -161,9 +155,6 @@ public function testProtocolsWildcardRejectsInvalidSchemes() } } - /** - * Test that protocols: ['*'] works with relativeProtocol - */ public function testProtocolsWildcardWithRelativeProtocol() { $constraint = new Url(protocols: ['*'], relativeProtocol: true, requireTld: true); @@ -175,9 +166,6 @@ public function testProtocolsWildcardWithRelativeProtocol() $this->assertNoViolation(); } - /** - * Test that protocols: ['*'] works with requireTld - */ public function testProtocolsWildcardWithRequireTld() { $constraint = new Url(protocols: ['*'], requireTld: true); @@ -192,9 +180,6 @@ public function testProtocolsWildcardWithRequireTld() ->assertRaised(); } - /** - * Test that protocols accepts regex patterns - */ public function testProtocolsSupportsRegexPatterns() { $constraint = new Url(protocols: ['https?', 'custom.*'], requireTld: true); From d9113988f99fa8be8e3c3363f101cbdd70520921 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 24 Sep 2025 11:22:40 +0200 Subject: [PATCH 45/57] allow protocols to be passed as a string --- Constraints/Url.php | 14 +++++++++----- Tests/Constraints/UrlTest.php | 10 ++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Constraints/Url.php b/Constraints/Url.php index 01d365c6e..08d391e38 100644 --- a/Constraints/Url.php +++ b/Constraints/Url.php @@ -40,16 +40,16 @@ class Url extends Constraint public $normalizer; /** - * @param string[]|null $protocols The protocols considered to be valid for the URL (e.g. http, https, ftp, etc.) (defaults to ['http', 'https']; use ['*'] to allow any protocol or regex patterns like ['.*'] for custom matching) - * @param bool|null $relativeProtocol Whether to accept URL without the protocol (i.e. //example.com) (defaults to false) - * @param string[]|null $groups - * @param bool|null $requireTld Whether to require the URL to include a top-level domain (defaults to false) + * @param string[]|string|null $protocols The protocols considered to be valid for the URL (e.g. http, https, ftp, etc.) (defaults to ['http', 'https']; use '*' to allow any protocol) + * @param bool|null $relativeProtocol Whether to accept URL without the protocol (i.e. //example.com) (defaults to false) + * @param string[]|null $groups + * @param bool|null $requireTld Whether to require the URL to include a top-level domain (defaults to false) */ #[HasNamedArguments] public function __construct( ?array $options = null, ?string $message = null, - ?array $protocols = null, + array|string|null $protocols = null, ?bool $relativeProtocol = null, ?callable $normalizer = null, ?array $groups = null, @@ -67,6 +67,10 @@ public function __construct( trigger_deprecation('symfony/validator', '7.1', 'Not passing a value for the "requireTld" option to the Url constraint is deprecated. Its default value will change to "true".'); } + if (\is_string($protocols)) { + $protocols = (array) $protocols; + } + $this->message = $message ?? $this->message; $this->protocols = $protocols ?? $this->protocols; $this->relativeProtocol = $relativeProtocol ?? $this->relativeProtocol; diff --git a/Tests/Constraints/UrlTest.php b/Tests/Constraints/UrlTest.php index 297b2acc8..cfbb5ca1a 100644 --- a/Tests/Constraints/UrlTest.php +++ b/Tests/Constraints/UrlTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Url; use Symfony\Component\Validator\Exception\InvalidArgumentException; @@ -88,6 +89,15 @@ public function testRequireTldDefaultsToFalse() $this->assertFalse($constraint->requireTld); } + + #[TestWith(['*'])] + #[TestWith(['http'])] + public function testProtocolsAsString(string $protocol) + { + $constraint = new Url(protocols: $protocol, requireTld: true); + + $this->assertSame([$protocol], $constraint->protocols); + } } class UrlDummy From e9787b16903812bad05ddf688ebef28a5fe6b5fc Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 13 Sep 2025 13:18:25 +0200 Subject: [PATCH 46/57] deprecate implicit constraint option names in YAML/XML mapping files --- CHANGELOG.md | 47 ++++++++++++++++++- Mapping/Loader/AbstractLoader.php | 8 ++++ Mapping/Loader/XmlFileLoader.php | 4 +- Mapping/Loader/YamlFileLoader.php | 4 +- Tests/Mapping/Loader/XmlFileLoaderTest.php | 2 + Tests/Mapping/Loader/YamlFileLoaderTest.php | 3 ++ .../constraint-mapping-value-option.xml | 4 ++ .../constraint-mapping-value-option.yml | 3 ++ Tests/Mapping/Loader/constraint-mapping.xml | 23 +++++---- Tests/Mapping/Loader/constraint-mapping.yml | 22 +++++---- 10 files changed, 100 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 535edccd6..b609f3f12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,52 @@ CHANGELOG 7.4 --- + * Deprecate configuring constraint options implicitly with the XML format + + Before: + + ```xml + + + Symfony\Component\Validator\Tests\Fixtures\CallbackClass + callback + + + ``` + + After: + + ```xml + + + + + + ``` + * Deprecate configuring constraint options implicitly with the YAML format + + Before: + + ```yaml + Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: + constraints: + - Callback: validateMeStatic + - Callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback] + ``` + + After: + + ```yaml + Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: + constraints: + - Callback: + callback: validateMeStatic + - Callback: + callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback] + ``` * Add `#[ExtendsValidationFor]` to declare new constraints for a class * Add `ValidatorBuilder::addAttributeMappings()` and `AttributeMetadataPass` to declare compile-time constraint metadata using attributes * Add the `Video` constraint for validating video files @@ -48,7 +94,6 @@ CHANGELOG } } ``` - * Deprecate the `getRequiredOptions()` method of the base `Constraint` class. Use mandatory constructor arguments instead. Before: diff --git a/Mapping/Loader/AbstractLoader.php b/Mapping/Loader/AbstractLoader.php index ebff64fd5..d6b1ab777 100644 --- a/Mapping/Loader/AbstractLoader.php +++ b/Mapping/Loader/AbstractLoader.php @@ -94,10 +94,16 @@ protected function newConstraint(string $name, mixed $options = null): Constrain } if (1 === \count($options) && isset($options['value'])) { + if (\func_num_args() < 3 || !func_get_arg(2)) { + trigger_deprecation('symfony/validator', '7.4', 'Using the "value" option to configure the "%s" constraint is deprecated.', $className); + } + return new $className($options['value']); } if (array_is_list($options)) { + trigger_deprecation('symfony/validator', '7.4', 'Configuring the "%s" without passing its option names is deprecated.', $className); + return new $className($options); } @@ -105,6 +111,8 @@ protected function newConstraint(string $name, mixed $options = null): Constrain return new $className(...$options); } catch (\Error $e) { if (str_starts_with($e->getMessage(), 'Unknown named parameter ')) { + trigger_deprecation('symfony/validator', '7.4', 'Using option names not matching the named arguments of the "%s" constraint is deprecated.', $className); + return new $className($options); } diff --git a/Mapping/Loader/XmlFileLoader.php b/Mapping/Loader/XmlFileLoader.php index 9bc8b449c..25af501d8 100644 --- a/Mapping/Loader/XmlFileLoader.php +++ b/Mapping/Loader/XmlFileLoader.php @@ -80,6 +80,8 @@ protected function parseConstraints(\SimpleXMLElement $nodes): array foreach ($nodes as $node) { if (\count($node) > 0) { if (\count($node->value) > 0) { + trigger_deprecation('symfony/validator', '7.4', 'Using the "value" XML element to configure an option for the "%s" is deprecated. Use the "option" element instead.', (string) $node['name']); + $options = [ 'value' => $this->parseValues($node->value), ]; @@ -100,7 +102,7 @@ protected function parseConstraints(\SimpleXMLElement $nodes): array $options['groups'] = (array) $options['groups']; } - $constraints[] = $this->newConstraint((string) $node['name'], $options); + $constraints[] = $this->newConstraint((string) $node['name'], $options, true); } return $constraints; diff --git a/Mapping/Loader/YamlFileLoader.php b/Mapping/Loader/YamlFileLoader.php index 047fa2194..9c168aff6 100644 --- a/Mapping/Loader/YamlFileLoader.php +++ b/Mapping/Loader/YamlFileLoader.php @@ -87,12 +87,14 @@ protected function parseNodes(array $nodes): array } if (null !== $options && (!\is_array($options) || array_is_list($options))) { + trigger_deprecation('symfony/validator', '7.4', 'Not using a YAML mapping of constraint option names to their values to configure the "%s" constraint is deprecated.', key($childNodes)); + $options = [ 'value' => $options, ]; } - $values[] = $this->newConstraint(key($childNodes), $options); + $values[] = $this->newConstraint(key($childNodes), $options, true); } else { if (\is_array($childNodes)) { $childNodes = $this->parseNodes($childNodes); diff --git a/Tests/Mapping/Loader/XmlFileLoaderTest.php b/Tests/Mapping/Loader/XmlFileLoaderTest.php index 199a10a2a..6490a8b13 100644 --- a/Tests/Mapping/Loader/XmlFileLoaderTest.php +++ b/Tests/Mapping/Loader/XmlFileLoaderTest.php @@ -30,6 +30,7 @@ use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; use Symfony\Component\Validator\Tests\Dummy\DummyGroupProvider; use Symfony\Component\Validator\Tests\Fixtures\Attribute\GroupProviderDto; +use Symfony\Component\Validator\Tests\Fixtures\CallbackClass; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithRequiredArgument; @@ -104,6 +105,7 @@ public function testLoadClassMetadataValueOption() $loader->loadClassMetadata($metadata); $expected = new ClassMetadata(Entity::class); + $expected->addConstraint(new Callback([CallbackClass::class, 'callback'])); $expected->addPropertyConstraint('firstName', new Type(type: 'string')); $expected->addPropertyConstraint('firstName', new Choice(choices: ['A', 'B'])); diff --git a/Tests/Mapping/Loader/YamlFileLoaderTest.php b/Tests/Mapping/Loader/YamlFileLoaderTest.php index e5f3db9f7..8b2077931 100644 --- a/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -27,6 +27,7 @@ use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; use Symfony\Component\Validator\Tests\Dummy\DummyGroupProvider; use Symfony\Component\Validator\Tests\Fixtures\Attribute\GroupProviderDto; +use Symfony\Component\Validator\Tests\Fixtures\CallbackClass; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithRequiredArgument; @@ -146,6 +147,8 @@ public function testLoadClassMetadataValueOption() $loader->loadClassMetadata($metadata); $expected = new ClassMetadata(Entity::class); + $expected->addConstraint(new Callback('validateMeStatic')); + $expected->addConstraint(new Callback([CallbackClass::class, 'callback'])); $expected->addPropertyConstraint('firstName', new Type(type: 'string')); $expected->addPropertyConstraint('firstName', new Choice(choices: ['A', 'B'])); diff --git a/Tests/Mapping/Loader/constraint-mapping-value-option.xml b/Tests/Mapping/Loader/constraint-mapping-value-option.xml index d0fea931d..f7f5bdb55 100644 --- a/Tests/Mapping/Loader/constraint-mapping-value-option.xml +++ b/Tests/Mapping/Loader/constraint-mapping-value-option.xml @@ -7,6 +7,10 @@ Symfony\Component\Validator\Tests\Fixtures\ + + Symfony\Component\Validator\Tests\Fixtures\CallbackClass + callback + diff --git a/Tests/Mapping/Loader/constraint-mapping-value-option.yml b/Tests/Mapping/Loader/constraint-mapping-value-option.yml index 149497ad1..093696c8f 100644 --- a/Tests/Mapping/Loader/constraint-mapping-value-option.yml +++ b/Tests/Mapping/Loader/constraint-mapping-value-option.yml @@ -2,6 +2,9 @@ namespaces: custom: Symfony\Component\Validator\Tests\Fixtures\ Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: + constraints: + - Callback: validateMeStatic + - Callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback] properties: firstName: # Constraint with single value diff --git a/Tests/Mapping/Loader/constraint-mapping.xml b/Tests/Mapping/Loader/constraint-mapping.xml index 3666d3a75..588833208 100644 --- a/Tests/Mapping/Loader/constraint-mapping.xml +++ b/Tests/Mapping/Loader/constraint-mapping.xml @@ -27,8 +27,10 @@ validateMeStatic - Symfony\Component\Validator\Tests\Fixtures\CallbackClass - callback + @@ -43,8 +45,10 @@ - foo - bar + @@ -61,11 +65,12 @@ - - - - - + diff --git a/Tests/Mapping/Loader/constraint-mapping.yml b/Tests/Mapping/Loader/constraint-mapping.yml index 06b0bd44f..e31a64189 100644 --- a/Tests/Mapping/Loader/constraint-mapping.yml +++ b/Tests/Mapping/Loader/constraint-mapping.yml @@ -12,15 +12,20 @@ Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: # Custom constraint with namespaces prefix - "custom:ConstraintB": ~ # Callbacks - - Callback: validateMe - - Callback: validateMeStatic - - Callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback] + - Callback: + callback: validateMe + - Callback: + callback: validateMeStatic + - Callback: + callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback] # Constraint with named arguments support without value - Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithoutValueWithNamedArguments: ~ # Constraint with named arguments support with scalar value - - Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithNamedArguments: foo + - Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithNamedArguments: + choices: foo # Constraint with named arguments support with array value - - Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithNamedArguments: [foo, bar] + - Symfony\Component\Validator\Tests\Mapping\Loader\Fixtures\ConstraintWithNamedArguments: + choices: [foo, bar] properties: firstName: @@ -28,9 +33,10 @@ Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: - NotNull: ~ # Constraint with child constraints - All: - - NotNull: ~ - - Range: - min: 3 + constraints: + - NotNull: ~ + - Range: + min: 3 # Option with child constraints - All: constraints: From 6d8d4a9e9003e111c73081d4fab1f4bfbee33016 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 25 Sep 2025 16:04:40 +0200 Subject: [PATCH 47/57] deprecate passing an associative array to GroupSequence --- CHANGELOG.md | 13 +++++++++++++ Constraints/GroupSequence.php | 4 ++++ Tests/Constraints/GroupSequenceTest.php | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b609f3f12..b0d349a68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ CHANGELOG 7.4 --- + * Deprecate handling associative arrays in `GroupSequence` + + Before: + + ```php + $groupSequence = GroupSequence(['value' => ['group 1', 'group 2']]); + ``` + + After: + + ```php + $groupSequence = GroupSequence(['group 1', 'group 2']); + ``` * Deprecate configuring constraint options implicitly with the XML format Before: diff --git a/Constraints/GroupSequence.php b/Constraints/GroupSequence.php index e3e4f47f9..440c29003 100644 --- a/Constraints/GroupSequence.php +++ b/Constraints/GroupSequence.php @@ -80,6 +80,10 @@ class GroupSequence #[HasNamedArguments] public function __construct(array $groups) { + if (!array_is_list($groups)) { + trigger_deprecation('symfony/validator', '7.4', 'Support for passing an array of options to "%s()" is deprecated.', __METHOD__); + } + $this->groups = $groups['value'] ?? $groups; } } diff --git a/Tests/Constraints/GroupSequenceTest.php b/Tests/Constraints/GroupSequenceTest.php index 7803a73cc..f27a95fd0 100644 --- a/Tests/Constraints/GroupSequenceTest.php +++ b/Tests/Constraints/GroupSequenceTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\GroupSequence; @@ -26,8 +28,12 @@ public function testCreate() $this->assertSame(['Group 1', 'Group 2'], $sequence->groups); } + #[Group('legacy')] + #[IgnoreDeprecations] public function testCreateDoctrineStyle() { + $this->expectUserDeprecationMessage('Since symfony/validator 7.4: Support for passing an array of options to "Symfony\Component\Validator\Constraints\GroupSequence::__construct()" is deprecated.'); + $sequence = new GroupSequence(['value' => ['Group 1', 'Group 2']]); $this->assertSame(['Group 1', 'Group 2'], $sequence->groups); From 11d1b43ad163f8c2364cd30d29d5a18eb048af12 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 26 Sep 2025 10:24:02 +0200 Subject: [PATCH 48/57] remove support for passing associative arrays to GroupSequence --- CHANGELOG.md | 13 +++++++++++++ Constraints/GroupSequence.php | 6 +----- Tests/Constraints/GroupSequenceTest.php | 13 ------------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1b4e3286..cb614544e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ CHANGELOG 8.0 --- + * Remove support for passing associative arrays to `GroupSequence` + + Before: + + ```php + $groupSequence = GroupSequence(['value' => ['group 1', 'group 2']]); + ``` + + After: + + ```php + $groupSequence = GroupSequence(['group 1', 'group 2']); + ``` * Change the default value of the `$requireTld` option of the `Url` constraint to `true` * Add method `getGroupProvider()` to `ClassMetadataInterface` * Replace `__sleep/wakeup()` by `__(un)serialize()` on `GenericMetadata` implementations diff --git a/Constraints/GroupSequence.php b/Constraints/GroupSequence.php index e70901ca0..ec6620e1c 100644 --- a/Constraints/GroupSequence.php +++ b/Constraints/GroupSequence.php @@ -77,10 +77,6 @@ class GroupSequence */ public function __construct(array $groups) { - if (!array_is_list($groups)) { - trigger_deprecation('symfony/validator', '7.4', 'Support for passing an array of options to "%s()" is deprecated.', __METHOD__); - } - - $this->groups = $groups['value'] ?? $groups; + $this->groups = $groups; } } diff --git a/Tests/Constraints/GroupSequenceTest.php b/Tests/Constraints/GroupSequenceTest.php index f27a95fd0..5ee529a00 100644 --- a/Tests/Constraints/GroupSequenceTest.php +++ b/Tests/Constraints/GroupSequenceTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\GroupSequence; @@ -27,15 +25,4 @@ public function testCreate() $this->assertSame(['Group 1', 'Group 2'], $sequence->groups); } - - #[Group('legacy')] - #[IgnoreDeprecations] - public function testCreateDoctrineStyle() - { - $this->expectUserDeprecationMessage('Since symfony/validator 7.4: Support for passing an array of options to "Symfony\Component\Validator\Constraints\GroupSequence::__construct()" is deprecated.'); - - $sequence = new GroupSequence(['value' => ['Group 1', 'Group 2']]); - - $this->assertSame(['Group 1', 'Group 2'], $sequence->groups); - } } From 382e0c75a3372d3ba47cc13fb1f0b69beb41d901 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 26 Sep 2025 10:38:31 +0200 Subject: [PATCH 49/57] remove support for implicit constraint option names in YAML/XML mapping files --- CHANGELOG.md | 46 +++++++++++++++++++ Mapping/Loader/AbstractLoader.php | 14 ------ Mapping/Loader/XmlFileLoader.php | 8 +--- Mapping/Loader/YamlFileLoader.php | 8 ---- Tests/Mapping/Loader/XmlFileLoaderTest.php | 21 --------- Tests/Mapping/Loader/YamlFileLoaderTest.php | 21 --------- .../constraint-mapping-value-option.xml | 31 ------------- .../constraint-mapping-value-option.yml | 13 ------ 8 files changed, 47 insertions(+), 115 deletions(-) delete mode 100644 Tests/Mapping/Loader/constraint-mapping-value-option.xml delete mode 100644 Tests/Mapping/Loader/constraint-mapping-value-option.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index cb614544e..9af86a49d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,52 @@ CHANGELOG 8.0 --- + * Remove support for configuring constraint options implicitly with the XML format + + Before: + + ```xml + + + Symfony\Component\Validator\Tests\Fixtures\CallbackClass + callback + + + ``` + + After: + + ```xml + + + + + + ``` + * Remove support for configuring constraint options implicitly with the YAML format + + Before: + + ```yaml + Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: + constraints: + - Callback: validateMeStatic + - Callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback] + ``` + + After: + + ```yaml + Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: + constraints: + - Callback: + callback: validateMeStatic + - Callback: + callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback] + ``` * Remove support for passing associative arrays to `GroupSequence` Before: diff --git a/Mapping/Loader/AbstractLoader.php b/Mapping/Loader/AbstractLoader.php index 105487692..e33ca7f97 100644 --- a/Mapping/Loader/AbstractLoader.php +++ b/Mapping/Loader/AbstractLoader.php @@ -86,20 +86,6 @@ protected function newConstraint(string $name, mixed $options = null): Constrain return new $className($options); } - if (1 === \count($options) && isset($options['value'])) { - if (\func_num_args() < 3 || !func_get_arg(2)) { - trigger_deprecation('symfony/validator', '7.4', 'Using the "value" option to configure the "%s" constraint is deprecated.', $className); - } - - return new $className($options['value']); - } - - if (array_is_list($options)) { - trigger_deprecation('symfony/validator', '7.4', 'Configuring the "%s" without passing its option names is deprecated.', $className); - - return new $className($options); - } - return new $className(...$options); } } diff --git a/Mapping/Loader/XmlFileLoader.php b/Mapping/Loader/XmlFileLoader.php index 25af501d8..e656edc8e 100644 --- a/Mapping/Loader/XmlFileLoader.php +++ b/Mapping/Loader/XmlFileLoader.php @@ -79,13 +79,7 @@ protected function parseConstraints(\SimpleXMLElement $nodes): array foreach ($nodes as $node) { if (\count($node) > 0) { - if (\count($node->value) > 0) { - trigger_deprecation('symfony/validator', '7.4', 'Using the "value" XML element to configure an option for the "%s" is deprecated. Use the "option" element instead.', (string) $node['name']); - - $options = [ - 'value' => $this->parseValues($node->value), - ]; - } elseif (\count($node->constraint) > 0) { + if (\count($node->constraint) > 0) { $options = $this->parseConstraints($node->constraint); } elseif (\count($node->option) > 0) { $options = $this->parseOptions($node->option); diff --git a/Mapping/Loader/YamlFileLoader.php b/Mapping/Loader/YamlFileLoader.php index 9c168aff6..ef689cac3 100644 --- a/Mapping/Loader/YamlFileLoader.php +++ b/Mapping/Loader/YamlFileLoader.php @@ -86,14 +86,6 @@ protected function parseNodes(array $nodes): array $options = $this->parseNodes($options); } - if (null !== $options && (!\is_array($options) || array_is_list($options))) { - trigger_deprecation('symfony/validator', '7.4', 'Not using a YAML mapping of constraint option names to their values to configure the "%s" constraint is deprecated.', key($childNodes)); - - $options = [ - 'value' => $options, - ]; - } - $values[] = $this->newConstraint(key($childNodes), $options, true); } else { if (\is_array($childNodes)) { diff --git a/Tests/Mapping/Loader/XmlFileLoaderTest.php b/Tests/Mapping/Loader/XmlFileLoaderTest.php index 9320f0b88..162603b3a 100644 --- a/Tests/Mapping/Loader/XmlFileLoaderTest.php +++ b/Tests/Mapping/Loader/XmlFileLoaderTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Mapping\Loader; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Callback; @@ -23,13 +21,11 @@ use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Regex; use Symfony\Component\Validator\Constraints\Traverse; -use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; use Symfony\Component\Validator\Tests\Dummy\DummyGroupProvider; use Symfony\Component\Validator\Tests\Fixtures\Attribute\GroupProviderDto; -use Symfony\Component\Validator\Tests\Fixtures\CallbackClass; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithRequiredArgument; @@ -93,23 +89,6 @@ public function testLoadClassMetadata() $this->assertEquals($expected, $metadata); } - #[IgnoreDeprecations] - #[Group('legacy')] - public function testLoadClassMetadataValueOption() - { - $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-value-option.xml'); - $metadata = new ClassMetadata(Entity::class); - - $loader->loadClassMetadata($metadata); - - $expected = new ClassMetadata(Entity::class); - $expected->addConstraint(new Callback([CallbackClass::class, 'callback'])); - $expected->addPropertyConstraint('firstName', new Type(type: 'string')); - $expected->addPropertyConstraint('firstName', new Choice(choices: ['A', 'B'])); - - $this->assertEquals($expected, $metadata); - } - public function testLoadClassMetadataWithNonStrings() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-non-strings.xml'); diff --git a/Tests/Mapping/Loader/YamlFileLoaderTest.php b/Tests/Mapping/Loader/YamlFileLoaderTest.php index d7ad197ff..e076e814a 100644 --- a/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -12,8 +12,6 @@ namespace Symfony\Component\Validator\Tests\Mapping\Loader; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Callback; @@ -26,7 +24,6 @@ use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; use Symfony\Component\Validator\Tests\Dummy\DummyGroupProvider; use Symfony\Component\Validator\Tests\Fixtures\Attribute\GroupProviderDto; -use Symfony\Component\Validator\Tests\Fixtures\CallbackClass; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithRequiredArgument; @@ -135,24 +132,6 @@ public function testLoadClassMetadata() $this->assertEquals($expected, $metadata); } - #[IgnoreDeprecations] - #[Group('legacy')] - public function testLoadClassMetadataValueOption() - { - $loader = new YamlFileLoader(__DIR__.'/constraint-mapping-value-option.yml'); - $metadata = new ClassMetadata(Entity::class); - - $loader->loadClassMetadata($metadata); - - $expected = new ClassMetadata(Entity::class); - $expected->addConstraint(new Callback('validateMeStatic')); - $expected->addConstraint(new Callback([CallbackClass::class, 'callback'])); - $expected->addPropertyConstraint('firstName', new Type(type: 'string')); - $expected->addPropertyConstraint('firstName', new Choice(choices: ['A', 'B'])); - - $this->assertEquals($expected, $metadata); - } - public function testLoadClassMetadataWithConstants() { $loader = new YamlFileLoader(__DIR__.'/mapping-with-constants.yml'); diff --git a/Tests/Mapping/Loader/constraint-mapping-value-option.xml b/Tests/Mapping/Loader/constraint-mapping-value-option.xml deleted file mode 100644 index f7f5bdb55..000000000 --- a/Tests/Mapping/Loader/constraint-mapping-value-option.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - Symfony\Component\Validator\Tests\Fixtures\ - - - - Symfony\Component\Validator\Tests\Fixtures\CallbackClass - callback - - - - - - - - string - - - - A - B - - - - - - diff --git a/Tests/Mapping/Loader/constraint-mapping-value-option.yml b/Tests/Mapping/Loader/constraint-mapping-value-option.yml deleted file mode 100644 index 093696c8f..000000000 --- a/Tests/Mapping/Loader/constraint-mapping-value-option.yml +++ /dev/null @@ -1,13 +0,0 @@ -namespaces: - custom: Symfony\Component\Validator\Tests\Fixtures\ - -Symfony\Component\Validator\Tests\Fixtures\NestedAttribute\Entity: - constraints: - - Callback: validateMeStatic - - Callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback] - properties: - firstName: - # Constraint with single value - - Type: string - # Constraint with multiple values - - Choice: [A, B] From 620d6a6af3b7abd6dc655b4f0eef2f177586adeb Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 26 Sep 2025 11:25:22 +0200 Subject: [PATCH 50/57] clean up the XML schema definition --- Mapping/Loader/XmlFileLoader.php | 2 +- Mapping/Loader/YamlFileLoader.php | 2 +- .../schema/dic/constraint-mapping/constraint-mapping-1.0.xsd | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Mapping/Loader/XmlFileLoader.php b/Mapping/Loader/XmlFileLoader.php index e656edc8e..9ecd86827 100644 --- a/Mapping/Loader/XmlFileLoader.php +++ b/Mapping/Loader/XmlFileLoader.php @@ -96,7 +96,7 @@ protected function parseConstraints(\SimpleXMLElement $nodes): array $options['groups'] = (array) $options['groups']; } - $constraints[] = $this->newConstraint((string) $node['name'], $options, true); + $constraints[] = $this->newConstraint((string) $node['name'], $options); } return $constraints; diff --git a/Mapping/Loader/YamlFileLoader.php b/Mapping/Loader/YamlFileLoader.php index ef689cac3..aeec2588b 100644 --- a/Mapping/Loader/YamlFileLoader.php +++ b/Mapping/Loader/YamlFileLoader.php @@ -86,7 +86,7 @@ protected function parseNodes(array $nodes): array $options = $this->parseNodes($options); } - $values[] = $this->newConstraint(key($childNodes), $options, true); + $values[] = $this->newConstraint(key($childNodes), $options); } else { if (\is_array($childNodes)) { $childNodes = $this->parseNodes($childNodes); diff --git a/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd b/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd index a744e50b9..b8d2416ba 100644 --- a/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd +++ b/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd @@ -116,14 +116,12 @@ Contains a constraint definition. The name of the constraint should be given in the "name" option. - May contain a single value, multiple "constraint" elements, - multiple "value" elements or multiple "option" elements. + May contain multiple "constraint" elements or multiple "option" elements. ]]> - From 3ca4a1b054c589470871d90fef40f90fdbb3a269 Mon Sep 17 00:00:00 2001 From: Vincent QUATREVIEUX Date: Wed, 1 Oct 2025 10:36:54 +0200 Subject: [PATCH 51/57] [Validator] bad value on AbstractComparison constructor using array parameter --- Constraints/AbstractComparison.php | 1 + Tests/Constraints/AbstractComparisonTest.php | 30 ++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 Tests/Constraints/AbstractComparisonTest.php diff --git a/Constraints/AbstractComparison.php b/Constraints/AbstractComparison.php index 586a23ef4..786d86803 100644 --- a/Constraints/AbstractComparison.php +++ b/Constraints/AbstractComparison.php @@ -36,6 +36,7 @@ public function __construct(mixed $value = null, ?string $propertyPath = null, ? trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($value, $options ?? []); + $value = null; } elseif (null !== $value) { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); diff --git a/Tests/Constraints/AbstractComparisonTest.php b/Tests/Constraints/AbstractComparisonTest.php new file mode 100644 index 000000000..ef65f961e --- /dev/null +++ b/Tests/Constraints/AbstractComparisonTest.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Constraints; + +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Validator\Constraints\AbstractComparison; + +class AbstractComparisonTest extends TestCase +{ + #[IgnoreDeprecations] + #[Group('legacy')] + public function testConstructorWithArrayOption() + { + $comparison = new class(['value' => 42, 'message' => 'my error']) extends AbstractComparison {}; + + $this->assertSame(42, $comparison->value); + $this->assertSame('my error', $comparison->message); + } +} From aa1ec6c14080be47a715ae2476ae1e8935e86368 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 1 Oct 2025 08:25:21 +0200 Subject: [PATCH 52/57] fix handling Doctrine-style options handling --- Constraints/Callback.php | 1 + Constraints/CssColor.php | 1 + Constraints/DateTime.php | 1 + Constraints/Timezone.php | 1 + Tests/Constraints/CallbackTest.php | 29 ++++++++++++++++++++ Tests/Constraints/CssColorTest.php | 11 ++++++++ Tests/Constraints/DateTimeTest.php | 11 ++++++++ Tests/Constraints/DivisibleByTest.php | 11 ++++++++ Tests/Constraints/EqualToTest.php | 11 ++++++++ Tests/Constraints/GreaterThanOrEqualTest.php | 11 ++++++++ Tests/Constraints/GreaterThanTest.php | 11 ++++++++ Tests/Constraints/IdenticalToTest.php | 11 ++++++++ Tests/Constraints/LessThanOrEqualTest.php | 11 ++++++++ Tests/Constraints/LessThanTest.php | 11 ++++++++ Tests/Constraints/NotEqualToTest.php | 11 ++++++++ Tests/Constraints/NotIdenticalToTest.php | 11 ++++++++ Tests/Constraints/TimezoneTest.php | 11 ++++++++ 17 files changed, 165 insertions(+) create mode 100644 Tests/Constraints/CallbackTest.php diff --git a/Constraints/Callback.php b/Constraints/Callback.php index f38aa9899..326125a45 100644 --- a/Constraints/Callback.php +++ b/Constraints/Callback.php @@ -49,6 +49,7 @@ public function __construct(array|string|callable|null $callback = null, ?array trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($callback, $options ?? []); + $callback = null; } parent::__construct($options, $groups, $payload); diff --git a/Constraints/CssColor.php b/Constraints/CssColor.php index 0e87e20db..f73d2941b 100644 --- a/Constraints/CssColor.php +++ b/Constraints/CssColor.php @@ -77,6 +77,7 @@ public function __construct(array|string $formats = [], ?string $message = null, trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($formats, $options ?? []); + $formats = null; } elseif (\is_array($formats)) { if ([] === array_intersect(self::$validationModes, $formats)) { throw new InvalidArgumentException(\sprintf('The "formats" parameter value is not valid. It must contain one or more of the following values: "%s".', $validationModesAsString)); diff --git a/Constraints/DateTime.php b/Constraints/DateTime.php index f9e94f0c2..63c8bda90 100644 --- a/Constraints/DateTime.php +++ b/Constraints/DateTime.php @@ -48,6 +48,7 @@ public function __construct(string|array|null $format = null, ?string $message = trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($format, $options ?? []); + $format = null; } elseif (null !== $format) { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); diff --git a/Constraints/Timezone.php b/Constraints/Timezone.php index 7c8297652..0a05085a1 100644 --- a/Constraints/Timezone.php +++ b/Constraints/Timezone.php @@ -63,6 +63,7 @@ public function __construct( trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($zone, $options ?? []); + $zone = null; } elseif (null !== $zone) { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); diff --git a/Tests/Constraints/CallbackTest.php b/Tests/Constraints/CallbackTest.php new file mode 100644 index 000000000..d7c758c17 --- /dev/null +++ b/Tests/Constraints/CallbackTest.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Constraints; + +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Validator\Constraints\Callback; + +class CallbackTest extends TestCase +{ + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new Callback(['callback' => 'validate']); + + $this->assertSame('validate', $constraint->callback); + } +} diff --git a/Tests/Constraints/CssColorTest.php b/Tests/Constraints/CssColorTest.php index ebd657e71..72479363c 100644 --- a/Tests/Constraints/CssColorTest.php +++ b/Tests/Constraints/CssColorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\CssColor; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -60,6 +62,15 @@ public function testMissingPatternDoctrineStyle() CssColor::HSLA, ], $constraint->formats); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new CssColor(['formats' => CssColor::RGB]); + + $this->assertSame(CssColor::RGB, $constraint->formats); + } } class CssColorDummy diff --git a/Tests/Constraints/DateTimeTest.php b/Tests/Constraints/DateTimeTest.php index d8891fe5b..d144fc34a 100644 --- a/Tests/Constraints/DateTimeTest.php +++ b/Tests/Constraints/DateTimeTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\DateTime; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -37,6 +39,15 @@ public function testAttributes() self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new DateTime(['format' => 'm/d/Y']); + + $this->assertSame('m/d/Y', $constraint->format); + } } class DateTimeDummy diff --git a/Tests/Constraints/DivisibleByTest.php b/Tests/Constraints/DivisibleByTest.php index 7c9275ea9..9c0f1f9fa 100644 --- a/Tests/Constraints/DivisibleByTest.php +++ b/Tests/Constraints/DivisibleByTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\DivisibleBy; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -39,6 +41,15 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new DivisibleBy(['value' => 5]); + + $this->assertSame(5, $constraint->value); + } } class DivisibleByDummy diff --git a/Tests/Constraints/EqualToTest.php b/Tests/Constraints/EqualToTest.php index ae0f97cfd..9d7cf1dfc 100644 --- a/Tests/Constraints/EqualToTest.php +++ b/Tests/Constraints/EqualToTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\EqualTo; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -39,6 +41,15 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new EqualTo(['value' => 5]); + + $this->assertSame(5, $constraint->value); + } } class EqualToDummy diff --git a/Tests/Constraints/GreaterThanOrEqualTest.php b/Tests/Constraints/GreaterThanOrEqualTest.php index b73a32885..96ebe737d 100644 --- a/Tests/Constraints/GreaterThanOrEqualTest.php +++ b/Tests/Constraints/GreaterThanOrEqualTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\GreaterThanOrEqual; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -39,6 +41,15 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new GreaterThanOrEqual(['value' => 5]); + + $this->assertSame(5, $constraint->value); + } } class GreaterThanOrEqualDummy diff --git a/Tests/Constraints/GreaterThanTest.php b/Tests/Constraints/GreaterThanTest.php index ea962837a..07c0fe0e7 100644 --- a/Tests/Constraints/GreaterThanTest.php +++ b/Tests/Constraints/GreaterThanTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\GreaterThan; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -39,6 +41,15 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new GreaterThan(['value' => 5]); + + $this->assertSame(5, $constraint->value); + } } class GreaterThanDummy diff --git a/Tests/Constraints/IdenticalToTest.php b/Tests/Constraints/IdenticalToTest.php index da91a174b..589fab43b 100644 --- a/Tests/Constraints/IdenticalToTest.php +++ b/Tests/Constraints/IdenticalToTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\IdenticalTo; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -39,6 +41,15 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new IdenticalTo(['value' => 5]); + + $this->assertSame(5, $constraint->value); + } } class IdenticalToDummy diff --git a/Tests/Constraints/LessThanOrEqualTest.php b/Tests/Constraints/LessThanOrEqualTest.php index 1784eaff9..1659fd1ec 100644 --- a/Tests/Constraints/LessThanOrEqualTest.php +++ b/Tests/Constraints/LessThanOrEqualTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\LessThanOrEqual; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -39,6 +41,15 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new LessThanOrEqual(['value' => 5]); + + $this->assertSame(5, $constraint->value); + } } class LessThanOrEqualDummy diff --git a/Tests/Constraints/LessThanTest.php b/Tests/Constraints/LessThanTest.php index 1d2429d2a..effffba71 100644 --- a/Tests/Constraints/LessThanTest.php +++ b/Tests/Constraints/LessThanTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\LessThan; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -39,6 +41,15 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new LessThan(['value' => 5]); + + $this->assertSame(5, $constraint->value); + } } class LessThanDummy diff --git a/Tests/Constraints/NotEqualToTest.php b/Tests/Constraints/NotEqualToTest.php index 970c67ce5..941348e8e 100644 --- a/Tests/Constraints/NotEqualToTest.php +++ b/Tests/Constraints/NotEqualToTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\NotEqualTo; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -39,6 +41,15 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new NotEqualTo(['value' => 5]); + + $this->assertSame(5, $constraint->value); + } } class NotEqualToDummy diff --git a/Tests/Constraints/NotIdenticalToTest.php b/Tests/Constraints/NotIdenticalToTest.php index 96f13341b..e9714f9c9 100644 --- a/Tests/Constraints/NotIdenticalToTest.php +++ b/Tests/Constraints/NotIdenticalToTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\NotIdenticalTo; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -39,6 +41,15 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new NotIdenticalTo(['value' => 5]); + + $this->assertSame(5, $constraint->value); + } } class NotIdenticalToDummy diff --git a/Tests/Constraints/TimezoneTest.php b/Tests/Constraints/TimezoneTest.php index 5def3e361..2b4f1ad2a 100644 --- a/Tests/Constraints/TimezoneTest.php +++ b/Tests/Constraints/TimezoneTest.php @@ -12,6 +12,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Timezone; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -83,6 +85,15 @@ public function testAttributes() self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } + + #[IgnoreDeprecations] + #[Group('legacy')] + public function testDoctrineStyle() + { + $constraint = new Timezone(['zone' => \DateTimeZone::ALL]); + + $this->assertSame(\DateTimeZone::ALL, $constraint->zone); + } } class TimezoneDummy From 5da8c8fe7cfc091709364353e632758cfca0d0e5 Mon Sep 17 00:00:00 2001 From: benkarrer-lab Date: Thu, 2 Oct 2025 18:42:37 +0200 Subject: [PATCH 53/57] =?UTF-8?q?Validator:=20finalize=20pt=20translations?= =?UTF-8?q?=20for=20video/image=20(ids=20122=E2=80=93142);=20set=20state?= =?UTF-8?q?=3Dtranslated;=20unify=20wording?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Resources/translations/validators.pt.xlf | 42 ++++++++++++------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Resources/translations/validators.pt.xlf b/Resources/translations/validators.pt.xlf index 62c3c5fc2..6f628c740 100644 --- a/Resources/translations/validators.pt.xlf +++ b/Resources/translations/validators.pt.xlf @@ -472,87 +472,87 @@ This file is not a valid video. - Este ficheiro não é um vídeo válido. + Este ficheiro não é um vídeo válido. The size of the video could not be detected. - Não foi possível detetar o tamanho do vídeo. + Não foi possível detetar o tamanho do vídeo. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - A largura do vídeo é demasiado grande ({{ width }}px). A largura máxima permitida é {{ max_width }}px. + A largura do vídeo é demasiado grande ({{ width }}px). A largura máxima permitida é {{ max_width }}px. The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - A largura do vídeo é muito pequena ({{ width }}px). A largura mínima esperada é {{ min_width }}px. + A largura do vídeo é demasiado pequena ({{ width }}px). A largura mínima esperada é {{ min_width }}px. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - A altura do vídeo é demasiado grande ({{ height }}px). A altura máxima permitida é {{ max_height }}px. + A altura do vídeo é demasiado grande ({{ height }}px). A altura máxima permitida é {{ max_height }}px. The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - A altura do vídeo é muito pequena ({{ height }}px). A altura mínima esperada é {{ min_height }}px. + A altura do vídeo é demasiado pequena ({{ height }}px). A altura mínima esperada é {{ min_height }}px. The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - O vídeo tem poucos píxeis ({{ pixels }}). A quantidade mínima esperada é {{ min_pixels }}. + O vídeo tem poucos píxeis ({{ pixels }}). A quantidade mínima esperada é {{ min_pixels }}. The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - O vídeo tem píxeis a mais ({{ pixels }}). A quantidade máxima esperada é {{ max_pixels }}. + O vídeo tem píxeis a mais ({{ pixels }}). A quantidade máxima esperada é {{ max_pixels }}. The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - A proporção do vídeo é muito grande ({{ ratio }}). A proporção máxima permitida é {{ max_ratio }}. + A proporção do vídeo é demasiado grande ({{ ratio }}). A proporção máxima permitida é {{ max_ratio }}. The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - A proporção do vídeo é muito pequena ({{ ratio }}). A proporção mínima esperada é {{ min_ratio }}. + A proporção do vídeo é demasiado pequena ({{ ratio }}). A proporção mínima esperada é {{ min_ratio }}. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - O vídeo é quadrado ({{ width }}x{{ height }}px). Vídeos quadrados não são permitidos. + O vídeo é quadrado ({{ width }}x{{ height }}px). Vídeos quadrados não são permitidos. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - O vídeo está em modo paisagem ({{ width }}x{{ height }} px). Vídeos em paisagem não são permitidos. + O vídeo está em orientação horizontal ({{ width }}x{{ height }}px). Vídeos em orientação horizontal não são permitidos. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - O vídeo está em orientação vertical ({{ width }}x{{ height }}px). Vídeos em orientação vertical não são permitidos. + O vídeo está em orientação vertical ({{ width }}x{{ height }}px). Vídeos em orientação vertical não são permitidos. The video file is corrupted. - O ficheiro de vídeo está corrompido. + O ficheiro de vídeo está corrompido. The video contains multiple streams. Only one stream is allowed. - O vídeo contém vários fluxos. É permitido apenas um fluxo. + O vídeo contém vários fluxos. Apenas é permitido um fluxo. Unsupported video codec "{{ codec }}". - Codec de vídeo não suportado «{{ codec }}». + Codec de vídeo não suportado «{{ codec }}». Unsupported video container "{{ container }}". - Contentor de vídeo não suportado "{{ container }}". + Contentor de vídeo não suportado «{{ container }}». The image file is corrupted. - O ficheiro de imagem está corrompido. + O ficheiro de imagem está corrompido. The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - A imagem tem píxeis a menos ({{ pixels }}). A quantidade mínima esperada é {{ min_pixels }}. + A imagem tem píxeis a menos ({{ pixels }}). A quantidade mínima esperada é {{ min_pixels }}. The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - A imagem tem píxeis a mais ({{ pixels }}). A quantidade máxima esperada é {{ max_pixels }}. + A imagem tem píxeis a mais ({{ pixels }}). A quantidade máxima esperada é {{ max_pixels }}. This filename does not match the expected charset. - Este nome de ficheiro não corresponde ao conjunto de caracteres esperado. + Este nome de ficheiro não corresponde ao conjunto de caracteres esperado. From 49f358b0636bd1370780860b705d883297eb082e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 6 Oct 2025 18:45:53 +0200 Subject: [PATCH 54/57] remove legacy tests --- Tests/Constraints/AbstractComparisonTest.php | 30 -------------------- Tests/Constraints/CallbackTest.php | 29 ------------------- Tests/Constraints/CssColorTest.php | 11 ------- Tests/Constraints/DateTimeTest.php | 11 ------- Tests/Constraints/DivisibleByTest.php | 11 ------- Tests/Constraints/EqualToTest.php | 11 ------- Tests/Constraints/GreaterThanOrEqualTest.php | 11 ------- Tests/Constraints/GreaterThanTest.php | 11 ------- Tests/Constraints/IdenticalToTest.php | 11 ------- Tests/Constraints/LessThanOrEqualTest.php | 11 ------- Tests/Constraints/LessThanTest.php | 11 ------- Tests/Constraints/NotEqualToTest.php | 11 ------- Tests/Constraints/NotIdenticalToTest.php | 11 ------- Tests/Constraints/TimezoneTest.php | 11 ------- 14 files changed, 191 deletions(-) delete mode 100644 Tests/Constraints/AbstractComparisonTest.php delete mode 100644 Tests/Constraints/CallbackTest.php diff --git a/Tests/Constraints/AbstractComparisonTest.php b/Tests/Constraints/AbstractComparisonTest.php deleted file mode 100644 index ef65f961e..000000000 --- a/Tests/Constraints/AbstractComparisonTest.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Constraints; - -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Validator\Constraints\AbstractComparison; - -class AbstractComparisonTest extends TestCase -{ - #[IgnoreDeprecations] - #[Group('legacy')] - public function testConstructorWithArrayOption() - { - $comparison = new class(['value' => 42, 'message' => 'my error']) extends AbstractComparison {}; - - $this->assertSame(42, $comparison->value); - $this->assertSame('my error', $comparison->message); - } -} diff --git a/Tests/Constraints/CallbackTest.php b/Tests/Constraints/CallbackTest.php deleted file mode 100644 index d7c758c17..000000000 --- a/Tests/Constraints/CallbackTest.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Constraints; - -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Validator\Constraints\Callback; - -class CallbackTest extends TestCase -{ - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new Callback(['callback' => 'validate']); - - $this->assertSame('validate', $constraint->callback); - } -} diff --git a/Tests/Constraints/CssColorTest.php b/Tests/Constraints/CssColorTest.php index 72479363c..ebd657e71 100644 --- a/Tests/Constraints/CssColorTest.php +++ b/Tests/Constraints/CssColorTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\CssColor; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -62,15 +60,6 @@ public function testMissingPatternDoctrineStyle() CssColor::HSLA, ], $constraint->formats); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new CssColor(['formats' => CssColor::RGB]); - - $this->assertSame(CssColor::RGB, $constraint->formats); - } } class CssColorDummy diff --git a/Tests/Constraints/DateTimeTest.php b/Tests/Constraints/DateTimeTest.php index d144fc34a..d8891fe5b 100644 --- a/Tests/Constraints/DateTimeTest.php +++ b/Tests/Constraints/DateTimeTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\DateTime; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -39,15 +37,6 @@ public function testAttributes() self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new DateTime(['format' => 'm/d/Y']); - - $this->assertSame('m/d/Y', $constraint->format); - } } class DateTimeDummy diff --git a/Tests/Constraints/DivisibleByTest.php b/Tests/Constraints/DivisibleByTest.php index 9c0f1f9fa..7c9275ea9 100644 --- a/Tests/Constraints/DivisibleByTest.php +++ b/Tests/Constraints/DivisibleByTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\DivisibleBy; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -41,15 +39,6 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new DivisibleBy(['value' => 5]); - - $this->assertSame(5, $constraint->value); - } } class DivisibleByDummy diff --git a/Tests/Constraints/EqualToTest.php b/Tests/Constraints/EqualToTest.php index 9d7cf1dfc..ae0f97cfd 100644 --- a/Tests/Constraints/EqualToTest.php +++ b/Tests/Constraints/EqualToTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\EqualTo; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -41,15 +39,6 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new EqualTo(['value' => 5]); - - $this->assertSame(5, $constraint->value); - } } class EqualToDummy diff --git a/Tests/Constraints/GreaterThanOrEqualTest.php b/Tests/Constraints/GreaterThanOrEqualTest.php index 96ebe737d..b73a32885 100644 --- a/Tests/Constraints/GreaterThanOrEqualTest.php +++ b/Tests/Constraints/GreaterThanOrEqualTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\GreaterThanOrEqual; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -41,15 +39,6 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new GreaterThanOrEqual(['value' => 5]); - - $this->assertSame(5, $constraint->value); - } } class GreaterThanOrEqualDummy diff --git a/Tests/Constraints/GreaterThanTest.php b/Tests/Constraints/GreaterThanTest.php index 07c0fe0e7..ea962837a 100644 --- a/Tests/Constraints/GreaterThanTest.php +++ b/Tests/Constraints/GreaterThanTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\GreaterThan; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -41,15 +39,6 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new GreaterThan(['value' => 5]); - - $this->assertSame(5, $constraint->value); - } } class GreaterThanDummy diff --git a/Tests/Constraints/IdenticalToTest.php b/Tests/Constraints/IdenticalToTest.php index 589fab43b..da91a174b 100644 --- a/Tests/Constraints/IdenticalToTest.php +++ b/Tests/Constraints/IdenticalToTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\IdenticalTo; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -41,15 +39,6 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new IdenticalTo(['value' => 5]); - - $this->assertSame(5, $constraint->value); - } } class IdenticalToDummy diff --git a/Tests/Constraints/LessThanOrEqualTest.php b/Tests/Constraints/LessThanOrEqualTest.php index 1659fd1ec..1784eaff9 100644 --- a/Tests/Constraints/LessThanOrEqualTest.php +++ b/Tests/Constraints/LessThanOrEqualTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\LessThanOrEqual; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -41,15 +39,6 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new LessThanOrEqual(['value' => 5]); - - $this->assertSame(5, $constraint->value); - } } class LessThanOrEqualDummy diff --git a/Tests/Constraints/LessThanTest.php b/Tests/Constraints/LessThanTest.php index effffba71..1d2429d2a 100644 --- a/Tests/Constraints/LessThanTest.php +++ b/Tests/Constraints/LessThanTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\LessThan; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -41,15 +39,6 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new LessThan(['value' => 5]); - - $this->assertSame(5, $constraint->value); - } } class LessThanDummy diff --git a/Tests/Constraints/NotEqualToTest.php b/Tests/Constraints/NotEqualToTest.php index 941348e8e..970c67ce5 100644 --- a/Tests/Constraints/NotEqualToTest.php +++ b/Tests/Constraints/NotEqualToTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\NotEqualTo; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -41,15 +39,6 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new NotEqualTo(['value' => 5]); - - $this->assertSame(5, $constraint->value); - } } class NotEqualToDummy diff --git a/Tests/Constraints/NotIdenticalToTest.php b/Tests/Constraints/NotIdenticalToTest.php index e9714f9c9..96f13341b 100644 --- a/Tests/Constraints/NotIdenticalToTest.php +++ b/Tests/Constraints/NotIdenticalToTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\NotIdenticalTo; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -41,15 +39,6 @@ public function testAttributes() self::assertSame('myMessage', $cConstraint->message); self::assertSame(['foo'], $cConstraint->groups); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new NotIdenticalTo(['value' => 5]); - - $this->assertSame(5, $constraint->value); - } } class NotIdenticalToDummy diff --git a/Tests/Constraints/TimezoneTest.php b/Tests/Constraints/TimezoneTest.php index 2b4f1ad2a..5def3e361 100644 --- a/Tests/Constraints/TimezoneTest.php +++ b/Tests/Constraints/TimezoneTest.php @@ -12,8 +12,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Timezone; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -85,15 +83,6 @@ public function testAttributes() self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } - - #[IgnoreDeprecations] - #[Group('legacy')] - public function testDoctrineStyle() - { - $constraint = new Timezone(['zone' => \DateTimeZone::ALL]); - - $this->assertSame(\DateTimeZone::ALL, $constraint->zone); - } } class TimezoneDummy From ec6573942bd67865589b3863e421c91306247b0a Mon Sep 17 00:00:00 2001 From: Younes ENNAJI Date: Mon, 27 Oct 2025 14:33:24 +0100 Subject: [PATCH 55/57] [Validator] Correct PHPDoc for Collection constructor --- Constraints/Collection.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Constraints/Collection.php b/Constraints/Collection.php index cfd3bef55..3954a6c38 100644 --- a/Constraints/Collection.php +++ b/Constraints/Collection.php @@ -38,10 +38,10 @@ class Collection extends Composite public string $missingFieldsMessage = 'This field is missing.'; /** - * @param array|null $fields An associative array defining keys in the collection and their constraints - * @param string[]|null $groups - * @param bool|null $allowExtraFields Whether to allow additional keys not declared in the configured fields (defaults to false) - * @param bool|null $allowMissingFields Whether to allow the collection to lack some fields declared in the configured fields (defaults to false) + * @param array>|null $fields An associative array defining keys in the collection and their constraints + * @param string[]|null $groups + * @param bool|null $allowExtraFields Whether to allow additional keys not declared in the configured fields (defaults to false) + * @param bool|null $allowMissingFields Whether to allow the collection to lack some fields declared in the configured fields (defaults to false) */ #[HasNamedArguments] public function __construct(mixed $fields = null, ?array $groups = null, mixed $payload = null, ?bool $allowExtraFields = null, ?bool $allowMissingFields = null, ?string $extraFieldsMessage = null, ?string $missingFieldsMessage = null) From 8cbfeca6a4c719c00fb1c03bf8ae1d3adb8043c1 Mon Sep 17 00:00:00 2001 From: Younes ENNAJI Date: Wed, 29 Oct 2025 15:44:52 +0100 Subject: [PATCH 56/57] [Validator] Remove deprecated array type from Expression constructor PHPDoc --- Constraints/Expression.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Constraints/Expression.php b/Constraints/Expression.php index 3fe4e5bdc..3aeb943f6 100644 --- a/Constraints/Expression.php +++ b/Constraints/Expression.php @@ -41,10 +41,10 @@ class Expression extends Constraint public bool $negate = true; /** - * @param string|ExpressionObject|array|null $expression The expression to evaluate - * @param array|null $values The values of the custom variables used in the expression (defaults to an empty array) - * @param string[]|null $groups - * @param bool|null $negate Whether to fail if the expression evaluates to true (defaults to false) + * @param string|ExpressionObject|null $expression The expression to evaluate + * @param array|null $values The values of the custom variables used in the expression (defaults to an empty array) + * @param string[]|null $groups + * @param bool|null $negate Whether to fail if the expression evaluates to true (defaults to false) */ public function __construct( string|ExpressionObject|null $expression, From 865f7d1e6a23877ff77c9b722a40ae6306421ae8 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 30 Oct 2025 14:59:38 +0100 Subject: [PATCH 57/57] fix merge --- Tests/Constraints/YamlValidatorTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Tests/Constraints/YamlValidatorTest.php b/Tests/Constraints/YamlValidatorTest.php index bda49762d..21458725e 100644 --- a/Tests/Constraints/YamlValidatorTest.php +++ b/Tests/Constraints/YamlValidatorTest.php @@ -68,9 +68,7 @@ public function testInvalidFlags() ->assertRaised(); } - /** - * @dataProvider getDeprecationOnLinesData - */ + #[DataProvider('getDeprecationOnLinesData')] public function testDeprecationTriggersParseException(int $yamlLine, string $yamlValue) { $lines = explode("\n", $yamlValue);