Skip to content

Commit 9fa074d

Browse files
committed
feat!: add FloatValidator and NumericConstraintsTrait
- Add FloatValidator for dedicated floating-point number validation - Create NumericConstraintsTrait with shared numeric constraints (min, max, multipleOf, positive, negative) - Enhance IntValidator with numeric constraints via trait - Add Validator::isFloat() factory method - Smart multipleOf() implementation for both int and float types - Eliminate code duplication between numeric validators BREAKING CHANGE: Renamed NumberValidator to FloatValidator, isNumber() to isFloat()
1 parent b0dc98a commit 9fa074d

4 files changed

Lines changed: 132 additions & 0 deletions

File tree

src/Lemmon/FloatValidator.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Lemmon;
4+
5+
class FloatValidator extends FieldValidator
6+
{
7+
use NumericConstraintsTrait;
8+
9+
/**
10+
* @inheritDoc
11+
*/
12+
protected function coerceValue(mixed $value): mixed
13+
{
14+
if (is_numeric($value)) {
15+
return is_int($value) ? (float) $value : (float) $value;
16+
}
17+
return $value;
18+
}
19+
20+
/**
21+
* @inheritDoc
22+
*/
23+
protected function validateType(mixed $value, string $key): mixed
24+
{
25+
if (!is_numeric($value)) {
26+
throw new ValidationException(['Value must be a float.']);
27+
}
28+
return (float) $value;
29+
}
30+
}

src/Lemmon/IntValidator.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
class IntValidator extends FieldValidator
66
{
7+
use NumericConstraintsTrait;
8+
79
/**
810
* @inheritDoc
911
*/
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
namespace Lemmon;
4+
5+
/**
6+
* Trait providing common numeric validation constraints.
7+
*
8+
* This trait contains validation methods that are shared between
9+
* IntValidator and FloatValidator to eliminate code duplication.
10+
*/
11+
trait NumericConstraintsTrait
12+
{
13+
/**
14+
* Validates that the value is greater than or equal to the minimum.
15+
*
16+
* @param int|float $min The minimum value.
17+
* @param ?string $message Custom error message.
18+
* @return static
19+
*/
20+
public function min(int|float $min, ?string $message = null): static
21+
{
22+
return $this->addValidation(
23+
fn ($value, $key = null, $input = null) => $value >= $min,
24+
$message ?? "Value must be at least {$min}."
25+
);
26+
}
27+
28+
/**
29+
* Validates that the value is less than or equal to the maximum.
30+
*
31+
* @param int|float $max The maximum value.
32+
* @param ?string $message Custom error message.
33+
* @return static
34+
*/
35+
public function max(int|float $max, ?string $message = null): static
36+
{
37+
return $this->addValidation(
38+
fn ($value, $key = null, $input = null) => $value <= $max,
39+
$message ?? "Value must be at most {$max}."
40+
);
41+
}
42+
43+
/**
44+
* Validates that the value is a multiple of the given divisor.
45+
*
46+
* @param int|float $divisor The divisor.
47+
* @param ?string $message Custom error message.
48+
* @return static
49+
*/
50+
public function multipleOf(int|float $divisor, ?string $message = null): static
51+
{
52+
return $this->addValidation(
53+
function ($value, $key = null, $input = null) use ($divisor) {
54+
if (is_int($divisor) && is_int($value)) {
55+
return $value % $divisor === 0;
56+
}
57+
return fmod((float) $value, (float) $divisor) === 0.0;
58+
},
59+
$message ?? "Value must be a multiple of {$divisor}."
60+
);
61+
}
62+
63+
/**
64+
* Validates that the value is positive (greater than zero).
65+
*
66+
* @param ?string $message Custom error message.
67+
* @return static
68+
*/
69+
public function positive(?string $message = null): static
70+
{
71+
return $this->addValidation(
72+
fn ($value, $key = null, $input = null) => $value > 0,
73+
$message ?? 'Value must be positive.'
74+
);
75+
}
76+
77+
/**
78+
* Validates that the value is negative (less than zero).
79+
*
80+
* @param ?string $message Custom error message.
81+
* @return static
82+
*/
83+
public function negative(?string $message = null): static
84+
{
85+
return $this->addValidation(
86+
fn ($value, $key = null, $input = null) => $value < 0,
87+
$message ?? 'Value must be negative.'
88+
);
89+
}
90+
}

src/Lemmon/Validator.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,14 @@ public static function isBool(): BoolValidator
6565
{
6666
return new BoolValidator();
6767
}
68+
69+
/**
70+
* Creates a new FloatValidator for floating-point numbers.
71+
*
72+
* @return FloatValidator
73+
*/
74+
public static function isFloat(): FloatValidator
75+
{
76+
return new FloatValidator();
77+
}
6878
}

0 commit comments

Comments
 (0)