Skip to content

Commit b08f6af

Browse files
committed
deprecate handling options in the base Constraint class
1 parent 477311f commit b08f6af

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+468
-172
lines changed

src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,21 @@ public function __construct(
6666
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
6767

6868
$options = array_merge($fields, $options ?? []);
69+
$fields = null;
6970
} else {
7071
if (\is_array($options)) {
7172
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
73+
74+
$options['fields'] = $fields;
75+
$fields = null;
7276
} else {
73-
$options = [];
77+
$options = null;
7478
}
75-
76-
$options['fields'] = $fields;
7779
}
7880

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

83+
$this->fields = $fields ?? $this->fields;
8184
$this->message = $message ?? $this->message;
8285
$this->service = $service ?? $this->service;
8386
$this->em = $em ?? $this->em;

src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordTest.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ public function testValidatedByService(UserPassword $constraint)
3535

3636
public static function provideServiceValidatedConstraints(): iterable
3737
{
38-
yield 'Doctrine style' => [new UserPassword(['service' => 'my_service'])];
39-
4038
yield 'named arguments' => [new UserPassword(service: 'my_service')];
4139

4240
$metadata = new ClassMetadata(UserPasswordDummy::class);
@@ -45,6 +43,14 @@ public static function provideServiceValidatedConstraints(): iterable
4543
yield 'attribute' => [$metadata->properties['b']->constraints[0]];
4644
}
4745

46+
/**
47+
* @group legacy
48+
*/
49+
public function testValidatedByServiceDoctrineStyle()
50+
{
51+
self::assertSame('my_service', (new UserPassword(['service' => 'my_service']))->validatedBy());
52+
}
53+
4854
public function testAttributes()
4955
{
5056
$metadata = new ClassMetadata(UserPasswordDummy::class);

src/Symfony/Component/Validator/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
CHANGELOG
22
=========
33

4+
7.4
5+
---
6+
7+
* Deprecate evaluating options in the base `Constraint`. Initialize properties in the constructor of the concrete constraint
8+
class instead and add the `#[InitializesOptions]` attribute to opt-out of the deprecated behaviour.
9+
* Deprecate the `normalizeOptions()`, `getDefaultOption()`, and `getRequiredOptions()` method of the base `Constraint` class.
10+
Overriding them in child constraint will not have any effects starting with Symfony 8.0.
11+
412
7.3
513
---
614

src/Symfony/Component/Validator/Constraint.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,17 @@ public function __construct(mixed $options = null, ?array $groups = null, mixed
110110
{
111111
unset($this->groups); // enable lazy initialization
112112

113+
if (null === $options && (\func_num_args() > 0 || (new \ReflectionMethod($this, 'getRequiredOptions'))->getDeclaringClass()->getName() === self::class)) {
114+
if (null !== $groups) {
115+
$this->groups = $groups;
116+
}
117+
$this->payload = $payload;
118+
119+
return;
120+
}
121+
122+
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);
123+
113124
$options = $this->normalizeOptions($options);
114125
if (null !== $groups) {
115126
$options['groups'] = $groups;
@@ -122,6 +133,8 @@ public function __construct(mixed $options = null, ?array $groups = null, mixed
122133
}
123134

124135
/**
136+
* @deprecated since Symfony 7.4
137+
*
125138
* @return array<string, mixed>
126139
*/
127140
protected function normalizeOptions(mixed $options): array
@@ -241,6 +254,8 @@ public function addImplicitGroupName(string $group): void
241254
*
242255
* Override this method to define a default option.
243256
*
257+
* @deprecated since Symfony 7.4
258+
*
244259
* @see __construct()
245260
*/
246261
public function getDefaultOption(): ?string
@@ -255,6 +270,8 @@ public function getDefaultOption(): ?string
255270
*
256271
* @return string[]
257272
*
273+
* @deprecated since Symfony 7.4
274+
*
258275
* @see __construct()
259276
*/
260277
public function getRequiredOptions(): array

src/Symfony/Component/Validator/Constraints/AbstractComparison.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,15 @@ public function __construct(mixed $value = null, ?string $propertyPath = null, ?
3939
} elseif (null !== $value) {
4040
if (\is_array($options)) {
4141
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
42-
} else {
43-
$options = [];
44-
}
4542

46-
$options['value'] = $value;
43+
$options['value'] = $value;
44+
}
4745
}
4846

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

5149
$this->message = $message ?? $this->message;
50+
$this->value = $value ?? $this->value;
5251
$this->propertyPath = $propertyPath ?? $this->propertyPath;
5352

5453
if (null === $this->value && null === $this->propertyPath) {
@@ -64,6 +63,9 @@ public function __construct(mixed $value = null, ?string $propertyPath = null, ?
6463
}
6564
}
6665

66+
/**
67+
* @deprecated since Symfony 7.4
68+
*/
6769
public function getDefaultOption(): ?string
6870
{
6971
return 'value';

src/Symfony/Component/Validator/Constraints/All.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,25 @@ class All extends Composite
3333
public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null)
3434
{
3535
if (\is_array($constraints) && !array_is_list($constraints)) {
36-
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
37-
}
36+
parent::__construct($constraints, $groups, $payload);
37+
} else {
38+
$this->constraints = $constraints;
3839

39-
parent::__construct($constraints ?? [], $groups, $payload);
40+
parent::__construct(null, $groups, $payload);
41+
}
4042
}
4143

44+
/**
45+
* @deprecated since Symfony 7.4
46+
*/
4247
public function getDefaultOption(): ?string
4348
{
4449
return 'constraints';
4550
}
4651

52+
/**
53+
* @deprecated since Symfony 7.4
54+
*/
4755
public function getRequiredOptions(): array
4856
{
4957
return ['constraints'];

src/Symfony/Component/Validator/Constraints/AtLeastOneOf.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,33 @@ class AtLeastOneOf extends Composite
4141
*/
4242
public function __construct(mixed $constraints = null, ?array $groups = null, mixed $payload = null, ?string $message = null, ?string $messageCollection = null, ?bool $includeInternalMessages = null)
4343
{
44+
$options = null;
45+
4446
if (\is_array($constraints) && !array_is_list($constraints)) {
4547
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
48+
$options = $constraints;
49+
} else {
50+
$this->constraints = $constraints;
4651
}
4752

48-
parent::__construct($constraints ?? [], $groups, $payload);
53+
parent::__construct($options, $groups, $payload);
4954

5055
$this->message = $message ?? $this->message;
5156
$this->messageCollection = $messageCollection ?? $this->messageCollection;
5257
$this->includeInternalMessages = $includeInternalMessages ?? $this->includeInternalMessages;
5358
}
5459

60+
/**
61+
* @deprecated since Symfony 7.4
62+
*/
5563
public function getDefaultOption(): ?string
5664
{
5765
return 'constraints';
5866
}
5967

68+
/**
69+
* @deprecated since Symfony 7.4
70+
*/
6071
public function getRequiredOptions(): array
6172
{
6273
return ['constraints'];
@@ -66,4 +77,23 @@ protected function getCompositeOption(): string
6677
{
6778
return 'constraints';
6879
}
80+
81+
private static function isConstraintsOption(mixed $value): bool
82+
{
83+
if (!\is_array($value)) {
84+
return true;
85+
}
86+
87+
if (!array_is_list($value)) {
88+
return false;
89+
}
90+
91+
foreach ($value as $constraint) {
92+
if (!$constraint instanceof Constraint) {
93+
return false;
94+
}
95+
}
96+
97+
return false;
98+
}
6999
}

src/Symfony/Component/Validator/Constraints/Blank.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function __construct(?array $options = null, ?string $message = null, ?ar
4141
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
4242
}
4343

44-
parent::__construct($options ?? [], $groups, $payload);
44+
parent::__construct($options, $groups, $payload);
4545

4646
$this->message = $message ?? $this->message;
4747
}

src/Symfony/Component/Validator/Constraints/Callback.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,21 @@ public function __construct(array|string|callable|null $callback = null, ?array
4444
if (!\is_array($callback) || (!isset($callback['callback']) && !isset($callback['groups']) && !isset($callback['payload']))) {
4545
if (\is_array($options)) {
4646
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
47-
} else {
48-
$options = [];
4947
}
50-
51-
$options['callback'] = $callback;
5248
} else {
5349
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
5450

5551
$options = array_merge($callback, $options ?? []);
5652
}
5753

5854
parent::__construct($options, $groups, $payload);
55+
56+
$this->callback = $callback ?? $this->callback;
5957
}
6058

59+
/**
60+
* @deprecated since Symfony 7.4
61+
*/
6162
public function getDefaultOption(): ?string
6263
{
6364
return 'callback';

src/Symfony/Component/Validator/Constraints/CardScheme.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,23 +62,28 @@ public function __construct(array|string|null $schemes, ?string $message = null,
6262
} else {
6363
if (\is_array($options)) {
6464
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
65-
} else {
66-
$options = [];
67-
}
6865

69-
$options['value'] = $schemes;
66+
$options['value'] = $schemes;
67+
}
7068
}
7169

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

72+
$this->schemes = $schemes ?? $this->schemes;
7473
$this->message = $message ?? $this->message;
7574
}
7675

76+
/**
77+
* @deprecated since Symfony 7.4
78+
*/
7779
public function getDefaultOption(): ?string
7880
{
7981
return 'schemes';
8082
}
8183

84+
/**
85+
* @deprecated since Symfony 7.4
86+
*/
8287
public function getRequiredOptions(): array
8388
{
8489
return ['schemes'];

src/Symfony/Component/Validator/Constraints/Cascade.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,26 @@ class Cascade extends Constraint
3333
public function __construct(array|string|null $exclude = null, ?array $options = null)
3434
{
3535
if (\is_array($exclude) && !array_is_list($exclude)) {
36-
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
3736

3837
$options = array_merge($exclude, $options ?? []);
3938
$options['exclude'] = array_flip((array) ($options['exclude'] ?? []));
39+
$exclude = $options['exclude'] ?? null;
4040
} else {
4141
if (\is_array($options)) {
4242
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
4343
}
4444

45-
$this->exclude = array_flip((array) $exclude);
45+
$exclude = array_flip((array) $exclude);
46+
$this->exclude = $exclude;
4647
}
4748

4849
if (\is_array($options) && \array_key_exists('groups', $options)) {
4950
throw new ConstraintDefinitionException(\sprintf('The option "groups" is not supported by the constraint "%s".', __CLASS__));
5051
}
5152

52-
parent::__construct($options);
53+
parent::__construct($options, null, $options['payload'] ?? null);
54+
55+
$this->exclude = $exclude ?? $this->exclude;
5356
}
5457

5558
public function getTargets(): string|array

src/Symfony/Component/Validator/Constraints/Choice.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ class Choice extends Constraint
4545
public string $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.';
4646
public bool $match = true;
4747

48+
/**
49+
* @deprecated since Symfony 7.4
50+
*/
4851
public function getDefaultOption(): ?string
4952
{
5053
return 'choices';
@@ -62,7 +65,7 @@ public function getDefaultOption(): ?string
6265
*/
6366
#[HasNamedArguments]
6467
public function __construct(
65-
string|array $options = [],
68+
string|array|null $options = null,
6669
?array $choices = null,
6770
callable|string|null $callback = null,
6871
?bool $multiple = null,
@@ -79,17 +82,14 @@ public function __construct(
7982
) {
8083
if (\is_array($options) && $options && array_is_list($options)) {
8184
$choices ??= $options;
82-
$options = [];
85+
$options = null;
8386
} elseif (\is_array($options) && [] !== $options) {
8487
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
8588
}
8689

87-
if (null !== $choices) {
88-
$options['value'] = $choices;
89-
}
90-
9190
parent::__construct($options, $groups, $payload);
9291

92+
$this->choices = $choices ?? $this->choices;
9393
$this->callback = $callback ?? $this->callback;
9494
$this->multiple = $multiple ?? $this->multiple;
9595
$this->strict = $strict ?? $this->strict;

src/Symfony/Component/Validator/Constraints/Collection.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,15 @@ class Collection extends Composite
4646
public function __construct(mixed $fields = null, ?array $groups = null, mixed $payload = null, ?bool $allowExtraFields = null, ?bool $allowMissingFields = null, ?string $extraFieldsMessage = null, ?string $missingFieldsMessage = null)
4747
{
4848
if (self::isFieldsOption($fields)) {
49-
$fields = ['fields' => $fields];
49+
$this->fields = $fields;
50+
$options = null;
5051
} else {
5152
trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class);
53+
54+
$options = $fields;
5255
}
5356

54-
parent::__construct($fields, $groups, $payload);
57+
parent::__construct($options, $groups, $payload);
5558

5659
$this->allowExtraFields = $allowExtraFields ?? $this->allowExtraFields;
5760
$this->allowMissingFields = $allowMissingFields ?? $this->allowMissingFields;
@@ -76,6 +79,9 @@ protected function initializeNestedConstraints(): void
7679
}
7780
}
7881

82+
/**
83+
* @deprecated since Symfony 7.4
84+
*/
7985
public function getRequiredOptions(): array
8086
{
8187
return ['fields'];

0 commit comments

Comments
 (0)