1: <?php
2:
3: 4: 5: 6: 7:
8:
9:
10:
11: 12: 13: 14: 15: 16:
17: class NValidators extends NObject
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('NStrings', '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 NAssertionException("The $label expects to be $expected, $type given.");
86: }
87: }
88:
89:
90: 91: 92: 93: 94: 95: 96: 97:
98: public static function assertField($arr, $field, $expected = NULL, $label = "item '%' in array")
99: {
100: self::assert($arr, 'array', 'first argument');
101: if (!array_key_exists($field, $arr)) {
102: throw new NAssertionException('Missing ' . str_replace('%', $field, $label) . '.');
103:
104: } elseif ($expected) {
105: self::assert($arr[$field], $expected, str_replace('%', $field, $label));
106: }
107: }
108:
109:
110: 111: 112: 113: 114: 115:
116: public static function is($value, $expected)
117: {
118: foreach (explode('|', $expected) as $item) {
119: list($type) = $item = explode(':', $item, 2);
120: if (isset(self::$validators[$type])) {
121: if (!call_user_func(self::$validators[$type], $value)) {
122: continue;
123: }
124: } elseif ($type === 'number') {
125: if (!is_int($value) && !is_float($value)) {
126: continue;
127: }
128: } elseif ($type === 'pattern') {
129: if (preg_match('|^' . (isset($item[1]) ? $item[1] : '') . '\z|', $value)) {
130: return TRUE;
131: }
132: continue;
133: } elseif (!$value instanceof $type) {
134: continue;
135: }
136:
137: if (isset($item[1])) {
138: if (isset(self::$counters[$type])) {
139: $value = call_user_func(self::$counters[$type], $value);
140: }
141: $range = explode('..', $item[1]);
142: if (!isset($range[1])) {
143: $range[1] = $range[0];
144: }
145: if (($range[0] !== '' && $value < $range[0]) || ($range[1] !== '' && $value > $range[1])) {
146: continue;
147: }
148: }
149: return TRUE;
150: }
151: return FALSE;
152: }
153:
154:
155: 156: 157: 158:
159: public static function isNumericInt($value)
160: {
161: return is_int($value) || is_string($value) && preg_match('#^-?[0-9]+\z#', $value);
162: }
163:
164:
165: 166: 167: 168:
169: public static function isNumeric($value)
170: {
171: return is_float($value) || is_int($value) || is_string($value) && preg_match('#^-?[0-9]*[.]?[0-9]+\z#', $value);
172: }
173:
174:
175: 176: 177: 178:
179: public static function isCallable($value)
180: {
181: return $value && is_callable($value, TRUE);
182: }
183:
184:
185: 186: 187: 188: 189:
190: public static function isUnicode($value)
191: {
192: return is_string($value) && preg_match('##u', $value);
193: }
194:
195:
196: 197: 198: 199:
200: public static function isNone($value)
201: {
202: return $value == NULL;
203: }
204:
205:
206: 207: 208: 209: 210:
211: public static function isList($value)
212: {
213: return is_array($value) && (!$value || array_keys($value) === range(0, count($value) - 1));
214: }
215:
216:
217: 218: 219: 220: 221: 222:
223: public static function isInRange($value, $range)
224: {
225: return (!isset($range[0]) || $value >= $range[0]) && (!isset($range[1]) || $value <= $range[1]);
226: }
227:
228:
229: 230: 231: 232: 233:
234: public static function isEmail($value)
235: {
236: $atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]";
237: $localPart = "(?:\"(?:[ !\\x23-\\x5B\\x5D-\\x7E]*|\\\\[ -~])+\"|$atom+(?:\\.$atom+)*)";
238: $alpha = "a-z\x80-\xFF";
239: $domain = "[0-9$alpha](?:[-0-9$alpha]{0,61}[0-9$alpha])?";
240: $topDomain = "[$alpha][-0-9$alpha]{0,17}[$alpha]";
241: return (bool) preg_match("(^$localPart@(?:$domain\\.)+$topDomain\\z)i", $value);
242: }
243:
244:
245: 246: 247: 248: 249:
250: public static function isUrl($value)
251: {
252: $alpha = "a-z\x80-\xFF";
253: $domain = "[0-9$alpha](?:[-0-9$alpha]{0,61}[0-9$alpha])?";
254: $topDomain = "[$alpha][-0-9$alpha]{0,17}[$alpha]";
255: 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);
256: }
257:
258: }
259:
260:
261: 262: 263: 264:
265: class NAssertionException extends Exception
266: {
267: }
268: