1: <?php declare(strict_types=1);
2:
3: namespace Salient\Utility;
4:
5: use Stringable;
6:
7: /**
8: * Perform true/false tests on values
9: *
10: * @api
11: */
12: final class Test extends AbstractUtility
13: {
14: /**
15: * Check if a value is a boolean or boolean string
16: *
17: * The following are regarded as boolean strings (case-insensitive):
18: *
19: * - `"1"`, `"0"`
20: * - `"on"`, `"off"`
21: * - `"true"`, `"false"`
22: * - `"y"`, `"n"`
23: * - `"yes"`, `"no"`
24: * - `"enable"`, `"disable"`
25: * - `"enabled"`, `"disabled"`
26: *
27: * @param mixed $value
28: */
29: public static function isBoolean($value): bool
30: {
31: return is_bool($value) || (
32: is_string($value)
33: && Regex::match('/^' . Regex::BOOLEAN_STRING . '$/', $value)
34: );
35: }
36:
37: /**
38: * Check if a value is an integer or integer string
39: *
40: * @param mixed $value
41: */
42: public static function isInteger($value): bool
43: {
44: return is_int($value) || (
45: is_string($value)
46: && Regex::match('/^' . Regex::INTEGER_STRING . '$/', $value)
47: );
48: }
49:
50: /**
51: * Check if a value is a float or float string
52: *
53: * Returns `false` if `$value` is an integer string.
54: *
55: * @param mixed $value
56: */
57: public static function isFloat($value): bool
58: {
59: return is_float($value) || (
60: is_string($value)
61: && is_numeric(trim($value))
62: && !Regex::match('/^' . Regex::INTEGER_STRING . '$/', $value)
63: );
64: }
65:
66: /**
67: * Check if a value is an integer or would be cast to an integer if used as
68: * an array key
69: *
70: * @param mixed $value
71: */
72: public static function isNumericKey($value): bool
73: {
74: return is_int($value)
75: || is_float($value)
76: || is_bool($value)
77: || (is_string($value) && Regex::match('/^(-?[1-9][0-9]*|0)$/D', $value));
78: }
79:
80: /**
81: * Check if a value is a valid date string
82: *
83: * @param mixed $value
84: */
85: public static function isDateString($value): bool
86: {
87: return is_string($value) && strtotime($value) !== false;
88: }
89:
90: /**
91: * Check if a value is a string or Stringable
92: *
93: * @param mixed $value
94: * @phpstan-assert-if-true Stringable|string $value
95: */
96: public static function isStringable($value): bool
97: {
98: return is_string($value)
99: || $value instanceof Stringable
100: || (is_object($value) && method_exists($value, '__toString'));
101: }
102:
103: /**
104: * Check if a value is a number within a range
105: *
106: * @param int|float $value
107: * @param int|float $min
108: * @param int|float $max
109: */
110: public static function isBetween($value, $min, $max): bool
111: {
112: return $value >= $min && $value <= $max;
113: }
114:
115: /**
116: * Check if a value is a reserved PHP type
117: *
118: * @link https://www.php.net/manual/en/reserved.php
119: */
120: public static function isBuiltinType(string $value): bool
121: {
122: return in_array(Str::lower($value), [
123: 'array',
124: 'bool',
125: 'callable',
126: 'enum',
127: 'false',
128: 'float',
129: 'int',
130: 'iterable',
131: 'mixed',
132: 'never',
133: 'null',
134: 'numeric',
135: 'object',
136: 'parent',
137: 'resource',
138: 'self',
139: 'static',
140: 'string',
141: 'true',
142: 'void',
143: ], true);
144: }
145:
146: /**
147: * Check if a value is a valid PHP class name
148: *
149: * @param mixed $value
150: * @phpstan-assert-if-true class-string $value
151: */
152: public static function isFqcn($value): bool
153: {
154: return is_string($value)
155: && Regex::match('/^' . Regex::PHP_TYPE . '$/D', $value);
156: }
157: }
158: