Create BetweenExclusive rule

Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
This commit is contained in:
Henrique Moody 2024-03-11 00:34:11 +01:00
parent 1e2c1bfe30
commit 52b75bc1ed
No known key found for this signature in database
GPG key ID: 221E9281655813A6
16 changed files with 231 additions and 0 deletions

View file

@ -44,6 +44,7 @@
## Comparisons
- [Between](rules/Between.md)
- [BetweenExclusive](rules/BetweenExclusive.md)
- [Equals](rules/Equals.md)
- [Equivalent](rules/Equivalent.md)
- [GreaterThan](rules/GreaterThan.md)
@ -297,6 +298,7 @@
- [Base](rules/Base.md)
- [Base64](rules/Base64.md)
- [Between](rules/Between.md)
- [BetweenExclusive](rules/BetweenExclusive.md)
- [BoolType](rules/BoolType.md)
- [BoolVal](rules/BoolVal.md)
- [Bsn](rules/Bsn.md)

View file

@ -30,6 +30,7 @@ Version | Description
***
See also:
- [BetweenExclusive](BetweenExclusive.md)
- [DateTime](DateTime.md)
- [GreaterThan](GreaterThan.md)
- [GreaterThanOrEqual](GreaterThanOrEqual.md)

View file

@ -0,0 +1,39 @@
# BetweenExclusive
- `BetweenExclusive(mixed $minimum, mixed $maximum)`
Validates whether the input is between two other values, exclusively.
```php
v::betweenExclusive(10, 20)->validate(10); // true
v::betweenExclusive('a', 'e')->validate('c'); // true
v::betweenExclusive(new DateTime('yesterday'), new DateTime('tomorrow'))->validate(new DateTime('today')); // true
v::betweenExclusive(0, 100)->validate(100); // false
v::betweenExclusive('a', 'z')->validate('a'); // false
```
Validation makes comparison easier, check out our supported [comparable values](../07-comparable-values.md).
## Categorization
- Comparisons
## Changelog
| Version | Description |
|--------:|-----------------------------|
| 3.0.0 | Created |
***
See also:
- [Between](Between.md)
- [DateTime](DateTime.md)
- [GreaterThan](GreaterThan.md)
- [GreaterThanOrEqual](GreaterThanOrEqual.md)
- [Length](Length.md)
- [LessThan](LessThan.md)
- [LessThanOrEqual](LessThanOrEqual.md)
- [Max](Max.md)
- [Min](Min.md)

View file

@ -71,6 +71,7 @@ v::dateTime(DateTime::RFC3339_EXTENDED)->validate($input); // false
See also:
- [Between](Between.md)
- [BetweenExclusive](BetweenExclusive.md)
- [Callback](Callback.md)
- [Date](Date.md)
- [LeapDate](LeapDate.md)

View file

@ -28,6 +28,7 @@ Version | Description
See also:
- [Between](Between.md)
- [BetweenExclusive](BetweenExclusive.md)
- [GreaterThanOrEqual](GreaterThanOrEqual.md)
- [LessThanOrEqual](LessThanOrEqual.md)
- [Max](Max.md)

View file

@ -32,6 +32,7 @@ Message template for this validator includes `{{compareTo}}`.
See also:
- [Between](Between.md)
- [BetweenExclusive](BetweenExclusive.md)
- [GreaterThan](GreaterThan.md)
- [Length](Length.md)
- [LessThan](LessThan.md)

View file

@ -50,4 +50,5 @@ Version | Description
See also:
- [Between](Between.md)
- [BetweenExclusive](BetweenExclusive.md)
- [GreaterThanOrEqual](GreaterThanOrEqual.md)

View file

@ -28,6 +28,7 @@ Version | Description
See also:
- [Between](Between.md)
- [BetweenExclusive](BetweenExclusive.md)
- [GreaterThanOrEqual](GreaterThanOrEqual.md)
- [LessThanOrEqual](LessThanOrEqual.md)
- [Max](Max.md)

View file

@ -32,6 +32,7 @@ Message template for this validator includes `{{compareTo}}`.
See also:
- [Between](Between.md)
- [BetweenExclusive](BetweenExclusive.md)
- [GreaterThan](GreaterThan.md)
- [GreaterThanOrEqual](GreaterThanOrEqual.md)
- [LessThan](LessThan.md)

View file

@ -38,6 +38,7 @@ empty, the validation will fail.
See also:
- [Between](Between.md)
- [BetweenExclusive](BetweenExclusive.md)
- [GreaterThan](GreaterThan.md)
- [GreaterThanOrEqual](GreaterThanOrEqual.md)
- [IterableType](IterableType.md)

View file

@ -38,6 +38,7 @@ empty, the validation will fail.
See also:
- [Between](Between.md)
- [BetweenExclusive](BetweenExclusive.md)
- [Each](Each.md)
- [GreaterThan](GreaterThan.md)
- [GreaterThanOrEqual](GreaterThanOrEqual.md)

View file

@ -42,6 +42,8 @@ interface ChainedValidator extends Validatable
public function between(mixed $minimum, mixed $maximum): ChainedValidator;
public function betweenExclusive(mixed $minimum, mixed $maximum): ChainedValidator;
public function boolType(): ChainedValidator;
public function boolVal(): ChainedValidator;

View file

@ -42,6 +42,8 @@ interface StaticValidator
public static function between(mixed $minimum, mixed $maximum): ChainedValidator;
public static function betweenExclusive(mixed $minimum, mixed $maximum): ChainedValidator;
public static function bic(string $countryCode): ChainedValidator;
public static function boolType(): ChainedValidator;

View file

@ -0,0 +1,36 @@
<?php
/*
* Copyright (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
* SPDX-License-Identifier: MIT
*/
declare(strict_types=1);
namespace Respect\Validation\Rules;
use Respect\Validation\Exceptions\InvalidRuleConstructorException;
use Respect\Validation\Helpers\CanCompareValues;
use Respect\Validation\Message\Template;
use Respect\Validation\Rules\Core\Envelope;
#[Template(
'{{name}} must be greater than {{minValue}} and less than {{maxValue}}',
'{{name}} must not be greater than {{minValue}} and less than {{maxValue}}',
)]
final class BetweenExclusive extends Envelope
{
use CanCompareValues;
public function __construct(mixed $minimum, mixed $maximum)
{
if ($this->toComparable($minimum) >= $this->toComparable($maximum)) {
throw new InvalidRuleConstructorException('Minimum cannot be less than or equals to maximum');
}
parent::__construct(
new AllOf(new GreaterThan($minimum), new LessThan($maximum)),
['minValue' => $minimum, 'maxValue' => $maximum]
);
}
}

View file

@ -0,0 +1,49 @@
--FILE--
<?php
declare(strict_types=1);
require 'vendor/autoload.php';
use Respect\Validation\Validator as v;
run([
'Default' => [v::betweenExclusive(1, 10), 12],
'Negative' => [v::not(v::betweenExclusive(1, 10)), 5],
'With template' => [v::betweenExclusive(1, 10), 12, 'Bewildered bees buzzed between blooming begonias'],
'With name' => [v::betweenExclusive(1, 10)->setName('Range'), 10],
]);
?>
--EXPECT--
Default
⎺⎺⎺⎺⎺⎺⎺
12 must be greater than 1 and less than 10
- 12 must be greater than 1 and less than 10
[
'betweenExclusive' => '12 must be greater than 1 and less than 10',
]
Negative
⎺⎺⎺⎺⎺⎺⎺⎺
5 must not be greater than 1 and less than 10
- 5 must not be greater than 1 and less than 10
[
'betweenExclusive' => '5 must not be greater than 1 and less than 10',
]
With template
⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺
Bewildered bees buzzed between blooming begonias
- Bewildered bees buzzed between blooming begonias
[
'betweenExclusive' => 'Bewildered bees buzzed between blooming begonias',
]
With name
⎺⎺⎺⎺⎺⎺⎺⎺⎺
Range must be greater than 1 and less than 10
- Range must be greater than 1 and less than 10
[
'Range' => 'Range must be greater than 1 and less than 10',
]

View file

@ -0,0 +1,92 @@
<?php
/*
* Copyright (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
* SPDX-License-Identifier: MIT
*/
declare(strict_types=1);
namespace Respect\Validation\Rules;
use DateTime;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\Test;
use Respect\Validation\Exceptions\InvalidRuleConstructorException;
use Respect\Validation\Test\Stubs\CountableStub;
use Respect\Validation\Test\TestCase;
#[Group('rule')]
#[CoversClass(BetweenExclusive::class)]
final class BetweenExclusiveTest extends TestCase
{
#[Test]
public function minimumValueShouldNotBeGreaterThanMaximumValue(): void
{
$this->expectExceptionObject(
new InvalidRuleConstructorException('Minimum cannot be less than or equals to maximum')
);
new BetweenExclusive(10, 5);
}
#[Test]
public function minimumValueShouldNotBeEqualsToMaximumValue(): void
{
$this->expectExceptionObject(
new InvalidRuleConstructorException('Minimum cannot be less than or equals to maximum')
);
new BetweenExclusive(5, 5);
}
#[Test]
#[DataProvider('providerForValidInput')]
public function shouldValidateValidInput(mixed $minValue, mixed $maxValue, mixed $input): void
{
self::assertValidInput(new BetweenExclusive($minValue, $maxValue), $input);
}
#[Test]
#[DataProvider('providerForInvalidInput')]
public function shouldValidateInvalidInput(mixed $minValue, mixed $maxValue, mixed $input): void
{
self::assertInvalidInput(new BetweenExclusive($minValue, $maxValue), $input);
}
/** @return array<array{mixed, mixed, mixed}> */
public static function providerForValidInput(): array
{
return [
'positive numbers' => [10, 20, 15],
'negative numbers' => [-10, 20, -5],
'positive and negative numbers' => [-10, 20, 0],
'letters' => ['a', 'z', 'j'],
'date time objects' => [new DateTime('yesterday'), new DateTime('tomorrow'), new DateTime('now')],
'countable objects' => [new CountableStub(1), new CountableStub(10), 5],
'countable objects against integer' => [new CountableStub(1), new CountableStub(10), 5],
];
}
/** @return array<array{mixed, mixed, mixed}> */
public static function providerForInvalidInput(): iterable
{
return [
'equals to the max value' => [10, 20, 20],
'equals to the min value' => [10, 20, 10],
'equals to the max value without a gap' => [0, 1, 1],
'equals to the min value without a gap' => [0, 1, 0],
'empty string' => [10, 20, ''],
'greater than max value' => [0, 1, 2],
'less than min value' => [0, 1, -1],
'letters greater than max value' => ['a', 'j', 'z'],
'datetime greater than max value' => [
new DateTime('yesterday'),
new DateTime('now'),
new DateTime('tomorrow'),
],
];
}
}