Skip to content

Commit 391bc85

Browse files
committed
Add minimum / exclusiveMinimum / exclusiveMaximum / maximum
1 parent 7749a8f commit 391bc85

12 files changed

Lines changed: 762 additions & 77 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ $p = new Parser();
4949
$userSchema = $p->object([
5050
'name' => $p->string()->minLength(1)->maxLength(100),
5151
'email' => $p->string()->email(),
52-
'age' => $p->int()->gte(0)->lte(150),
52+
'age' => $p->int()->minimum(0)->maximum(150),
5353
]);
5454

5555
// Parse and validate data

doc/ErrorHandling.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ $p = new Parser();
226226
$requestSchema = $p->object([
227227
'name' => $p->string()->trim()->minLength(1)->maxLength(100),
228228
'email' => $p->string()->trim()->toLowerCase()->email(),
229-
'age' => $p->int()->gte(0)->lte(150),
229+
'age' => $p->int()->minimum(0)->maximum(150),
230230
])->strict();
231231

232232
function handleRequest(array $input): array
@@ -267,8 +267,8 @@ Each schema type uses a consistent error code prefix:
267267
| Schema | Prefix | Example Codes |
268268
|--------|--------|---------------|
269269
| string | `string.` | `string.type`, `string.minLength`, `string.email` |
270-
| int | `int.` | `int.type`, `int.gt`, `int.positive` |
271-
| float | `float.` | `float.type`, `float.gte`, `float.negative` |
270+
| int | `int.` | `int.type`, `int.exclusiveMinimum`, `int.positive` |
271+
| float | `float.` | `float.type`, `float.minimum`, `float.negative` |
272272
| bool | `bool.` | `bool.type` |
273273
| array | `array.` | `array.type`, `array.minLength` |
274274
| assoc | `assoc.` | `assoc.type`, `assoc.unknownField` |

doc/Schema/FloatSchema.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ $data = $schema->parse(4.2); // Returns: 4.2
1919
### Comparison Constraints
2020

2121
```php
22-
$schema->gt(5.0); // Greater than 5.0
23-
$schema->gte(5.0); // Greater than or equal to 5.0
24-
$schema->lt(10.0); // Less than 10.0
25-
$schema->lte(10.0); // Less than or equal to 10.0
22+
$schema->minimum(5.0); // Greater than or equal to 5.0
23+
$schema->exclusiveMinimum(5.0); // Greater than 5.0
24+
$schema->exclusiveMaximum(10.0); // Less than 10.0
25+
$schema->maximum(10.0); // Less than or equal to 10.0
2626
```
2727

2828
### Sign Constraints
@@ -56,17 +56,18 @@ $priceSchema->parse(-5.0); // Throws: nonNegative validation error
5656
### Percentage
5757

5858
```php
59-
$percentageSchema = $p->float()->gte(0.0)->lte(100.0);
59+
$percentageSchema = $p->float()->minimum(0.0)->maximum(100.0);
6060

6161
$percentageSchema->parse(75.5); // Returns: 75.5
62-
$percentageSchema->parse(150.0); // Throws: lte validation error
62+
$percentageSchema->parse(-1.0); // Throws: minimum validation error
63+
$percentageSchema->parse(150.0); // Throws: maximum validation error
6364
```
6465

6566
### Coordinates
6667

6768
```php
68-
$latitudeSchema = $p->float()->gte(-90.0)->lte(90.0);
69-
$longitudeSchema = $p->float()->gte(-180.0)->lte(180.0);
69+
$latitudeSchema = $p->float()->minimum(-90.0)->maximum(90.0);
70+
$longitudeSchema = $p->float()->minimum(-180.0)->maximum(180.0);
7071

7172
$coordinatesSchema = $p->object([
7273
'lat' => $latitudeSchema,
@@ -81,8 +82,8 @@ $coordinatesSchema->parse(['lat' => 47.1, 'lng' => 8.2]);
8182
| Code | Description |
8283
|------|-------------|
8384
| `float.type` | Value is not a float |
84-
| `float.gt` | Value is not greater than threshold (used by `gt()` and `positive()`) |
85-
| `float.gte` | Value is not greater than or equal to threshold (used by `gte()` and `nonNegative()`) |
86-
| `float.lt` | Value is not less than threshold (used by `lt()` and `negative()`) |
87-
| `float.lte` | Value is not less than or equal to threshold (used by `lte()` and `nonPositive()`) |
85+
| `float.minimum` | Value is not greater than or equal to threshold (used by `minimum` and `nonNegative()`) |
86+
| `float.exclusiveMinimum` | Value is not greater than threshold (used by `exclusiveMinimum()` and `positive()`) |
87+
| `float.exclusiveMaximum` | Value is not less than threshold (used by `exclusiveMaximum()` and `negative()`) |
88+
| `float.maximum` | Value is not less than or equal to threshold (used by `maximum()` and `nonPositive()`) |
8889
| `float.int` | Cannot convert float to int without precision loss (for `toInt()`) |

doc/Schema/IntSchema.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ $data = $schema->parse(1337); // Returns: 1337
1919
### Comparison Constraints
2020

2121
```php
22-
$schema->gt(5); // Greater than 5
23-
$schema->gte(5); // Greater than or equal to 5
24-
$schema->lt(10); // Less than 10
25-
$schema->lte(10); // Less than or equal to 10
22+
$schema->minimum(5); // Greater than or equal to 5
23+
$schema->exclusiveMinimum(5); // Greater than 5
24+
$schema->exclusiveMaximum(10); // Less than 10
25+
$schema->maximum(10); // Less than or equal to 10
2626
```
2727

2828
### Sign Constraints
@@ -57,18 +57,18 @@ $positiveSchema->parse(-1); // Throws: positive validation error
5757
### Range Validation
5858

5959
```php
60-
$ageSchema = $p->int()->gte(0)->lte(150);
60+
$ageSchema = $p->int()->minimum(0)->maximum(150);
6161

6262
$ageSchema->parse(25); // Returns: 25
63-
$ageSchema->parse(-1); // Throws: gte validation error
64-
$ageSchema->parse(200); // Throws: lte validation error
63+
$ageSchema->parse(-1); // Throws: minimum validation error
64+
$ageSchema->parse(200); // Throws: maximum validation error
6565
```
6666

6767
### Pagination
6868

6969
```php
7070
$offsetSchema = $p->int()->nonNegative();
71-
$limitSchema = $p->int()->positive()->lte(100);
71+
$limitSchema = $p->int()->positive()->maximum(100);
7272

7373
$paginationSchema = $p->object([
7474
'offset' => $offsetSchema,
@@ -90,7 +90,7 @@ $date = $timestampSchema->parse(1705744500);
9090
| Code | Description |
9191
|------|-------------|
9292
| `int.type` | Value is not an integer |
93-
| `int.gt` | Value is not greater than threshold (used by `gt()` and `positive()`) |
94-
| `int.gte` | Value is not greater than or equal to threshold (used by `gte()` and `nonNegative()`) |
95-
| `int.lt` | Value is not less than threshold (used by `lt()` and `negative()`) |
96-
| `int.lte` | Value is not less than or equal to threshold (used by `lte()` and `nonPositive()`) |
93+
| `int.minimum` | Value is not greater than or equal to threshold (used by `minimum` and `nonNegative()`) |
94+
| `int.exclusiveMinimum` | Value is not greater than threshold (used by `exclusiveMinimum()` and `positive()`) |
95+
| `int.exclusiveMaximum` | Value is not less than threshold (used by `exclusiveMaximum()` and `negative()`) |
96+
| `int.maximum` | Value is not less than or equal to threshold (used by `maximum()` and `nonPositive()`) |

doc/Schema/ObjectSchema.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ $userSchema = $p->object([
123123
$createUserSchema = $p->object([
124124
'name' => $p->string()->trim()->minLength(1)->maxLength(100),
125125
'email' => $p->string()->trim()->toLowerCase()->email(),
126-
'age' => $p->int()->gte(0)->lte(150),
126+
'age' => $p->int()->minimum(0)->maximum(150),
127127
])->strict();
128128
```
129129

@@ -182,7 +182,7 @@ $petSchema = $p->object([
182182

183183
$listRequestSchema = $p->object([
184184
'offset' => $p->int()->nonNegative(),
185-
'limit' => $p->int()->positive()->lte(100),
185+
'limit' => $p->int()->positive()->maximum(100),
186186
'sort' => $p->record($p->literal('asc')),
187187
'items' => $p->array($petSchema),
188188
]);

doc/Schema/TupleSchema.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ A tuple schema:
3030

3131
```php
3232
$coordinatesSchema = $p->tuple([
33-
$p->float()->gte(-90)->lte(90), // Latitude
34-
$p->float()->gte(-180)->lte(180), // Longitude
33+
$p->float()->minimum(-90)->maximum(90), // Latitude
34+
$p->float()->minimum(-180)->maximum(180), // Longitude
3535
]);
3636

3737
$coordinatesSchema->parse([47.3769, 8.5417]); // Zurich coordinates
@@ -41,9 +41,9 @@ $coordinatesSchema->parse([47.3769, 8.5417]); // Zurich coordinates
4141

4242
```php
4343
$rgbSchema = $p->tuple([
44-
$p->int()->gte(0)->lte(255), // Red
45-
$p->int()->gte(0)->lte(255), // Green
46-
$p->int()->gte(0)->lte(255), // Blue
44+
$p->int()->minimum(0)->maximum(255), // Red
45+
$p->int()->minimum(0)->maximum(255), // Green
46+
$p->int()->minimum(0)->maximum(255), // Blue
4747
]);
4848

4949
$rgbSchema->parse([255, 128, 0]); // Orange color
@@ -53,10 +53,10 @@ $rgbSchema->parse([255, 128, 0]); // Orange color
5353

5454
```php
5555
$rgbaSchema = $p->tuple([
56-
$p->int()->gte(0)->lte(255), // Red
57-
$p->int()->gte(0)->lte(255), // Green
58-
$p->int()->gte(0)->lte(255), // Blue
59-
$p->float()->gte(0)->lte(1), // Alpha
56+
$p->int()->minimum(0)->maximum(255), // Red
57+
$p->int()->minimum(0)->maximum(255), // Green
58+
$p->int()->minimum(0)->maximum(255), // Blue
59+
$p->float()->minimum(0)->maximum(1), // Alpha
6060
]);
6161

6262
$rgbaSchema->parse([255, 128, 0, 0.5]); // Semi-transparent orange
@@ -107,9 +107,9 @@ $point3dSchema->parse([1.5, 2.5, 3.5]);
107107

108108
```php
109109
$datePartsSchema = $p->tuple([
110-
$p->int()->gte(1)->lte(9999), // Year
111-
$p->int()->gte(1)->lte(12), // Month
112-
$p->int()->gte(1)->lte(31), // Day
110+
$p->int()->minimum(1)->maximum(9999), // Year
111+
$p->int()->minimum(1)->maximum(12), // Month
112+
$p->int()->minimum(1)->maximum(31), // Day
113113
]);
114114

115115
$datePartsSchema->parse([2024, 1, 20]);

src/Schema/FloatSchema.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ final class FloatSchema extends AbstractSchemaInnerParse implements SchemaInterf
1212
public const string ERROR_TYPE_CODE = 'float.type';
1313
public const string ERROR_TYPE_TEMPLATE = 'Type should be "float", {{given}} given';
1414

15+
public const string ERROR_MINIMUM_CODE = 'float.minimum';
16+
public const string ERROR_MINIMUM_TEMPLATE = 'Value should be greater than or equal {{minimum}}, {{given}} given';
17+
18+
public const string ERROR_EXCLUSIVE_MINIMUM_CODE = 'float.exclusiveMinimum';
19+
public const string ERROR_EXCLUSIVE_MINIMUM_TEMPLATE = 'Value should be greater than {{exclusiveMinimum}}, {{given}} given';
20+
21+
public const string ERROR_EXCLUSIVE_MAXIMUM_CODE = 'float.exclusiveMaximum';
22+
public const string ERROR_EXCLUSIVE_MAXIMUM_TEMPLATE = 'Value should be lesser than {{exclusiveMaximum}}, {{given}} given';
23+
24+
public const string ERROR_MAXIMUM_CODE = 'float.maximum';
25+
public const string ERROR_MAXIMUM_TEMPLATE = 'Value should be lesser than or equal {{maximum}}, {{given}} given';
26+
1527
public const string ERROR_GTE_CODE = 'float.gte';
1628
public const string ERROR_GTE_TEMPLATE = 'Value should be greater than or equal {{gte}}, {{given}} given';
1729

@@ -27,8 +39,78 @@ final class FloatSchema extends AbstractSchemaInnerParse implements SchemaInterf
2739
public const string ERROR_INT_CODE = 'float.int';
2840
public const string ERROR_INT_TEMPLATE = 'Cannot convert {{given}} to int';
2941

42+
public function minimum(float $minimum): static
43+
{
44+
return $this->postParse(static function (float $float) use ($minimum) {
45+
if ($float >= $minimum) {
46+
return $float;
47+
}
48+
49+
throw new ErrorsException(
50+
new Error(
51+
self::ERROR_MINIMUM_CODE,
52+
self::ERROR_MINIMUM_TEMPLATE,
53+
['minimum' => $minimum, 'given' => $float]
54+
)
55+
);
56+
});
57+
}
58+
59+
public function exclusiveMinimum(float $exclusiveMinimum): static
60+
{
61+
return $this->postParse(static function (float $float) use ($exclusiveMinimum) {
62+
if ($float > $exclusiveMinimum) {
63+
return $float;
64+
}
65+
66+
throw new ErrorsException(
67+
new Error(
68+
self::ERROR_EXCLUSIVE_MINIMUM_CODE,
69+
self::ERROR_EXCLUSIVE_MINIMUM_TEMPLATE,
70+
['exclusiveMinimum' => $exclusiveMinimum, 'given' => $float]
71+
)
72+
);
73+
});
74+
}
75+
76+
public function exclusiveMaximum(float $exclusiveMaximum): static
77+
{
78+
return $this->postParse(static function (float $float) use ($exclusiveMaximum) {
79+
if ($float < $exclusiveMaximum) {
80+
return $float;
81+
}
82+
83+
throw new ErrorsException(
84+
new Error(
85+
self::ERROR_EXCLUSIVE_MAXIMUM_CODE,
86+
self::ERROR_EXCLUSIVE_MAXIMUM_TEMPLATE,
87+
['exclusiveMaximum' => $exclusiveMaximum, 'given' => $float]
88+
)
89+
);
90+
});
91+
}
92+
93+
public function maximum(float $maximum): static
94+
{
95+
return $this->postParse(static function (float $float) use ($maximum) {
96+
if ($float <= $maximum) {
97+
return $float;
98+
}
99+
100+
throw new ErrorsException(
101+
new Error(
102+
self::ERROR_MAXIMUM_CODE,
103+
self::ERROR_MAXIMUM_TEMPLATE,
104+
['maximum' => $maximum, 'given' => $float]
105+
)
106+
);
107+
});
108+
}
109+
30110
public function gte(float $gte): static
31111
{
112+
@trigger_error('Use minimum instead', E_USER_DEPRECATED);
113+
32114
return $this->postParse(static function (float $float) use ($gte) {
33115
if ($float >= $gte) {
34116
return $float;
@@ -46,6 +128,8 @@ public function gte(float $gte): static
46128

47129
public function gt(float $gt): static
48130
{
131+
@trigger_error('Use exclusiveMinimum instead', E_USER_DEPRECATED);
132+
49133
return $this->postParse(static function (float $float) use ($gt) {
50134
if ($float > $gt) {
51135
return $float;
@@ -63,6 +147,8 @@ public function gt(float $gt): static
63147

64148
public function lt(float $lt): static
65149
{
150+
@trigger_error('Use exclusiveMaximum instead', E_USER_DEPRECATED);
151+
66152
return $this->postParse(static function (float $float) use ($lt) {
67153
if ($float < $lt) {
68154
return $float;
@@ -80,6 +166,8 @@ public function lt(float $lt): static
80166

81167
public function lte(float $lte): static
82168
{
169+
@trigger_error('Use maximum instead', E_USER_DEPRECATED);
170+
83171
return $this->postParse(static function (float $float) use ($lte) {
84172
if ($float <= $lte) {
85173
return $float;

0 commit comments

Comments
 (0)