1: <?php
2:
3: 4: 5: 6: 7:
8:
9:
10:
11: 12: 13: 14: 15: 16:
17: class Validators extends Object
18: {
19: protected static $validators = array(
20: 'bool' => 'is_bool',
21: 'boolean' => 'is_bool',
22: 'int' => 'is_int',
23: 'integer' => 'is_int',
24: 'float' => 'is_float',
25: 'number' => NULL,
26: 'numeric' => array(__CLASS__, 'isNumeric'),
27: 'numericint' => array(__CLASS__, 'isNumericInt'),
28: 'string' => 'is_string',
29: 'unicode' => array(__CLASS__, 'isUnicode'),
30: 'array' => 'is_array',
31: 'list' => array(__CLASS__, 'isList'),
32: 'object' => 'is_object',
33: 'resource' => 'is_resource',
34: 'scalar' => 'is_scalar',
35: 'callable' => array(__CLASS__, 'isCallable'),
36: 'null' => 'is_null',
37: 'email' => array(__CLASS__, 'isEmail'),
38: 'url' => array(__CLASS__, 'isUrl'),
39: 'none' => array(__CLASS__, 'isNone'),
40: 'pattern' => NULL,
41: 'alnum' => 'ctype_alnum',
42: 'alpha' => 'ctype_alpha',
43: 'digit' => 'ctype_digit',
44: 'lower' => 'ctype_lower',
45: 'upper' => 'ctype_upper',
46: 'space' => 'ctype_space',
47: 'xdigit' => 'ctype_xdigit',
48: );
49:
50: protected static $counters = array(
51: 'string' => 'strlen',
52: 'unicode' => array('Strings', 'length'),
53: 'array' => 'count',
54: 'list' => 'count',
55: 'alnum' => 'strlen',
56: 'alpha' => 'strlen',
57: 'digit' => 'strlen',
58: 'lower' => 'strlen',
59: 'space' => 'strlen',
60: 'upper' => 'strlen',
61: 'xdigit' => 'strlen',
62: );
63:
64:
65: 66: 67: 68: 69: 70: 71:
72: public static function assert($value, $expected, $label = 'variable')
73: {
74: if (!self::is($value, $expected)) {
75: $expected = str_replace(array('|', ':'), array(' or ', ' in range '), $expected);
76: if (is_array($value)) {
77: $type = 'array(' . count($value) . ')';
78: } elseif (is_object($value)) {
79: $type = 'object ' . get_class($value);
80: } elseif (is_string($value) && strlen($value) < 40) {
81: $type = "string '$value'";
82: } else {
83: $type = gettype($value);
84: }
85: throw new AssertionException("The $label expects to be $expected, $type given.");
86: }
87: }
88:
89:
90: 91: 92: 93: 94: 95: 96:
97: public static function assertField($arr, $field, $expected = NULL, $label = "item '%' in array")
98: {
99: self::assert($arr, 'array', 'first argument');
100: if (!array_key_exists($field, $arr)) {
101: throw new AssertionException('Missing ' . str_replace('%', $field, $label) . '.');
102:
103: } elseif ($expected) {
104: self::assert($arr[$field], $expected, str_replace('%', $field, $label));
105: }
106: }
107:
108:
109: 110: 111: 112: 113: 114:
115: public static function is($value, $expected)
116: {
117: foreach (explode('|', $expected) as $item) {
118: list($type) = $item = explode(':', $item, 2);
119: if (isset(self::$validators[$type])) {
120: if (!call_user_func(self::$validators[$type], $value)) {
121: continue;
122: }
123: } elseif ($type === 'number') {
124: if (!is_int($value) && !is_float($value)) {
125: continue;
126: }
127: } elseif ($type === 'pattern') {
128: if (preg_match('|^' . (isset($item[1]) ? $item[1] : '') . '\z|', $value)) {
129: return TRUE;
130: }
131: continue;
132: } elseif (!$value instanceof $type) {
133: continue;
134: }
135:
136: if (isset($item[1])) {
137: if (isset(self::$counters[$type])) {
138: $value = call_user_func(self::$counters[$type], $value);
139: }
140: $range = explode('..', $item[1]);
141: if (!isset($range[1])) {
142: $range[1] = $range[0];
143: }
144: if (($range[0] !== '' && $value < $range[0]) || ($range[1] !== '' && $value > $range[1])) {
145: continue;
146: }
147: }
148: return TRUE;
149: }
150: return FALSE;
151: }
152:
153:
154: 155: 156: 157:
158: public static function isNumericInt($value)
159: {
160: return is_int($value) || is_string($value) && preg_match('#^-?[0-9]+\z#', $value);
161: }
162:
163:
164: 165: 166: 167:
168: public static function isNumeric($value)
169: {
170: return is_float($value) || is_int($value) || is_string($value) && preg_match('#^-?[0-9]*[.]?[0-9]+\z#', $value);
171: }
172:
173:
174: 175: 176: 177:
178: public static function isCallable($value)
179: {
180: return $value && is_callable($value, TRUE);
181: }
182:
183:
184: 185: 186: 187: 188:
189: public static function isUnicode($value)
190: {
191: return is_string($value) && preg_match('##u', $value);
192: }
193:
194:
195: 196: 197: 198:
199: public static function isNone($value)
200: {
201: return $value == NULL;
202: }
203:
204:
205: 206: 207: 208: 209:
210: public static function isList($value)
211: {
212: return is_array($value) && (!$value || array_keys($value) === range(0, count($value) - 1));
213: }
214:
215:
216: 217: 218: 219: 220: 221:
222: public static function isInRange($value, $range)
223: {
224: return (!isset($range[0]) || $value >= $range[0]) && (!isset($range[1]) || $value <= $range[1]);
225: }
226:
227:
228: 229: 230: 231: 232:
233: public static function isEmail($value)
234: {
235: $atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]";
236: $localPart = "(?:\"(?:[ !\\x23-\\x5B\\x5D-\\x7E]*|\\\\[ -~])+\"|$atom+(?:\\.$atom+)*)";
237: $alpha = "a-z\x80-\xFF";
238: $domain = "[0-9$alpha](?:[-0-9$alpha]{0,61}[0-9$alpha])?";
239: $topDomain = "[$alpha][-0-9$alpha]{0,17}[$alpha]";
240: return (bool) preg_match("(^$localPart@(?:$domain\\.)+$topDomain\\z)i", $value);
241: }
242:
243:
244: 245: 246: 247: 248:
249: public static function isUrl($value)
250: {
251: $alpha = "a-z\x80-\xFF";
252: $domain = "[0-9$alpha](?:[-0-9$alpha]{0,61}[0-9$alpha])?";
253: $topDomain = "[$alpha][-0-9$alpha]{0,17}[$alpha]";
254: return (bool) preg_match("(^https?://(?:(?:$domain\\.)*$topDomain|\\d{1,3}\.\\d{1,3}\.\\d{1,3}\.\\d{1,3}|\[[0-9a-f:]{3,39}\])(:\\d{1,5})?(/\\S*)?\\z)i", $value);
255: }
256:
257: }
258:
259:
260: 261: 262: 263:
264: class AssertionException extends Exception
265: {
266: }
267: