From 1f366830bca6e810c8d1e2597a827593b0328535 Mon Sep 17 00:00:00 2001 From: kj Date: Thu, 3 Sep 2026 14:35:02 -0300 Subject: [PATCH] feat(validation): add type and size-based validation methods Add string, array, min, max, between, and size validators to the Validator class. A private measure helper centralizes size semantics for numbers (value), strings (length), and arrays (element count). --- src/Libs/Validator.php | 111 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/Libs/Validator.php b/src/Libs/Validator.php index 8b4afd8..e69a5f3 100644 --- a/src/Libs/Validator.php +++ b/src/Libs/Validator.php @@ -228,6 +228,117 @@ class Validator return filter_var($subject, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== null; } + /** + * Checks if the value is a string. + * + * Note this is the strict type check: a PHP integer (e.g. 42) or an array + * fails, while any string - including a numeric string like "42" - passes. + * + * @param mixed $subject The value to check. + * + * @return bool + */ + public static function string(mixed $subject): bool + { + return is_string($subject); + } + + /** + * Checks if the value is an array. + * + * @param mixed $subject The value to check. + * + * @return bool + */ + public static function array(mixed $subject): bool + { + return is_array($subject); + } + + /** + * Measures a value for the size-based rules (min/max/between/size). + * + * A numeric value is measured by its number, a plain string by its + * character length, and an array by its element count. This single helper + * keeps the size semantics consistent and is where the file case (kilobytes) + * is added later. + * + * @param mixed $subject The value to measure. + * + * @return float + */ + private static function measure(mixed $subject): float + { + if (is_numeric($subject)) { + return (float) $subject; + } + + if (is_string($subject)) { + return (float) (function_exists('mb_strlen') ? mb_strlen($subject) : strlen($subject)); + } + + if (is_array($subject)) { + return (float) count($subject); + } + + return 0.0; + } + + /** + * Checks if the measured value is greater than or equal to a minimum. + * + * @param mixed $subject The value to check. + * @param mixed $min The minimum length, number or count. + * + * @return bool + */ + public static function min(mixed $subject, mixed $min): bool + { + return static::measure($subject) >= (float) $min; + } + + /** + * Checks if the measured value is less than or equal to a maximum. + * + * @param mixed $subject The value to check. + * @param mixed $max The maximum length, number or count. + * + * @return bool + */ + public static function max(mixed $subject, mixed $max): bool + { + return static::measure($subject) <= (float) $max; + } + + /** + * Checks if the measured value is within an inclusive range. + * + * @param mixed $subject The value to check. + * @param mixed $min The lower bound. + * @param mixed $max The upper bound. + * + * @return bool + */ + public static function between(mixed $subject, mixed $min, mixed $max): bool + { + $size = static::measure($subject); + + return $size >= (float) $min && $size <= (float) $max; + } + + /** + * Checks if the measured value is exactly a given size. + * + * @param mixed $subject The value to check. + * @param mixed $size The expected length, number or count. + * + * @return bool + */ + public static function size(mixed $subject, mixed $size): bool + { + return static::measure($subject) === (float) $size; + } + /** * Checks if the value is a valid email address. *