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 ? $rule->control->translate($rule->control->caption) : null;
71: case 'value': return $withValue ? $rule->control->getValue() : $m[0];
72: default:
73: $args = is_array($rule->arg) ? $rule->arg : [$rule->arg];
74: $i = (int) $m[1] ? (int) $m[1] - 1 : $i + 1;
75: return isset($args[$i]) ? ($args[$i] instanceof IControl ? ($withValue ? $args[$i]->getValue() : "%$i") : $args[$i]) : '';
76: }
77: }, $message);
78: return $message;
79: }
80:
81:
82:
83:
84:
85: 86: 87: 88:
89: public static function validateEqual(IControl $control, $arg)
90: {
91: $value = $control->getValue();
92: foreach ((is_array($value) ? $value : [$value]) as $val) {
93: foreach ((is_array($arg) ? $arg : [$arg]) as $item) {
94: if ((string) $val === (string) $item) {
95: continue 2;
96: }
97: }
98: return false;
99: }
100: return true;
101: }
102:
103:
104: 105: 106: 107:
108: public static function validateNotEqual(IControl $control, $arg)
109: {
110: return !static::validateEqual($control, $arg);
111: }
112:
113:
114: 115: 116: 117:
118: public static function validateStatic(IControl $control, $arg)
119: {
120: return $arg;
121: }
122:
123:
124: 125: 126: 127:
128: public static function validateFilled(IControl $control)
129: {
130: return $control->isFilled();
131: }
132:
133:
134: 135: 136: 137:
138: public static function validateBlank(IControl $control)
139: {
140: return !$control->isFilled();
141: }
142:
143:
144: 145: 146: 147:
148: public static function validateValid(Controls\BaseControl $control)
149: {
150: return $control->getRules()->validate();
151: }
152:
153:
154: 155: 156: 157: 158: 159:
160: public static function validateRange(IControl $control, $range)
161: {
162: $range = array_map(function ($v) {
163: return $v === '' ? null : $v;
164: }, $range);
165: return Validators::isInRange($control->getValue(), $range);
166: }
167:
168:
169: 170: 171: 172: 173: 174:
175: public static function validateMin(IControl $control, $minimum)
176: {
177: return Validators::isInRange($control->getValue(), [$minimum === '' ? null : $minimum, null]);
178: }
179:
180:
181: 182: 183: 184: 185: 186:
187: public static function validateMax(IControl $control, $maximum)
188: {
189: return Validators::isInRange($control->getValue(), [null, $maximum === '' ? null : $maximum]);
190: }
191:
192:
193: 194: 195: 196: 197: 198:
199: public static function validateLength(IControl $control, $range)
200: {
201: if (!is_array($range)) {
202: $range = [$range, $range];
203: }
204: $value = $control->getValue();
205: return Validators::isInRange(is_array($value) ? count($value) : Strings::length((string) $value), $range);
206: }
207:
208:
209: 210: 211: 212: 213: 214:
215: public static function validateMinLength(IControl $control, $length)
216: {
217: return static::validateLength($control, [$length, null]);
218: }
219:
220:
221: 222: 223: 224: 225: 226:
227: public static function validateMaxLength(IControl $control, $length)
228: {
229: return static::validateLength($control, [null, $length]);
230: }
231:
232:
233: 234: 235: 236:
237: public static function validateSubmitted(Controls\SubmitButton $control)
238: {
239: return $control->isSubmittedBy();
240: }
241:
242:
243: 244: 245: 246:
247: public static function validateEmail(IControl $control)
248: {
249: return Validators::isEmail($control->getValue());
250: }
251:
252:
253: 254: 255: 256:
257: public static function validateUrl(IControl $control)
258: {
259: if (Validators::isUrl($value = $control->getValue())) {
260: return true;
261:
262: } elseif (Validators::isUrl($value = "http://$value")) {
263: $control->setValue($value);
264: return true;
265: }
266: return false;
267: }
268:
269:
270: 271: 272: 273: 274:
275: public static function validatePattern(IControl $control, $pattern)
276: {
277: return (bool) Strings::match($control->getValue(), "\x01^(?:$pattern)\\z\x01u");
278: }
279:
280:
281: 282: 283: 284:
285: public static function validateInteger(IControl $control)
286: {
287: if (Validators::isNumericInt($value = $control->getValue())) {
288: if (!is_float($tmp = $value * 1)) {
289: $control->setValue($tmp);
290: }
291: return true;
292: }
293: return false;
294: }
295:
296:
297: 298: 299: 300:
301: public static function validateFloat(IControl $control)
302: {
303: $value = str_replace([' ', ','], ['', '.'], $control->getValue());
304: if (Validators::isNumeric($value)) {
305: $control->setValue((float) $value);
306: return true;
307: }
308: return false;
309: }
310:
311:
312: 313: 314: 315: 316:
317: public static function validateFileSize(Controls\UploadControl $control, $limit)
318: {
319: foreach (static::toArray($control->getValue()) as $file) {
320: if ($file->getSize() > $limit || $file->getError() === UPLOAD_ERR_INI_SIZE) {
321: return false;
322: }
323: }
324: return true;
325: }
326:
327:
328: 329: 330: 331: 332: 333:
334: public static function validateMimeType(Controls\UploadControl $control, $mimeType)
335: {
336: $mimeTypes = is_array($mimeType) ? $mimeType : explode(',', $mimeType);
337: foreach (static::toArray($control->getValue()) as $file) {
338: $type = strtolower($file->getContentType());
339: if (!in_array($type, $mimeTypes, true) && !in_array(preg_replace('#/.*#', '/*', $type), $mimeTypes, true)) {
340: return false;
341: }
342: }
343: return true;
344: }
345:
346:
347: 348: 349: 350:
351: public static function validateImage(Controls\UploadControl $control)
352: {
353: foreach (static::toArray($control->getValue()) as $file) {
354: if (!$file->isImage()) {
355: return false;
356: }
357: }
358: return true;
359: }
360:
361:
362: 363: 364:
365: private static function toArray($value)
366: {
367: return $value instanceof Nette\Http\FileUpload ? [$value] : (array) $value;
368: }
369: }
370: