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