Hint::validateNumeric()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4286
cc 1
eloc 5
nc 1
nop 2
1
<?php
2
3
namespace Saxulum\Hint;
4
5
class Hint
6
{
7
    const BOOL = 'bool';
8
    const INT = 'int';
9
    const FLOAT = 'float';
10
    const NUMERIC = 'numeric';
11
    const STRING = 'string';
12
    const ARR = 'array';
13
14
    /**
15
     * @param  string      $varname
16
     * @param  mixed       $value
17
     * @param  string|null $hint
18
     * @param  bool|null   $nullable
19
     * @throws \Exception
20
     */
21
    public static function validateOrException($varname, $value, $hint = null, $nullable = null)
22
    {
23
        if (!self::validate($value, $hint, $nullable)) {
24
            $type = gettype($value);
25
            throw new \Exception("Invalid type '{$type}' for hint '{$hint}' on property '{$varname}'!");
26
        }
27
    }
28
29
    /**
30
     * @param  mixed       $value
31
     * @param  string|null $hint
32
     * @param  bool|null   $nullable
33
     * @return bool
34
     */
35
    public static function validate($value, $hint = null, $nullable = null)
36
    {
37
        if (null === $hint) {
38
            return true;
39
        }
40
41
        $isIteratableHint = self::isIteratableHint($hint);
42
        $hint = self::getHint($hint);
43
44
        if (!$isIteratableHint || !self::isIteratableValue($value)) {
45
            return self::validateOne($value, $hint, $nullable);
46
        }
47
48
        return self::validateMany($value, $hint, $nullable);
49
    }
50
51
    /**
52
     * @param  string $hint
53
     * @return bool
54
     */
55
    protected static function isIteratableHint($hint)
56
    {
57
        return substr($hint, -2) === '[]';
58
    }
59
60
    /**
61
     * @param  string $hint
62
     * @return string
63
     */
64
    protected static function getHint($hint)
65
    {
66
        if (self::isIteratableHint($hint)) {
67
            return substr($hint, 0, -2);
68
        }
69
70
        return $hint;
71
    }
72
73
    /**
74
     * @param  mixed $value
75
     * @return bool
76
     */
77
    protected static function isIteratableValue($value)
78
    {
79
        return is_array($value) || $value instanceof \Traversable;
80
    }
81
82
    /**
83
     * @param  mixed     $value
84
     * @param  string    $hint
85
     * @param  bool|null $nullable
86
     * @return bool
87
     */
88
    protected static function validateOne($value, $hint, $nullable)
89
    {
90
        $method = 'validate' . ucfirst($hint);
91
92
        if (method_exists(__CLASS__, $method)) {
93
            return self::$method($value, $nullable);
94
        }
95
96
        return self::validateObject($value, $hint, $nullable);
97
    }
98
99
    /**
100
     * @param  mixed     $value
101
     * @param  string    $hint
102
     * @param  bool|null $nullable
103
     * @return bool
104
     */
105
    protected static function validateMany($value, $hint, $nullable)
106
    {
107
        foreach ($value as $element) {
108
            if (!self::validateOne($element, $hint, $nullable)) {
109
                return false;
110
            }
111
        }
112
113
        return true;
114
    }
115
116
    /**
117
     * @param  mixed     $value
118
     * @param  bool|null $nullable
119
     * @return bool
120
     */
121
    public static function validateBool($value, $nullable = null)
122
    {
123
        return self::validateByCallable(
124
            'is_bool',
125
            $value,
126
            self::isNullableScalar($nullable)
127
        );
128
    }
129
130
    /**
131
     * @param  mixed     $value
132
     * @param  bool|null $nullable
133
     * @return bool
134
     */
135
    public static function validateInt($value, $nullable = null)
136
    {
137
        return self::validateByCallable(
138
            'is_int',
139
            $value,
140
            self::isNullableScalar($nullable)
141
        );
142
    }
143
144
    /**
145
     * @param  mixed     $value
146
     * @param  bool|null $nullable
147
     * @return bool
148
     */
149
    public static function validateFloat($value, $nullable = null)
150
    {
151
        return self::validateByCallable(
152
            'is_float',
153
            $value,
154
            self::isNullableScalar($nullable)
155
        );
156
    }
157
158
    /**
159
     * @param  mixed     $value
160
     * @param  bool|null $nullable
161
     * @return bool
162
     */
163
    public static function validateNumeric($value, $nullable = null)
164
    {
165
        return self::validateByCallable(
166
            'is_numeric',
167
            $value,
168
            self::isNullableScalar($nullable)
169
        );
170
    }
171
172
    /**
173
     * @param  mixed     $value
174
     * @param  bool|null $nullable
175
     * @return bool
176
     */
177
    public static function validateString($value, $nullable = null)
178
    {
179
        return self::validateByCallable(
180
            'is_string',
181
            $value,
182
            self::isNullableScalar($nullable)
183
        );
184
    }
185
186
    /**
187
     * @param  mixed     $value
188
     * @param  bool|null $nullable
189
     * @return bool
190
     */
191
    public static function validateArray($value, $nullable = null)
192
    {
193
        return self::validateByCallable(
194
            'is_array',
195
            $value,
196
            self::isNullableArrayOrObject($nullable)
197
        );
198
    }
199
200
    /**
201
     * @param  mixed     $value
202
     * @param  string    $hint
203
     * @param  bool|null $nullable
204
     * @return bool
205
     */
206
    public static function validateObject($value, $hint, $nullable = null)
207
    {
208
        return self::validateByCallable(
209
            function () use ($value, $hint) {
210
                return is_object($value) && is_a($value, $hint);
211
            },
212
            $value,
213
            self::isNullableArrayOrObject($nullable)
214
        );
215
    }
216
217
    /**
218
     * @param  bool|null $nullable
219
     * @return bool
220
     */
221
    protected static function isNullableScalar($nullable = null)
222
    {
223
        return null === $nullable || true === $nullable;
224
    }
225
226
    /**
227
     * @param  bool|null $nullable
228
     * @return bool
229
     */
230
    protected static function isNullableArrayOrObject($nullable = null)
231
    {
232
        return true === $nullable;
233
    }
234
235
    /**
236
     * @param  callable  $method
237
     * @param  string    $value
238
     * @param  bool|null $nullable
239
     * @return bool
240
     */
241
    protected static function validateByCallable($method, $value, $nullable)
242
    {
243
        if (null === $value && true === $nullable) {
244
            return true;
245
        }
246
247
        return $method($value);
248
    }
249
}
250