bug #36140 [Validator] Add BC layer for notInRangeMessage when min and max are set (l-vo)
This PR was merged into the 4.4 branch.
Discussion
----------
[Validator] Add BC layer for notInRangeMessage when min and max are set
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | yes
| New feature? | no
| Deprecations? | no
| Tickets | Fix #36133
| License | MIT
| Doc PR |
According to #36133, the improvement added in #32435 may lead to a BC break when the developer pass `min` and `max` options and a custom `minMessage` or `maxMessage`. In this case it's expected to receive a `minMessage`/`maxMessage` in the violation but a `notInRangeMessage` is received instead.
So in the following conditions:
- `min` and `max` options are set
- `minMessage` or `maxMessage` is set
A deprecation is triggered. If a limit is violated and matches to the min/max message passed as option (`minMessage` for `min` violated and `maxMessage` for `max` violated), `minMessage/maxMessage` is used in the violation instead of `notInRangeMessage`.
Commits
-------
092d85c947
[Validator] Add BC layer for notInRangeMessage when min and max are set
This commit is contained in:
commit
f3753e93d8
@ -46,6 +46,17 @@ class Range extends Constraint
|
||||
public $max;
|
||||
public $maxPropertyPath;
|
||||
|
||||
// BC layer, to be removed in 5.0
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public $deprecatedMinMessageSet = false;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public $deprecatedMaxMessageSet = false;
|
||||
|
||||
public function __construct($options = null)
|
||||
{
|
||||
if (\is_array($options)) {
|
||||
@ -60,6 +71,15 @@ class Range extends Constraint
|
||||
if ((isset($options['minPropertyPath']) || isset($options['maxPropertyPath'])) && !class_exists(PropertyAccess::class)) {
|
||||
throw new LogicException(sprintf('The "%s" constraint requires the Symfony PropertyAccess component to use the "minPropertyPath" or "maxPropertyPath" option.', static::class));
|
||||
}
|
||||
|
||||
if (isset($options['min']) && isset($options['max'])) {
|
||||
$this->deprecatedMinMessageSet = isset($options['minMessage']);
|
||||
$this->deprecatedMaxMessageSet = isset($options['maxMessage']);
|
||||
|
||||
if ($this->deprecatedMinMessageSet || $this->deprecatedMaxMessageSet) {
|
||||
@trigger_error('Since symfony/validator 4.4: "minMessage" and "maxMessage" are deprecated when the "min" and "max" options are both set. Use "notInRangeMessage" instead.', E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($options);
|
||||
|
@ -88,11 +88,24 @@ class RangeValidator extends ConstraintValidator
|
||||
$hasUpperLimit = null !== $max;
|
||||
|
||||
if ($hasLowerLimit && $hasUpperLimit && ($value < $min || $value > $max)) {
|
||||
$violationBuilder = $this->context->buildViolation($constraint->notInRangeMessage)
|
||||
$message = $constraint->notInRangeMessage;
|
||||
$code = Range::NOT_IN_RANGE_ERROR;
|
||||
|
||||
if ($value < $min && $constraint->deprecatedMinMessageSet) {
|
||||
$message = $constraint->minMessage;
|
||||
$code = Range::TOO_LOW_ERROR;
|
||||
}
|
||||
|
||||
if ($value > $max && $constraint->deprecatedMaxMessageSet) {
|
||||
$message = $constraint->maxMessage;
|
||||
$code = Range::TOO_HIGH_ERROR;
|
||||
}
|
||||
|
||||
$violationBuilder = $this->context->buildViolation($message)
|
||||
->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE))
|
||||
->setParameter('{{ min }}', $this->formatValue($min, self::PRETTY_DATE))
|
||||
->setParameter('{{ max }}', $this->formatValue($max, self::PRETTY_DATE))
|
||||
->setCode(Range::NOT_IN_RANGE_ERROR);
|
||||
->setCode($code);
|
||||
|
||||
if (null !== $constraint->maxPropertyPath) {
|
||||
$violationBuilder->setParameter('{{ max_limit_path }}', $constraint->maxPropertyPath);
|
||||
|
@ -40,4 +40,43 @@ class RangeTest extends TestCase
|
||||
$this->expectExceptionMessage('No default option is configured');
|
||||
new Range('value');
|
||||
}
|
||||
|
||||
public function provideDeprecationTriggeredIfMinMaxAndMinMessageOrMaxMessageSet(): array
|
||||
{
|
||||
return [
|
||||
[['min' => 1, 'max' => 10, 'minMessage' => 'my_min_message'], true, false],
|
||||
[['min' => 1, 'max' => 10, 'maxMessage' => 'my_max_message'], false, true],
|
||||
[['min' => 1, 'max' => 10, 'minMessage' => 'my_min_message', 'maxMessage' => 'my_max_message'], true, true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
* @expectedDeprecation Since symfony/validator 4.4: minMessage and maxMessage are deprecated when min and max options are set together. Use notInRangeMessage instead.
|
||||
* @dataProvider provideDeprecationTriggeredIfMinMaxAndMinMessageOrMaxMessageSet
|
||||
*/
|
||||
public function testDeprecationTriggeredIfMinMaxAndMinMessageOrMaxMessageSet(array $options, bool $expectedDeprecatedMinMessageSet, bool $expectedDeprecatedMaxMessageSet)
|
||||
{
|
||||
$sut = new Range($options);
|
||||
$this->assertEquals($expectedDeprecatedMinMessageSet, $sut->deprecatedMinMessageSet);
|
||||
$this->assertEquals($expectedDeprecatedMaxMessageSet, $sut->deprecatedMaxMessageSet);
|
||||
}
|
||||
|
||||
public function provideDeprecationNotTriggeredIfNotMinMaxOrNotMinMessageNorMaxMessageSet(): array
|
||||
{
|
||||
return [
|
||||
[['min' => 1, 'minMessage' => 'my_min_message', 'maxMessage' => 'my_max_message']],
|
||||
[['max' => 10, 'minMessage' => 'my_min_message', 'maxMessage' => 'my_max_message']],
|
||||
[['min' => 1, 'max' => 10, 'notInRangeMessage' => 'my_message']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @doesNotPerformAssertions
|
||||
* @dataProvider provideDeprecationNotTriggeredIfNotMinMaxOrNotMinMessageNorMaxMessageSet
|
||||
*/
|
||||
public function testDeprecationNotTriggeredIfNotMinMaxOrNotMinMessageNorMaxMessageSet(array $options)
|
||||
{
|
||||
new Range($options);
|
||||
}
|
||||
}
|
||||
|
@ -754,6 +754,66 @@ class RangeValidatorTest extends ConstraintValidatorTestCase
|
||||
->setCode(Range::NOT_IN_RANGE_ERROR)
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
public function provideMessageIfMinAndMaxSet(): array
|
||||
{
|
||||
$notInRangeMessage = (new Range(['min' => '']))->notInRangeMessage;
|
||||
|
||||
return [
|
||||
[
|
||||
[],
|
||||
12,
|
||||
$notInRangeMessage,
|
||||
Range::NOT_IN_RANGE_ERROR,
|
||||
],
|
||||
[
|
||||
['notInRangeMessage' => 'not_in_range_message'],
|
||||
12,
|
||||
'not_in_range_message',
|
||||
Range::NOT_IN_RANGE_ERROR,
|
||||
],
|
||||
[
|
||||
['minMessage' => 'min_message'],
|
||||
0,
|
||||
'min_message',
|
||||
Range::TOO_LOW_ERROR,
|
||||
],
|
||||
[
|
||||
['maxMessage' => 'max_message'],
|
||||
0,
|
||||
$notInRangeMessage,
|
||||
Range::NOT_IN_RANGE_ERROR,
|
||||
],
|
||||
[
|
||||
['minMessage' => 'min_message'],
|
||||
15,
|
||||
$notInRangeMessage,
|
||||
Range::NOT_IN_RANGE_ERROR,
|
||||
],
|
||||
[
|
||||
['maxMessage' => 'max_message'],
|
||||
15,
|
||||
'max_message',
|
||||
Range::TOO_HIGH_ERROR,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
* @dataProvider provideMessageIfMinAndMaxSet
|
||||
*/
|
||||
public function testMessageIfMinAndMaxSet(array $constraintExtraOptions, int $value, string $expectedMessage, string $expectedCode)
|
||||
{
|
||||
$constraint = new Range(array_merge(['min' => 1, 'max' => 10], $constraintExtraOptions));
|
||||
$this->validator->validate($value, $constraint);
|
||||
|
||||
$this
|
||||
->buildViolation($expectedMessage)
|
||||
->setParameters(['{{ min }}' => '1', '{{ max }}' => '10', '{{ value }}' => (string) $value])
|
||||
->setCode($expectedCode)
|
||||
->assertRaised();
|
||||
}
|
||||
}
|
||||
|
||||
final class Limit
|
||||
|
Reference in New Issue
Block a user