Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • ArrayHash
  • ArrayList
  • Arrays
  • Callback
  • DateTime
  • FileSystem
  • Finder
  • Html
  • Image
  • Json
  • ObjectHelpers
  • ObjectMixin
  • Paginator
  • Random
  • Reflection
  • SafeStream
  • Strings
  • TokenIterator
  • Tokenizer
  • Validators

Interfaces

  • IHtmlString

Exceptions

  • AssertionException
  • ImageException
  • JsonException
  • RegexpException
  • TokenizerException
  • UnknownImageFileException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Utils;
  9: 
 10: use Nette;
 11: 
 12: 
 13: /**
 14:  * Validation utilities.
 15:  */
 16: class Validators
 17: {
 18:     use Nette\StaticClass;
 19: 
 20:     protected static $validators = [
 21:         'bool' => 'is_bool',
 22:         'boolean' => 'is_bool',
 23:         'int' => 'is_int',
 24:         'integer' => 'is_int',
 25:         'float' => 'is_float',
 26:         'number' => [__CLASS__, 'isNumber'],
 27:         'numeric' => [__CLASS__, 'isNumeric'],
 28:         'numericint' => [__CLASS__, 'isNumericInt'],
 29:         'string' => 'is_string',
 30:         'unicode' => [__CLASS__, 'isUnicode'],
 31:         'array' => 'is_array',
 32:         'list' => [Arrays::class, 'isList'],
 33:         'object' => 'is_object',
 34:         'resource' => 'is_resource',
 35:         'scalar' => 'is_scalar',
 36:         'callable' => [__CLASS__, 'isCallable'],
 37:         'null' => 'is_null',
 38:         'email' => [__CLASS__, 'isEmail'],
 39:         'url' => [__CLASS__, 'isUrl'],
 40:         'uri' => [__CLASS__, 'isUri'],
 41:         'none' => [__CLASS__, 'isNone'],
 42:         'type' => [__CLASS__, 'isType'],
 43:         'identifier' => [__CLASS__, 'isPhpIdentifier'],
 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:         'iterable' => [__CLASS__, 'isIterable'],
 53:     ];
 54: 
 55:     protected static $counters = [
 56:         'string' => 'strlen',
 57:         'unicode' => [Strings::class, 'length'],
 58:         'array' => 'count',
 59:         'list' => 'count',
 60:         'alnum' => 'strlen',
 61:         'alpha' => 'strlen',
 62:         'digit' => 'strlen',
 63:         'lower' => 'strlen',
 64:         'space' => 'strlen',
 65:         'upper' => 'strlen',
 66:         'xdigit' => 'strlen',
 67:     ];
 68: 
 69: 
 70:     /**
 71:      * Throws exception if a variable is of unexpected type.
 72:      * @param  mixed
 73:      * @param  string  expected types separated by pipe
 74:      * @param  string  label
 75:      * @return void
 76:      */
 77:     public static function assert($value, $expected, $label = 'variable')
 78:     {
 79:         if (!static::is($value, $expected)) {
 80:             $expected = str_replace(['|', ':'], [' 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 AssertionException("The $label expects to be $expected, $type given.");
 91:         }
 92:     }
 93: 
 94: 
 95:     /**
 96:      * Throws exception if an array field is missing or of unexpected type.
 97:      * @param  array
 98:      * @param  string  item
 99:      * @param  string  expected types separated by pipe
100:      * @param  string
101:      * @return void
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 AssertionException('Missing ' . str_replace('%', $field, $label) . '.');
108: 
109:         } elseif ($expected) {
110:             static::assert($arr[$field], $expected, str_replace('%', $field, $label));
111:         }
112:     }
113: 
114: 
115:     /**
116:      * Finds whether a variable is of expected type.
117:      * @param  mixed
118:      * @param  string  expected types separated by pipe with optional ranges
119:      * @return bool
120:      */
121:     public static function is($value, $expected)
122:     {
123:         foreach (explode('|', $expected) as $item) {
124:             if (substr($item, -2) === '[]') {
125:                 if (self::everyIs($value, substr($item, 0, -2))) {
126:                     return true;
127:                 }
128:                 continue;
129:             }
130: 
131:             list($type) = $item = explode(':', $item, 2);
132:             if (isset(static::$validators[$type])) {
133:                 if (!call_user_func(static::$validators[$type], $value)) {
134:                     continue;
135:                 }
136:             } elseif ($type === 'pattern') {
137:                 if (preg_match('|^' . (isset($item[1]) ? $item[1] : '') . '\z|', $value)) {
138:                     return true;
139:                 }
140:                 continue;
141:             } elseif (!$value instanceof $type) {
142:                 continue;
143:             }
144: 
145:             if (isset($item[1])) {
146:                 $length = $value;
147:                 if (isset(static::$counters[$type])) {
148:                     $length = call_user_func(static::$counters[$type], $value);
149:                 }
150:                 $range = explode('..', $item[1]);
151:                 if (!isset($range[1])) {
152:                     $range[1] = $range[0];
153:                 }
154:                 if (($range[0] !== '' && $length < $range[0]) || ($range[1] !== '' && $length > $range[1])) {
155:                     continue;
156:                 }
157:             }
158:             return true;
159:         }
160:         return false;
161:     }
162: 
163: 
164:     /**
165:      * Finds whether all values are of expected type.
166:      * @param  array|\Traversable
167:      * @param  string  expected types separated by pipe with optional ranges
168:      * @return bool
169:      */
170:     public static function everyIs($values, $expected)
171:     {
172:         if (!self::isIterable($values)) {
173:             return false;
174:         }
175:         foreach ($values as $value) {
176:             if (!static::is($value, $expected)) {
177:                 return false;
178:             }
179:         }
180:         return true;
181:     }
182: 
183: 
184:     /**
185:      * Finds whether a value is an integer or a float.
186:      * @return bool
187:      */
188:     public static function isNumber($value)
189:     {
190:         return is_int($value) || is_float($value);
191:     }
192: 
193: 
194:     /**
195:      * Finds whether a value is an integer.
196:      * @return bool
197:      */
198:     public static function isNumericInt($value)
199:     {
200:         return is_int($value) || is_string($value) && preg_match('#^-?[0-9]+\z#', $value);
201:     }
202: 
203: 
204:     /**
205:      * Finds whether a string is a floating point number in decimal base.
206:      * @return bool
207:      */
208:     public static function isNumeric($value)
209:     {
210:         return is_float($value) || is_int($value) || is_string($value) && preg_match('#^-?[0-9]*[.]?[0-9]+\z#', $value);
211:     }
212: 
213: 
214:     /**
215:      * Finds whether a value is a syntactically correct callback.
216:      * @return bool
217:      */
218:     public static function isCallable($value)
219:     {
220:         return $value && is_callable($value, true);
221:     }
222: 
223: 
224:     /**
225:      * Finds whether a value is an UTF-8 encoded string.
226:      * @param  string
227:      * @return bool
228:      */
229:     public static function isUnicode($value)
230:     {
231:         return is_string($value) && preg_match('##u', $value);
232:     }
233: 
234: 
235:     /**
236:      * Finds whether a value is "falsy".
237:      * @return bool
238:      */
239:     public static function isNone($value)
240:     {
241:         return $value == null; // intentionally ==
242:     }
243: 
244: 
245:     /**
246:      * Finds whether a variable is a zero-based integer indexed array.
247:      * @param  array
248:      * @return bool
249:      */
250:     public static function isList($value)
251:     {
252:         return Arrays::isList($value);
253:     }
254: 
255: 
256:     /**
257:      * Is a value in specified range?
258:      * @param  mixed
259:      * @param  array  min and max value pair
260:      * @return bool
261:      */
262:     public static function isInRange($value, $range)
263:     {
264:         if ($value === null || !(isset($range[0]) || isset($range[1]))) {
265:             return false;
266:         }
267:         $limit = isset($range[0]) ? $range[0] : $range[1];
268:         if (is_string($limit)) {
269:             $value = (string) $value;
270:         } elseif ($limit instanceof \DateTimeInterface) {
271:             if (!$value instanceof \DateTimeInterface) {
272:                 return false;
273:             }
274:         } elseif (is_numeric($value)) {
275:             $value *= 1;
276:         } else {
277:             return false;
278:         }
279:         return (!isset($range[0]) || ($value >= $range[0])) && (!isset($range[1]) || ($value <= $range[1]));
280:     }
281: 
282: 
283:     /**
284:      * Finds whether a string is a valid email address.
285:      * @param  string
286:      * @return bool
287:      */
288:     public static function isEmail($value)
289:     {
290:         $atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]"; // RFC 5322 unquoted characters in local-part
291:         $alpha = "a-z\x80-\xFF"; // superset of IDN
292:         return (bool) preg_match("(^
293:             (\"([ !#-[\\]-~]*|\\\\[ -~])+\"|$atom+(\\.$atom+)*)  # quoted or unquoted
294:             @
295:             ([0-9$alpha]([-0-9$alpha]{0,61}[0-9$alpha])?\\.)+    # domain - RFC 1034
296:             [$alpha]([-0-9$alpha]{0,17}[$alpha])?                # top domain
297:         \\z)ix", $value);
298:     }
299: 
300: 
301:     /**
302:      * Finds whether a string is a valid http(s) URL.
303:      * @param  string
304:      * @return bool
305:      */
306:     public static function isUrl($value)
307:     {
308:         $alpha = "a-z\x80-\xFF";
309:         return (bool) preg_match("(^
310:             https?://(
311:                 (([-_0-9$alpha]+\\.)*                       # subdomain
312:                     [0-9$alpha]([-0-9$alpha]{0,61}[0-9$alpha])?\\.)?  # domain
313:                     [$alpha]([-0-9$alpha]{0,17}[$alpha])?   # top domain
314:                 |\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}  # IPv4
315:                 |\[[0-9a-f:]{3,39}\]                        # IPv6
316:             )(:\\d{1,5})?                                   # port
317:             (/\\S*)?                                        # path
318:         \\z)ix", $value);
319:     }
320: 
321: 
322:     /**
323:      * Finds whether a string is a valid URI according to RFC 1738.
324:      * @param  string
325:      * @return bool
326:      */
327:     public static function isUri($value)
328:     {
329:         return (bool) preg_match('#^[a-z\d+\.-]+:\S+\z#i', $value);
330:     }
331: 
332: 
333:     /**
334:      * Checks whether the input is a class, interface or trait.
335:      * @param  string
336:      * @return bool
337:      */
338:     public static function isType($type)
339:     {
340:         return class_exists($type) || interface_exists($type) || trait_exists($type);
341:     }
342: 
343: 
344:     /**
345:      * Checks whether the input is a valid PHP identifier.
346:      * @return bool
347:      */
348:     public static function isPhpIdentifier($value)
349:     {
350:         return is_string($value) && preg_match('#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\z#', $value);
351:     }
352: 
353: 
354:     /**
355:      * Returns true if value is iterable (array or instance of Traversable).
356:      * @return bool
357:      */
358:     private static function isIterable($value)
359:     {
360:         return is_array($value) || $value instanceof \Traversable;
361:     }
362: }
363: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0