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