1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Forms;
9:
10: use Nette;
11: use Nette\Utils\Strings;
12: use Nette\Utils\Validators;
13:
14:
15: 16: 17:
18: class Validator
19: {
20: use Nette\StaticClass;
21:
22:
23: public static $messages = [
24: Form::PROTECTION => 'Your session has expired. Please return to the home page and try again.',
25: Form::EQUAL => 'Please enter %s.',
26: Form::NOT_EQUAL => 'This value should not be %s.',
27: Form::FILLED => 'This field is required.',
28: Form::BLANK => 'This field should be blank.',
29: Form::MIN_LENGTH => 'Please enter at least %d characters.',
30: Form::MAX_LENGTH => 'Please enter no more than %d characters.',
31: Form::LENGTH => 'Please enter a value between %d and %d characters long.',
32: Form::EMAIL => 'Please enter a valid email address.',
33: Form::URL => 'Please enter a valid URL.',
34: Form::INTEGER => 'Please enter a valid integer.',
35: Form::FLOAT => 'Please enter a valid number.',
36: Form::MIN => 'Please enter a value greater than or equal to %d.',
37: Form::MAX => 'Please enter a value less than or equal to %d.',
38: Form::RANGE => 'Please enter a value between %d and %d.',
39: Form::MAX_FILE_SIZE => 'The size of the uploaded file can be up to %d bytes.',
40: Form::MAX_POST_SIZE => 'The uploaded data exceeds the limit of %d bytes.',
41: Form::MIME_TYPE => 'The uploaded file is not in the expected format.',
42: Form::IMAGE => 'The uploaded file must be image in format JPEG, GIF or PNG.',
43: Controls\SelectBox::VALID => 'Please select a valid option.',
44: Controls\UploadControl::VALID => 'An error occurred during file upload.',
45: ];
46:
47:
48:
49: public static function formatMessage(Rule $rule, $withValue = true)
50: {
51: $message = $rule->message;
52: if ($message instanceof Nette\Utils\IHtmlString) {
53: return $message;
54:
55: } elseif ($message === null && is_string($rule->validator) && isset(static::$messages[$rule->validator])) {
56: $message = static::$messages[$rule->validator];
57:
58: } elseif ($message == null) {
59: trigger_error("Missing validation message for control '{$rule->control->getName()}'.", E_USER_WARNING);
60: }
61:
62: if ($translator = $rule->control->getForm()->getTranslator()) {
63: $message = $translator->translate($message, is_int($rule->arg) ? $rule->arg : null);
64: }
65:
66: $message = preg_replace_callback('#%(name|label|value|\d+\$[ds]|[ds])#', function ($m) use ($rule, $withValue) {
67: static $i = -1;
68: switch ($m[1]) {
69: case 'name': return $rule->control->getName();
70: case 'label': return $rule->control instanceof Controls\BaseControl
71: ? rtrim($rule->control->translate($rule->control->caption), ':')
72: : null;
73: case 'value': return $withValue ? $rule->control->getValue() : $m[0];
74: default:
75: $args = is_array($rule->arg) ? $rule->arg : [$rule->arg];
76: $i = (int) $m[1] ? (int) $m[1] - 1 : $i + 1;
77: return isset($args[$i]) ? ($args[$i] instanceof IControl ? ($withValue ? $args[$i]->getValue() : "%$i") : $args[$i]) : '';
78: }
79: }, $message);
80: return $message;
81: }
82:
83:
84:
85:
86:
87: 88: 89: 90:
91: public static function validateEqual(IControl $control, $arg)
92: {
93: $value = $control->getValue();
94: foreach ((is_array($value) ? $value : [$value]) as $val) {
95: foreach ((is_array($arg) ? $arg : [$arg]) as $item) {
96: if ((string) $val === (string) $item) {
97: continue 2;
98: }
99: }
100: return false;
101: }
102: return true;
103: }
104:
105:
106: 107: 108: 109:
110: public static function validateNotEqual(IControl $control, $arg)
111: {
112: return !static::validateEqual($control, $arg);
113: }
114:
115:
116: 117: 118: 119:
120: public static function validateStatic(IControl $control, $arg)
121: {
122: return $arg;
123: }
124:
125:
126: 127: 128: 129:
130: public static function validateFilled(IControl $control)
131: {
132: return $control->isFilled();
133: }
134:
135:
136: 137: 138: 139:
140: public static function validateBlank(IControl $control)
141: {
142: return !$control->isFilled();
143: }
144:
145:
146: 147: 148: 149:
150: public static function validateValid(Controls\BaseControl $control)
151: {
152: return $control->getRules()->validate();
153: }
154:
155:
156: 157: 158: 159: 160: 161:
162: public static function validateRange(IControl $control, $range)
163: {
164: $range = array_map(function ($v) {
165: return $v === '' ? null : $v;
166: }, $range);
167: return Validators::isInRange($control->getValue(), $range);
168: }
169:
170:
171: 172: 173: 174: 175: 176:
177: public static function validateMin(IControl $control, $minimum)
178: {
179: return Validators::isInRange($control->getValue(), [$minimum === '' ? null : $minimum, null]);
180: }
181:
182:
183: 184: 185: 186: 187: 188:
189: public static function validateMax(IControl $control, $maximum)
190: {
191: return Validators::isInRange($control->getValue(), [null, $maximum === '' ? null : $maximum]);
192: }
193:
194:
195: 196: 197: 198: 199: 200:
201: public static function validateLength(IControl $control, $range)
202: {
203: if (!is_array($range)) {
204: $range = [$range, $range];
205: }
206: $value = $control->getValue();
207: return Validators::isInRange(is_array($value) ? count($value) : Strings::length((string) $value), $range);
208: }
209:
210:
211: 212: 213: 214: 215: 216:
217: public static function validateMinLength(IControl $control, $length)
218: {
219: return static::validateLength($control, [$length, null]);
220: }
221:
222:
223: 224: 225: 226: 227: 228:
229: public static function validateMaxLength(IControl $control, $length)
230: {
231: return static::validateLength($control, [null, $length]);
232: }
233:
234:
235: 236: 237: 238:
239: public static function validateSubmitted(Controls\SubmitButton $control)
240: {
241: return $control->isSubmittedBy();
242: }
243:
244:
245: 246: 247: 248:
249: public static function validateEmail(IControl $control)
250: {
251: return Validators::isEmail($control->getValue());
252: }
253:
254:
255: 256: 257: 258:
259: public static function validateUrl(IControl $control)
260: {
261: if (Validators::isUrl($value = $control->getValue())) {
262: return true;
263:
264: } elseif (Validators::isUrl($value = "http://$value")) {
265: $control->setValue($value);
266: return true;
267: }
268: return false;
269: }
270:
271:
272: 273: 274: 275: 276: 277:
278: public static function validatePattern(IControl $control, $pattern, $caseInsensitive = false)
279: {
280: $value = $control->getValue() instanceof Nette\Http\FileUpload ? $control->getValue()->getName() : $control->getValue();
281: return (bool) Strings::match($value, "\x01^(?:$pattern)\\z\x01u" . ($caseInsensitive ? 'i' : ''));
282: }
283:
284:
285: public static function validatePatternCaseInsensitive(IControl $control, $pattern)
286: {
287: return self::validatePattern($control, $pattern, true);
288: }
289:
290:
291: 292: 293: 294:
295: public static function validateInteger(IControl $control)
296: {
297: if (Validators::isNumericInt($value = $control->getValue())) {
298: if (!is_float($tmp = $value * 1)) {
299: $control->setValue($tmp);
300: }
301: return true;
302: }
303: return false;
304: }
305:
306:
307: 308: 309: 310:
311: public static function validateFloat(IControl $control)
312: {
313: $value = str_replace([' ', ','], ['', '.'], $control->getValue());
314: if (Validators::isNumeric($value)) {
315: $control->setValue((float) $value);
316: return true;
317: }
318: return false;
319: }
320:
321:
322: 323: 324: 325: 326:
327: public static function validateFileSize(Controls\UploadControl $control, $limit)
328: {
329: foreach (static::toArray($control->getValue()) as $file) {
330: if ($file->getSize() > $limit || $file->getError() === UPLOAD_ERR_INI_SIZE) {
331: return false;
332: }
333: }
334: return true;
335: }
336:
337:
338: 339: 340: 341: 342: 343:
344: public static function validateMimeType(Controls\UploadControl $control, $mimeType)
345: {
346: $mimeTypes = is_array($mimeType) ? $mimeType : explode(',', $mimeType);
347: foreach (static::toArray($control->getValue()) as $file) {
348: $type = strtolower($file->getContentType());
349: if (!in_array($type, $mimeTypes, true) && !in_array(preg_replace('#/.*#', '/*', $type), $mimeTypes, true)) {
350: return false;
351: }
352: }
353: return true;
354: }
355:
356:
357: 358: 359: 360:
361: public static function validateImage(Controls\UploadControl $control)
362: {
363: foreach (static::toArray($control->getValue()) as $file) {
364: if (!$file->isImage()) {
365: return false;
366: }
367: }
368: return true;
369: }
370:
371:
372: 373: 374:
375: private static function toArray($value)
376: {
377: return $value instanceof Nette\Http\FileUpload ? [$value] : (array) $value;
378: }
379: }
380: