diff --git a/UPGRADE-7.4.md b/UPGRADE-7.4.md index 487bf6f5007a6..261b113da6eda 100644 --- a/UPGRADE-7.4.md +++ b/UPGRADE-7.4.md @@ -22,3 +22,121 @@ HttpClient ---------- * Deprecate using amphp/http-client < 5 + +Validator +--------- + + * 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 + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + public function __construct($option1 = null, $option2 = null) + { + parent::__construct(); + + $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 + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + public function __construct($option1, $option2 = null) + { + parent::__construct(); + + $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 + class CustomCompositeConstraint extends Composite + { + public array $constraints = []; + + public function __construct(array $constraints) + { + $this->constraints = $constraints; + + parent::__construct(); + } + } + ``` diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php index 59ab0aa2627d0..b2c1b3b377552 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php @@ -66,18 +66,21 @@ 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($fields, $options ?? []); + $fields = 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); + + $options['fields'] = $fields; + $fields = null; } else { - $options = []; + $options = null; } - - $options['fields'] = $fields; } parent::__construct($options, $groups, $payload); + $this->fields = $fields ?? $this->fields; $this->message = $message ?? $this->message; $this->service = $service ?? $this->service; $this->em = $em ?? $this->em; diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index b2267ac5f69c3..9d32719d47524 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -41,7 +41,7 @@ "symfony/translation": "^6.4|^7.0|^8.0", "symfony/type-info": "^7.1|^8.0", "symfony/uid": "^6.4|^7.0|^8.0", - "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/validator": "^7.4|^8.0", "symfony/var-dumper": "^6.4|^7.0|^8.0", "doctrine/collections": "^1.8|^2.0", "doctrine/data-fixtures": "^1.1|^2", @@ -64,7 +64,7 @@ "symfony/property-info": "<6.4", "symfony/security-bundle": "<6.4", "symfony/security-core": "<6.4", - "symfony/validator": "<6.4" + "symfony/validator": "<7.4" }, "autoload": { "psr-4": { "Symfony\\Bridge\\Doctrine\\": "" }, diff --git a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordTest.php b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordTest.php index ed4ca4427798d..2c9908083fdd7 100644 --- a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordTest.php @@ -35,8 +35,6 @@ public function testValidatedByService(UserPassword $constraint) public static function provideServiceValidatedConstraints(): iterable { - yield 'Doctrine style' => [new UserPassword(['service' => 'my_service'])]; - yield 'named arguments' => [new UserPassword(service: 'my_service')]; $metadata = new ClassMetadata(UserPasswordDummy::class); @@ -45,6 +43,14 @@ public static function provideServiceValidatedConstraints(): iterable yield 'attribute' => [$metadata->properties['b']->constraints[0]]; } + /** + * @group legacy + */ + public function testValidatedByServiceDoctrineStyle() + { + self::assertSame('my_service', (new UserPassword(['service' => 'my_service']))->validatedBy()); + } + public function testAttributes() { $metadata = new ClassMetadata(UserPasswordDummy::class); diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index e8146d2a50683..2db0623263115 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -1,6 +1,124 @@ 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 + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + public function __construct($option1 = null, $option2 = null) + { + parent::__construct(); + + $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 + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + public function __construct($option1, $option2 = null) + { + parent::__construct(); + + $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 + class CustomCompositeConstraint extends Composite + { + public array $constraints = []; + + public function __construct(array $constraints) + { + $this->constraints = $constraints; + + parent::__construct(); + } + } + ``` + 7.3 --- diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php index 5fd8ce84c0643..42ed471c6dc71 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/AbstractComparison.php b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php index 3830da7892fe9..523a812960a26 100644 --- a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/All.php b/src/Symfony/Component/Validator/Constraints/All.php index 92ded329b5ac7..b1a477782a2a7 100644 --- a/src/Symfony/Component/Validator/Constraints/All.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/AtLeastOneOf.php b/src/Symfony/Component/Validator/Constraints/AtLeastOneOf.php index b20ea0df0abe8..9ab2d4de91eac 100644 --- a/src/Symfony/Component/Validator/Constraints/AtLeastOneOf.php +++ b/src/Symfony/Component/Validator/Constraints/AtLeastOneOf.php @@ -41,22 +41,31 @@ class AtLeastOneOf extends Composite */ 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/src/Symfony/Component/Validator/Constraints/Blank.php b/src/Symfony/Component/Validator/Constraints/Blank.php index 72fbae57a34ba..cc0f648b2439b 100644 --- a/src/Symfony/Component/Validator/Constraints/Blank.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Callback.php b/src/Symfony/Component/Validator/Constraints/Callback.php index 44b51ac2a5be2..3afe2a1a563dd 100644 --- a/src/Symfony/Component/Validator/Constraints/Callback.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/CardScheme.php b/src/Symfony/Component/Validator/Constraints/CardScheme.php index a75e9f7abf7a4..7d2b76951ee22 100644 --- a/src/Symfony/Component/Validator/Constraints/CardScheme.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Cascade.php b/src/Symfony/Component/Validator/Constraints/Cascade.php index 7d90cfcf7f99f..97ecdf655977a 100644 --- a/src/Symfony/Component/Validator/Constraints/Cascade.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Choice.php b/src/Symfony/Component/Validator/Constraints/Choice.php index 1435a762b8b7e..3849bbf17d30d 100644 --- a/src/Symfony/Component/Validator/Constraints/Choice.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Collection.php b/src/Symfony/Component/Validator/Constraints/Collection.php index eca5a4eeecc86..c0fc237f047c2 100644 --- a/src/Symfony/Component/Validator/Constraints/Collection.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Composite.php b/src/Symfony/Component/Validator/Constraints/Composite.php index deac22cc5570d..47169e23926cc 100644 --- a/src/Symfony/Component/Validator/Constraints/Composite.php +++ b/src/Symfony/Component/Validator/Constraints/Composite.php @@ -51,6 +51,10 @@ abstract class Composite extends Constraint */ 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/src/Symfony/Component/Validator/Constraints/Count.php b/src/Symfony/Component/Validator/Constraints/Count.php index 10887290487e1..9a26cc008ebaa 100644 --- a/src/Symfony/Component/Validator/Constraints/Count.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/CssColor.php b/src/Symfony/Component/Validator/Constraints/CssColor.php index 793a4a5762ba5..1a8cfd0dad1db 100644 --- a/src/Symfony/Component/Validator/Constraints/CssColor.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/DateTime.php b/src/Symfony/Component/Validator/Constraints/DateTime.php index 6b287be75cf1f..96e7493ea6019 100644 --- a/src/Symfony/Component/Validator/Constraints/DateTime.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Existence.php b/src/Symfony/Component/Validator/Constraints/Existence.php index 72bc1da61f4a6..a31d744464bda 100644 --- a/src/Symfony/Component/Validator/Constraints/Existence.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Expression.php b/src/Symfony/Component/Validator/Constraints/Expression.php index a739acbb807b0..ac0e99e287216 100644 --- a/src/Symfony/Component/Validator/Constraints/Expression.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/IsFalse.php b/src/Symfony/Component/Validator/Constraints/IsFalse.php index bcdadeaf9c328..aa19d191d063f 100644 --- a/src/Symfony/Component/Validator/Constraints/IsFalse.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/IsNull.php b/src/Symfony/Component/Validator/Constraints/IsNull.php index fa04703ea6fb7..4aac68b4fd2f7 100644 --- a/src/Symfony/Component/Validator/Constraints/IsNull.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/IsTrue.php b/src/Symfony/Component/Validator/Constraints/IsTrue.php index 3c0345e7763ac..ea20cc80d189f 100644 --- a/src/Symfony/Component/Validator/Constraints/IsTrue.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Isbn.php b/src/Symfony/Component/Validator/Constraints/Isbn.php index 45ca4e4b892e0..471a39ca8d3f5 100644 --- a/src/Symfony/Component/Validator/Constraints/Isbn.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Length.php b/src/Symfony/Component/Validator/Constraints/Length.php index ce1460c6e359b..6678e7dc18e97 100644 --- a/src/Symfony/Component/Validator/Constraints/Length.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/NotBlank.php b/src/Symfony/Component/Validator/Constraints/NotBlank.php index 725e7eede4216..f108021ba063b 100644 --- a/src/Symfony/Component/Validator/Constraints/NotBlank.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/NotNull.php b/src/Symfony/Component/Validator/Constraints/NotNull.php index 28596925eb8ff..e2c784ebb271d 100644 --- a/src/Symfony/Component/Validator/Constraints/NotNull.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/PasswordStrength.php b/src/Symfony/Component/Validator/Constraints/PasswordStrength.php index 3867cfbda74ba..030d48141beb5 100644 --- a/src/Symfony/Component/Validator/Constraints/PasswordStrength.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Regex.php b/src/Symfony/Component/Validator/Constraints/Regex.php index 5c8501fa060fc..0881ae0b35fc9 100644 --- a/src/Symfony/Component/Validator/Constraints/Regex.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Sequentially.php b/src/Symfony/Component/Validator/Constraints/Sequentially.php index 1096a994d0bb4..31f506f28e9bb 100644 --- a/src/Symfony/Component/Validator/Constraints/Sequentially.php +++ b/src/Symfony/Component/Validator/Constraints/Sequentially.php @@ -30,18 +30,27 @@ class Sequentially extends Composite */ 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/src/Symfony/Component/Validator/Constraints/Timezone.php b/src/Symfony/Component/Validator/Constraints/Timezone.php index 93b0692efe02f..66734faf45c9d 100644 --- a/src/Symfony/Component/Validator/Constraints/Timezone.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Traverse.php b/src/Symfony/Component/Validator/Constraints/Traverse.php index d8546e323eb55..fa63624f6bc94 100644 --- a/src/Symfony/Component/Validator/Constraints/Traverse.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Type.php b/src/Symfony/Component/Validator/Constraints/Type.php index f3fe56dbbc2d1..1c8ded6aa6951 100644 --- a/src/Symfony/Component/Validator/Constraints/Type.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/Valid.php b/src/Symfony/Component/Validator/Constraints/Valid.php index 48deae8ac3c4d..0e60574f16708 100644 --- a/src/Symfony/Component/Validator/Constraints/Valid.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Constraints/When.php b/src/Symfony/Component/Validator/Constraints/When.php index f32b81a37dd3f..cafdec08d101a 100644 --- a/src/Symfony/Component/Validator/Constraints/When.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Tests/ConstraintTest.php b/src/Symfony/Component/Validator/Tests/ConstraintTest.php index 80e33c7b722a8..4418509777694 100644 --- a/src/Symfony/Component/Validator/Tests/ConstraintTest.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php index 9c58dd10714d9..2173c45f52055 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceTest.php @@ -19,6 +19,9 @@ class ChoiceTest extends TestCase { + /** + * @group legacy + */ public function testSetDefaultPropertyChoice() { $constraint = new ConstraintChoiceWithPreset('A'); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php index 9329ef1a2a022..bc5a8316ad5fa 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Tests/Constraints/CompoundTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CompoundTest.php index 9b515a48ccd08..c3c55eb3e35c6 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CompoundTest.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php b/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php index 51e8ae6a7bf2c..6a0cc10ef3f11 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithRequiredArgument.php b/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithRequiredArgument.php index f8abc8a563f52..93123677a413d 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithRequiredArgument.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Tests/Fixtures/LegacyConstraintA.php b/src/Symfony/Component/Validator/Tests/Fixtures/LegacyConstraintA.php new file mode 100644 index 0000000000000..b115608def79a --- /dev/null +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php index edfacae16ad31..ce12b31d479fb 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php index 70579011c3c94..8dfc6dd1b3c9b 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithNamedArguments.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php index af950fc139ad6..48b67362c440c 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/Fixtures/ConstraintWithoutValueWithNamedArguments.php +++ b/src/Symfony/Component/Validator/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/src/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php index 84d047f102dbc..d5dfb9ec0aa60 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php +++ b/src/Symfony/Component/Validator/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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy