Make "Max" always inclusive

Since the rule "LessThan" was created, there is no reason to allow "Max"
to not be inclusive.

Also apply contribution guidelines to the rule.

Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
This commit is contained in:
Henrique Moody 2018-05-31 11:29:05 +02:00
parent da6abf4bdd
commit 6351f7a092
No known key found for this signature in database
GPG key ID: 221E9281655813A6
7 changed files with 132 additions and 79 deletions

View file

@ -1,43 +1,49 @@
# Max
- `Max(mixed $maxValue)`
- `Max(mixed $maxValue, bool $inclusive)`
- `Max(mixed $compareTo)`
Validates if the input doesn't exceed the maximum value.
Validates whether the input is less than or equal to a value.
```php
v::intVal()->max(15)->validate(20); // false
v::intVal()->max(20)->validate(20); // false
v::intVal()->max(20, true)->validate(20); // true
v::max(10)->validate(9); // true
v::max(10)->validate(10); // true
v::max(10)->validate(11); // false
```
Also accepts dates:
You can also validate:
```php
v::dateTime()->max('2012-01-01')->validate('2010-01-01'); // true
// Dates
v::dateTime()->max('2010-01-01')->validate('2000-01-01'); // true
v::dateTime()->max('2010-01-01')->validate('2020-01-01'); // false
// DateTimeInterface
v::dateTime()->max(new DateTime('today'))->validate(new DateTimeImmutable('yesterday')); // true
v::dateTime()->max(new DateTimeImmutable('today'))->validate(new DateTime('tomorrow')); // false
// Date intervals
v::dateTime()->max('18 years ago')->validate('1988-09-09'); // true
v::dateTime()->max('now')->validate('+1 minute'); // false
// Single character strings
v::stringType()->lowercase()->max('z')->validate('a'); // true
v::stringType()->uppercase()->max('B')->validate('C'); // false
```
Also date intervals:
```php
// Same of minimum age validation
v::dateTime()->max('-18 years')->validate('1988-09-09'); // true
```
`true` may be passed as a parameter to indicate that inclusive
values must be used.
Message template for this validator includes `{{maxValue}}`.
Message template for this validator includes `{{compareTo}}`.
## Changelog
Version | Description
--------|-------------
2.0.0 | Became always inclusive
1.0.0 | Became inclusive by default
0.3.9 | Created
***
See also:
- [Min](Min.md)
- [Between](Between.md)
- [GreaterThan](GreaterThan.md)
- [LessThan](LessThan.md)
- [Min](Min.md)

View file

@ -13,23 +13,22 @@ declare(strict_types=1);
namespace Respect\Validation\Exceptions;
class MaxException extends ValidationException
/**
* @author Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
* @author Andrew Peters <amp343@gmail.com>
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class MaxException extends ValidationException
{
public const INCLUSIVE = 'inclusive';
/**
* {@inheritdoc}
*/
public static $defaultTemplates = [
self::MODE_DEFAULT => [
self::STANDARD => '{{name}} must be less than {{interval}}',
self::INCLUSIVE => '{{name}} must be less than or equal to {{interval}}',
self::STANDARD => '{{name}} must be less than or equal to {{compareTo}}',
],
self::MODE_NEGATIVE => [
self::STANDARD => '{{name}} must not be less than {{interval}}',
self::INCLUSIVE => '{{name}} must not be less than or equal to {{interval}}',
self::STANDARD => '{{name}} must not be less than or equal to {{compareTo}}',
],
];
protected function chooseTemplate(): string
{
return $this->getParam('inclusive') ? static::INCLUSIVE : static::STANDARD;
}
}

View file

@ -43,7 +43,7 @@ final class Between extends AbstractEnvelope
parent::__construct(
new AllOf(
new Min($minValue, true),
new Max($maxValue, true)
new Max($maxValue)
),
[
'minValue' => $minValue,

View file

@ -13,14 +13,38 @@ declare(strict_types=1);
namespace Respect\Validation\Rules;
class Max extends AbstractInterval
use Respect\Validation\Helpers\ComparisonHelper;
/**
* Validates whether the input is less than or equal to a value.
*
* @author Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class Max extends AbstractRule
{
use ComparisonHelper;
/**
* @var mixed
*/
private $compareTo;
/**
* Initializes the rule by setting the value to be compared to the input.
*
* @param mixed $maxValue
*/
public function __construct($maxValue)
{
$this->compareTo = $maxValue;
}
/**
* {@inheritdoc}
*/
public function validate($input): bool
{
if ($this->inclusive) {
return $this->filterInterval($input) <= $this->filterInterval($this->interval);
}
return $this->filterInterval($input) < $this->filterInterval($this->interval);
return $this->toComparable($input) <= $this->toComparable($this->compareTo);
}
}

View file

@ -98,7 +98,7 @@ use Respect\Validation\Rules\Key;
* @method static Validator lessThan($compareTo)
* @method static Validator luhn()
* @method static Validator macAddress()
* @method static Validator max($maxValue, bool $inclusive = true)
* @method static Validator max($compareTo)
* @method static Validator maximumAge(int $age, string $format = null)
* @method static Validator mimetype(string $mimetype)
* @method static Validator min($minValue, bool $inclusive = true)

View file

@ -0,0 +1,37 @@
--FILE--
<?php
require 'vendor/autoload.php';
use Respect\Validation\Exceptions\MaxException;
use Respect\Validation\Exceptions\NestedValidationException;
use Respect\Validation\Validator as v;
try {
v::max(10)->check(11);
} catch (MaxException $exception) {
echo $exception->getMessage().PHP_EOL;
}
try {
v::not(v::max(10))->check(5);
} catch (MaxException $exception) {
echo $exception->getMessage().PHP_EOL;
}
try {
v::max('today')->assert('tomorrow');
} catch (NestedValidationException $exception) {
echo $exception->getFullMessage().PHP_EOL;
}
try {
v::not(v::max('b'))->assert('a');
} catch (NestedValidationException $exception) {
echo $exception->getFullMessage().PHP_EOL;
}
?>
--EXPECTF--
11 must be less than or equal to 10
5 must not be less than or equal to 10
- "tomorrow" must be less than or equal to "today"
- "a" must not be less than or equal to "b"

View file

@ -13,59 +13,46 @@ declare(strict_types=1);
namespace Respect\Validation\Rules;
use PHPUnit\Framework\TestCase;
use DateTime;
use DateTimeImmutable;
use Respect\Validation\Test\RuleTestCase;
/**
* @group rule
* @group rule
*
* @covers \Respect\Validation\Rules\Max
* @covers \Respect\Validation\Exceptions\MaxException
*
* @author Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
* @author Gabriel Caruso <carusogabriel34@gmail.com>
* @author Henrique Moody <henriquemoody@gmail.com>
*/
class MaxTest extends TestCase
final class MaxTest extends RuleTestCase
{
/**
* @dataProvider providerForValidMax
* {@inheritdoc}
*/
public function testValidMaxInputShouldReturnTrue($maxValue, $inclusive, $input): void
{
$max = new Max($maxValue, $inclusive);
self::assertTrue($max->validate($input));
$max->check($input);
$max->assert($input);
}
/**
* @dataProvider providerForInvalidMax
* @expectedException \Respect\Validation\Exceptions\MaxException
*/
public function testInvalidMaxValueShouldThrowMaxException($maxValue, $inclusive, $input): void
{
$max = new Max($maxValue, $inclusive);
self::assertFalse($max->validate($input));
$max->assert($input);
}
public function providerForValidMax()
public function providerForValidInput(): array
{
return [
[200, false, ''],
[200, false, 165.0],
[200, false, -200],
[200, true, 200],
[200, false, 0],
['-18 years', true, '1988-09-09'],
['z', true, 'z'],
['z', false, 'y'],
['tomorrow', true, 'now'],
[new Max(10), 9],
[new Max(10), 10],
[new Max('2010-01-01'), '2000-01-01'],
[new Max(new DateTime('today')), new DateTimeImmutable('yesterday')],
[new Max('18 years ago'), '1988-09-09'],
[new Max('z'), 'a'],
];
}
public function providerForInvalidMax()
/**
* {@inheritdoc}
*/
public function providerForInvalidInput(): array
{
return [
[200, false, 300],
[200, false, 250],
[200, false, 1500],
[200, false, 200],
[new Max(10), 11],
[new Max(new DateTimeImmutable('today')), new DateTime('tomorrow')],
[new Max('now'), '+1 minute'],
[new Max('B'), 'C'],
];
}
}