1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Klein (klein.php) - A fast & flexible router for PHP |
4
|
|
|
* |
5
|
|
|
* @author Chris O'Hara <[email protected]> |
6
|
|
|
* @author Trevor Suarez (Rican7) (contributor and v2 refactorer) |
7
|
|
|
* @copyright (c) Chris O'Hara |
8
|
|
|
* @link https://github.com/chriso/klein.php |
9
|
|
|
* @license MIT |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Klein; |
13
|
|
|
|
14
|
|
|
use BadMethodCallException; |
15
|
|
|
use Klein\Exceptions\ValidationException; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Validator |
19
|
|
|
*/ |
20
|
|
|
class Validator |
21
|
|
|
{ |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Class properties |
25
|
|
|
*/ |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* The available validator methods |
29
|
|
|
* |
30
|
|
|
* @type array |
31
|
|
|
*/ |
32
|
|
|
public static $methods = array(); |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* The string to validate |
36
|
|
|
* |
37
|
|
|
* @type string |
38
|
|
|
*/ |
39
|
|
|
protected $str; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* The custom exception message to throw on validation failure |
43
|
|
|
* |
44
|
|
|
* @type string |
45
|
|
|
*/ |
46
|
|
|
protected $err; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Flag for whether the default validation methods have been added or not |
50
|
|
|
* |
51
|
|
|
* @type boolean |
52
|
|
|
*/ |
53
|
|
|
protected static $defaultAdded = false; |
54
|
|
|
|
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Methods |
58
|
|
|
*/ |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Sets up the validator chain with the string and optional error message |
62
|
|
|
* |
63
|
|
|
* @param string $str The string to validate |
64
|
|
|
* @param string $err The optional custom exception message to throw on validation failure |
65
|
|
|
*/ |
66
|
|
|
public function __construct($str, $err = null) |
67
|
|
|
{ |
68
|
|
|
$this->str = $str; |
69
|
|
|
$this->err = $err; |
70
|
|
|
|
71
|
|
|
if (!static::$defaultAdded) { |
72
|
|
|
static::addDefault(); |
73
|
|
|
} |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Adds default validators on first use |
78
|
|
|
* |
79
|
|
|
* @return void |
80
|
|
|
*/ |
81
|
|
|
public static function addDefault() |
82
|
|
|
{ |
83
|
|
|
static::$methods['null'] = function ($str) { |
84
|
|
|
return $str === null || $str === ''; |
85
|
|
|
}; |
86
|
|
|
static::$methods['len'] = function ($str, $min, $max = null) { |
87
|
|
|
$len = strlen($str); |
88
|
|
|
return null === $max ? $len === $min : $len >= $min && $len <= $max; |
89
|
|
|
}; |
90
|
|
|
static::$methods['int'] = function ($str) { |
91
|
|
|
return (string)$str === ((string)(int)$str); |
92
|
|
|
}; |
93
|
|
|
static::$methods['float'] = function ($str) { |
94
|
|
|
return (string)$str === ((string)(float)$str); |
95
|
|
|
}; |
96
|
|
|
static::$methods['email'] = function ($str) { |
97
|
|
|
return filter_var($str, FILTER_VALIDATE_EMAIL) !== false; |
98
|
|
|
}; |
99
|
|
|
static::$methods['url'] = function ($str) { |
100
|
|
|
return filter_var($str, FILTER_VALIDATE_URL) !== false; |
101
|
|
|
}; |
102
|
|
|
static::$methods['ip'] = function ($str) { |
103
|
|
|
return filter_var($str, FILTER_VALIDATE_IP) !== false; |
104
|
|
|
}; |
105
|
|
|
static::$methods['remoteip'] = function ($str) { |
106
|
|
|
return filter_var($str, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false; |
107
|
|
|
}; |
108
|
|
|
static::$methods['alnum'] = function ($str) { |
109
|
|
|
return ctype_alnum($str); |
110
|
|
|
}; |
111
|
|
|
static::$methods['alpha'] = function ($str) { |
112
|
|
|
return ctype_alpha($str); |
113
|
|
|
}; |
114
|
|
|
static::$methods['contains'] = function ($str, $needle) { |
115
|
|
|
return strpos($str, $needle) !== false; |
116
|
|
|
}; |
117
|
|
|
static::$methods['regex'] = function ($str, $pattern) { |
118
|
|
|
return preg_match($pattern, $str); |
119
|
|
|
}; |
120
|
|
|
static::$methods['chars'] = function ($str, $chars) { |
121
|
|
|
return preg_match("/^[$chars]++$/i", $str); |
122
|
|
|
}; |
123
|
|
|
|
124
|
|
|
static::$defaultAdded = true; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Add a custom validator to our list of validation methods |
129
|
|
|
* |
130
|
|
|
* @param string $method The name of the validator method |
131
|
|
|
* @param callable $callback The callback to perform on validation |
132
|
|
|
* @return void |
133
|
|
|
*/ |
134
|
|
|
public static function addValidator($method, $callback) |
135
|
|
|
{ |
136
|
|
|
static::$methods[strtolower($method)] = $callback; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* Magic "__call" method |
141
|
|
|
* |
142
|
|
|
* Allows the ability to arbitrarily call a validator with an optional prefix |
143
|
|
|
* of "is" or "not" by simply calling an instance property like a callback |
144
|
|
|
* |
145
|
|
|
* @param string $method The callable method to execute |
146
|
|
|
* @param array $args The argument array to pass to our callback |
147
|
|
|
* @throws BadMethodCallException If an attempt was made to call a validator modifier that doesn't exist |
148
|
|
|
* @throws ValidationException If the validation check returns false |
149
|
|
|
* @return Validator|boolean |
150
|
|
|
*/ |
151
|
|
|
public function __call($method, $args) |
152
|
|
|
{ |
153
|
|
|
$reverse = false; |
154
|
|
|
$validator = $method; |
155
|
|
|
$method_substr = substr($method, 0, 2); |
156
|
|
|
|
157
|
|
|
if ($method_substr === 'is') { // is<$validator>() |
|
|
|
|
158
|
|
|
$validator = substr($method, 2); |
159
|
|
|
} elseif ($method_substr === 'no') { // not<$validator>() |
|
|
|
|
160
|
|
|
$validator = substr($method, 3); |
161
|
|
|
$reverse = true; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
$validator = strtolower($validator); |
165
|
|
|
|
166
|
|
|
if (!$validator || !isset(static::$methods[$validator])) { |
167
|
|
|
throw new BadMethodCallException('Unknown method '. $method .'()'); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
$validator = static::$methods[$validator]; |
171
|
|
|
array_unshift($args, $this->str); |
172
|
|
|
|
173
|
|
|
switch (count($args)) { |
174
|
|
|
case 1: |
175
|
|
|
$result = $validator($args[0]); |
176
|
|
|
break; |
177
|
|
|
case 2: |
178
|
|
|
$result = $validator($args[0], $args[1]); |
179
|
|
|
break; |
180
|
|
View Code Duplication |
case 3: |
|
|
|
|
181
|
|
|
$result = $validator($args[0], $args[1], $args[2]); |
182
|
|
|
break; |
183
|
|
View Code Duplication |
case 4: |
|
|
|
|
184
|
|
|
$result = $validator($args[0], $args[1], $args[2], $args[3]); |
185
|
|
|
break; |
186
|
|
|
default: |
187
|
|
|
$result = call_user_func_array($validator, $args); |
188
|
|
|
break; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
$result = (bool)($result ^ $reverse); |
192
|
|
|
|
193
|
|
|
if (false === $this->err) { |
194
|
|
|
return $result; |
195
|
|
|
} elseif (false === $result) { |
196
|
|
|
throw new ValidationException($this->err); |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
return $this; |
200
|
|
|
} |
201
|
|
|
} |
202
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.