1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * For full copyright and license information, please see the LICENSE.txt
8: * Redistributions of files must retain the above copyright notice.
9: *
10: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 2.2.0
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\Validation;
16:
17: use ArrayAccess;
18: use ArrayIterator;
19: use Countable;
20: use InvalidArgumentException;
21: use IteratorAggregate;
22:
23: /**
24: * Validator object encapsulates all methods related to data validations for a model
25: * It also provides an API to dynamically change validation rules for each model field.
26: *
27: * Implements ArrayAccess to easily modify rules in the set
28: *
29: * @link https://book.cakephp.org/3.0/en/core-libraries/validation.html
30: */
31: class Validator implements ArrayAccess, IteratorAggregate, Countable
32: {
33: /**
34: * Used to flag nested rules created with addNested() and addNestedMany()
35: *
36: * @var string
37: */
38: const NESTED = '_nested';
39:
40: /**
41: * A flag for allowEmptyFor()
42: *
43: * When an empty string is given, it will be recognized as empty.
44: *
45: * @var int
46: */
47: const EMPTY_STRING = 1;
48:
49: /**
50: * A flag for allowEmptyFor()
51: *
52: * When an empty array is given, it will be recognized as empty.
53: *
54: * @var int
55: */
56: const EMPTY_ARRAY = 2;
57:
58: /**
59: * A flag for allowEmptyFor()
60: *
61: * When an array is given, if it has at least the `name`, `type`, `tmp_name` and `error` keys,
62: * and the value of `error` is equal to `UPLOAD_ERR_NO_FILE`, the value will be recognized as
63: * empty.
64: *
65: * @var int
66: */
67: const EMPTY_FILE = 4;
68:
69: /**
70: * A flag for allowEmptyFor()
71: *
72: * When an array is given, if it contains the `year` key, and only empty strings
73: * or null values, it will be recognized as empty.
74: *
75: * @var int
76: */
77: const EMPTY_DATE = 8;
78:
79: /**
80: * A flag for allowEmptyFor()
81: *
82: * When an array is given, if it contains the `hour` key, and only empty strings
83: * or null values, it will be recognized as empty.
84: *
85: * @var int
86: */
87: const EMPTY_TIME = 16;
88:
89: /**
90: * A combination of the all EMPTY_* flags
91: *
92: * @var int
93: */
94: const EMPTY_ALL = self::EMPTY_STRING | self::EMPTY_ARRAY | self::EMPTY_FILE | self::EMPTY_DATE | self::EMPTY_TIME;
95:
96: /**
97: * Holds the ValidationSet objects array
98: *
99: * @var array
100: */
101: protected $_fields = [];
102:
103: /**
104: * An associative array of objects or classes containing methods
105: * used for validation
106: *
107: * @var array
108: */
109: protected $_providers = [];
110:
111: /**
112: * An associative array of objects or classes used as a default provider list
113: *
114: * @var array
115: */
116: protected static $_defaultProviders = [];
117:
118: /**
119: * Contains the validation messages associated with checking the presence
120: * for each corresponding field.
121: *
122: * @var array
123: */
124: protected $_presenceMessages = [];
125:
126: /**
127: * Whether or not to use I18n functions for translating default error messages
128: *
129: * @var bool
130: */
131: protected $_useI18n = false;
132:
133: /**
134: * Contains the validation messages associated with checking the emptiness
135: * for each corresponding field.
136: *
137: * @var array
138: */
139: protected $_allowEmptyMessages = [];
140:
141: /**
142: * Contains the flags which specify what is empty for each corresponding field.
143: *
144: * @var array
145: */
146: protected $_allowEmptyFlags = [];
147:
148: /**
149: * Constructor
150: *
151: */
152: public function __construct()
153: {
154: $this->_useI18n = function_exists('__d');
155: $this->_providers = self::$_defaultProviders;
156: }
157:
158: /**
159: * Returns an array of fields that have failed validation. On the current model. This method will
160: * actually run validation rules over data, not just return the messages.
161: *
162: * @param array $data The data to be checked for errors
163: * @param bool $newRecord whether the data to be validated is new or to be updated.
164: * @return array Array of invalid fields
165: */
166: public function errors(array $data, $newRecord = true)
167: {
168: $errors = [];
169:
170: foreach ($this->_fields as $name => $field) {
171: $keyPresent = array_key_exists($name, $data);
172:
173: $providers = $this->_providers;
174: $context = compact('data', 'newRecord', 'field', 'providers');
175:
176: if (!$keyPresent && !$this->_checkPresence($field, $context)) {
177: $errors[$name]['_required'] = $this->getRequiredMessage($name);
178: continue;
179: }
180: if (!$keyPresent) {
181: continue;
182: }
183:
184: $canBeEmpty = $this->_canBeEmpty($field, $context);
185:
186: $flags = static::EMPTY_ALL;
187: if (isset($this->_allowEmptyFlags[$name])) {
188: $flags = $this->_allowEmptyFlags[$name];
189: }
190:
191: $isEmpty = $this->isEmpty($data[$name], $flags);
192:
193: if (!$canBeEmpty && $isEmpty) {
194: $errors[$name]['_empty'] = $this->getNotEmptyMessage($name);
195: continue;
196: }
197:
198: if ($isEmpty) {
199: continue;
200: }
201:
202: $result = $this->_processRules($name, $field, $data, $newRecord);
203: if ($result) {
204: $errors[$name] = $result;
205: }
206: }
207:
208: return $errors;
209: }
210:
211: /**
212: * Returns a ValidationSet object containing all validation rules for a field, if
213: * passed a ValidationSet as second argument, it will replace any other rule set defined
214: * before
215: *
216: * @param string $name [optional] The fieldname to fetch.
217: * @param \Cake\Validation\ValidationSet|null $set The set of rules for field
218: * @return \Cake\Validation\ValidationSet
219: */
220: public function field($name, ValidationSet $set = null)
221: {
222: if (empty($this->_fields[$name])) {
223: $set = $set ?: new ValidationSet();
224: $this->_fields[$name] = $set;
225: }
226:
227: return $this->_fields[$name];
228: }
229:
230: /**
231: * Check whether or not a validator contains any rules for the given field.
232: *
233: * @param string $name The field name to check.
234: * @return bool
235: */
236: public function hasField($name)
237: {
238: return isset($this->_fields[$name]);
239: }
240:
241: /**
242: * Associates an object to a name so it can be used as a provider. Providers are
243: * objects or class names that can contain methods used during validation of for
244: * deciding whether a validation rule can be applied. All validation methods,
245: * when called will receive the full list of providers stored in this validator.
246: *
247: * @param string $name The name under which the provider should be set.
248: * @param object|string $object Provider object or class name.
249: * @return $this
250: */
251: public function setProvider($name, $object)
252: {
253: $this->_providers[$name] = $object;
254:
255: return $this;
256: }
257:
258: /**
259: * Returns the provider stored under that name if it exists.
260: *
261: * @param string $name The name under which the provider should be set.
262: * @return object|string|null
263: * @throws \ReflectionException
264: */
265: public function getProvider($name)
266: {
267: if (isset($this->_providers[$name])) {
268: return $this->_providers[$name];
269: }
270: if ($name !== 'default') {
271: return null;
272: }
273:
274: $this->_providers[$name] = new RulesProvider();
275:
276: return $this->_providers[$name];
277: }
278:
279: /**
280: * Returns the default provider stored under that name if it exists.
281: *
282: * @param string $name The name under which the provider should be retrieved.
283: * @return object|string|null
284: */
285: public static function getDefaultProvider($name)
286: {
287: if (!isset(self::$_defaultProviders[$name])) {
288: return null;
289: }
290:
291: return self::$_defaultProviders[$name];
292: }
293:
294: /**
295: * Associates an object to a name so it can be used as a default provider.
296: *
297: * @param string $name The name under which the provider should be set.
298: * @param object|string $object Provider object or class name.
299: * @return void
300: */
301: public static function addDefaultProvider($name, $object)
302: {
303: self::$_defaultProviders[$name] = $object;
304: }
305:
306: /**
307: * Get the list of default providers.
308: *
309: * @return string[]
310: */
311: public static function getDefaultProviders()
312: {
313: return array_keys(self::$_defaultProviders);
314: }
315:
316: /**
317: * Associates an object to a name so it can be used as a provider. Providers are
318: * objects or class names that can contain methods used during validation of for
319: * deciding whether a validation rule can be applied. All validation methods,
320: * when called will receive the full list of providers stored in this validator.
321: *
322: * If called with no arguments, it will return the provider stored under that name if
323: * it exists, otherwise it returns this instance of chaining.
324: *
325: * @deprecated 3.4.0 Use setProvider()/getProvider() instead.
326: * @param string $name The name under which the provider should be set.
327: * @param string|object|null $object Provider object or class name.
328: * @return $this|object|string|null
329: */
330: public function provider($name, $object = null)
331: {
332: deprecationWarning(
333: 'Validator::provider() is deprecated. ' .
334: 'Use Validator::setProvider()/getProvider() instead.'
335: );
336: if ($object !== null) {
337: return $this->setProvider($name, $object);
338: }
339:
340: return $this->getProvider($name);
341: }
342:
343: /**
344: * Get the list of providers in this validator.
345: *
346: * @return string[]
347: */
348: public function providers()
349: {
350: return array_keys($this->_providers);
351: }
352:
353: /**
354: * Returns whether a rule set is defined for a field or not
355: *
356: * @param string $field name of the field to check
357: * @return bool
358: */
359: public function offsetExists($field)
360: {
361: return isset($this->_fields[$field]);
362: }
363:
364: /**
365: * Returns the rule set for a field
366: *
367: * @param string $field name of the field to check
368: * @return \Cake\Validation\ValidationSet
369: */
370: public function offsetGet($field)
371: {
372: return $this->field($field);
373: }
374:
375: /**
376: * Sets the rule set for a field
377: *
378: * @param string $field name of the field to set
379: * @param array|\Cake\Validation\ValidationSet $rules set of rules to apply to field
380: * @return void
381: */
382: public function offsetSet($field, $rules)
383: {
384: if (!$rules instanceof ValidationSet) {
385: $set = new ValidationSet();
386: foreach ((array)$rules as $name => $rule) {
387: $set->add($name, $rule);
388: }
389: }
390: $this->_fields[$field] = $rules;
391: }
392:
393: /**
394: * Unsets the rule set for a field
395: *
396: * @param string $field name of the field to unset
397: * @return void
398: */
399: public function offsetUnset($field)
400: {
401: unset($this->_fields[$field]);
402: }
403:
404: /**
405: * Returns an iterator for each of the fields to be validated
406: *
407: * @return \ArrayIterator
408: */
409: public function getIterator()
410: {
411: return new ArrayIterator($this->_fields);
412: }
413:
414: /**
415: * Returns the number of fields having validation rules
416: *
417: * @return int
418: */
419: public function count()
420: {
421: return count($this->_fields);
422: }
423:
424: /**
425: * Adds a new rule to a field's rule set. If second argument is an array
426: * then rules list for the field will be replaced with second argument and
427: * third argument will be ignored.
428: *
429: * ### Example:
430: *
431: * ```
432: * $validator
433: * ->add('title', 'required', ['rule' => 'notBlank'])
434: * ->add('user_id', 'valid', ['rule' => 'numeric', 'message' => 'Invalid User'])
435: *
436: * $validator->add('password', [
437: * 'size' => ['rule' => ['lengthBetween', 8, 20]],
438: * 'hasSpecialCharacter' => ['rule' => 'validateSpecialchar', 'message' => 'not valid']
439: * ]);
440: * ```
441: *
442: * @param string $field The name of the field from which the rule will be added
443: * @param array|string $name The alias for a single rule or multiple rules array
444: * @param array|\Cake\Validation\ValidationRule $rule the rule to add
445: * @return $this
446: */
447: public function add($field, $name, $rule = [])
448: {
449: $validationSet = $this->field($field);
450:
451: if (!is_array($name)) {
452: $rules = [$name => $rule];
453: } else {
454: $rules = $name;
455: }
456:
457: foreach ($rules as $name => $rule) {
458: if (is_array($rule)) {
459: $rule += ['rule' => $name];
460: }
461: $validationSet->add($name, $rule);
462: }
463:
464: return $this;
465: }
466:
467: /**
468: * Adds a nested validator.
469: *
470: * Nesting validators allows you to define validators for array
471: * types. For example, nested validators are ideal when you want to validate a
472: * sub-document, or complex array type.
473: *
474: * This method assumes that the sub-document has a 1:1 relationship with the parent.
475: *
476: * The providers of the parent validator will be synced into the nested validator, when
477: * errors are checked. This ensures that any validation rule providers connected
478: * in the parent will have the same values in the nested validator when rules are evaluated.
479: *
480: * @param string $field The root field for the nested validator.
481: * @param \Cake\Validation\Validator $validator The nested validator.
482: * @param string|null $message The error message when the rule fails.
483: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
484: * true when the validation rule should be applied.
485: * @return $this
486: */
487: public function addNested($field, Validator $validator, $message = null, $when = null)
488: {
489: $extra = array_filter(['message' => $message, 'on' => $when]);
490:
491: $validationSet = $this->field($field);
492: $validationSet->add(static::NESTED, $extra + ['rule' => function ($value, $context) use ($validator, $message) {
493: if (!is_array($value)) {
494: return false;
495: }
496: foreach ($this->providers() as $provider) {
497: $validator->setProvider($provider, $this->getProvider($provider));
498: }
499: $errors = $validator->errors($value, $context['newRecord']);
500:
501: $message = $message ? [static::NESTED => $message] : [];
502:
503: return empty($errors) ? true : $errors + $message;
504: }]);
505:
506: return $this;
507: }
508:
509: /**
510: * Adds a nested validator.
511: *
512: * Nesting validators allows you to define validators for array
513: * types. For example, nested validators are ideal when you want to validate many
514: * similar sub-documents or complex array types.
515: *
516: * This method assumes that the sub-document has a 1:N relationship with the parent.
517: *
518: * The providers of the parent validator will be synced into the nested validator, when
519: * errors are checked. This ensures that any validation rule providers connected
520: * in the parent will have the same values in the nested validator when rules are evaluated.
521: *
522: * @param string $field The root field for the nested validator.
523: * @param \Cake\Validation\Validator $validator The nested validator.
524: * @param string|null $message The error message when the rule fails.
525: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
526: * true when the validation rule should be applied.
527: * @return $this
528: */
529: public function addNestedMany($field, Validator $validator, $message = null, $when = null)
530: {
531: $extra = array_filter(['message' => $message, 'on' => $when]);
532:
533: $validationSet = $this->field($field);
534: $validationSet->add(static::NESTED, $extra + ['rule' => function ($value, $context) use ($validator, $message) {
535: if (!is_array($value)) {
536: return false;
537: }
538: foreach ($this->providers() as $provider) {
539: $validator->setProvider($provider, $this->getProvider($provider));
540: }
541: $errors = [];
542: foreach ($value as $i => $row) {
543: if (!is_array($row)) {
544: return false;
545: }
546: $check = $validator->errors($row, $context['newRecord']);
547: if (!empty($check)) {
548: $errors[$i] = $check;
549: }
550: }
551:
552: $message = $message ? [static::NESTED => $message] : [];
553:
554: return empty($errors) ? true : $errors + $message;
555: }]);
556:
557: return $this;
558: }
559:
560: /**
561: * Removes a rule from the set by its name
562: *
563: * ### Example:
564: *
565: * ```
566: * $validator
567: * ->remove('title', 'required')
568: * ->remove('user_id')
569: * ```
570: *
571: * @param string $field The name of the field from which the rule will be removed
572: * @param string|null $rule the name of the rule to be removed
573: * @return $this
574: */
575: public function remove($field, $rule = null)
576: {
577: if ($rule === null) {
578: unset($this->_fields[$field]);
579: } else {
580: $this->field($field)->remove($rule);
581: }
582:
583: return $this;
584: }
585:
586: /**
587: * Sets whether a field is required to be present in data array.
588: * You can also pass array. Using an array will let you provide the following
589: * keys:
590: *
591: * - `mode` individual mode for field
592: * - `message` individual error message for field
593: *
594: * You can also set mode and message for all passed fields, the individual
595: * setting takes precedence over group settings.
596: *
597: * @param string|array $field the name of the field or list of fields.
598: * @param bool|string|callable $mode Valid values are true, false, 'create', 'update'.
599: * If a callable is passed then the field will be required only when the callback
600: * returns true.
601: * @param string|null $message The message to show if the field presence validation fails.
602: * @return $this
603: */
604: public function requirePresence($field, $mode = true, $message = null)
605: {
606: $defaults = [
607: 'mode' => $mode,
608: 'message' => $message
609: ];
610:
611: if (!is_array($field)) {
612: $field = $this->_convertValidatorToArray($field, $defaults);
613: }
614:
615: foreach ($field as $fieldName => $setting) {
616: $settings = $this->_convertValidatorToArray($fieldName, $defaults, $setting);
617: $fieldName = current(array_keys($settings));
618:
619: $this->field($fieldName)->requirePresence($settings[$fieldName]['mode']);
620: if ($settings[$fieldName]['message']) {
621: $this->_presenceMessages[$fieldName] = $settings[$fieldName]['message'];
622: }
623: }
624:
625: return $this;
626: }
627:
628: /**
629: * Allows a field to be empty. You can also pass array.
630: * Using an array will let you provide the following keys:
631: *
632: * - `when` individual when condition for field
633: * - 'message' individual message for field
634: *
635: * You can also set when and message for all passed fields, the individual setting
636: * takes precedence over group settings.
637: *
638: * This is the opposite of notEmpty() which requires a field to not be empty.
639: * By using $mode equal to 'create' or 'update', you can allow fields to be empty
640: * when records are first created, or when they are updated.
641: *
642: * ### Example:
643: *
644: * ```
645: * // Email can be empty
646: * $validator->allowEmpty('email');
647: *
648: * // Email can be empty on create
649: * $validator->allowEmpty('email', 'create');
650: *
651: * // Email can be empty on update
652: * $validator->allowEmpty('email', 'update');
653: *
654: * // Email and subject can be empty on update
655: * $validator->allowEmpty(['email', 'subject'], 'update');
656: *
657: * // Email can be always empty, subject and content can be empty on update.
658: * $validator->allowEmpty(
659: * [
660: * 'email' => [
661: * 'when' => true
662: * ],
663: * 'content' => [
664: * 'message' => 'Content cannot be empty'
665: * ],
666: * 'subject'
667: * ],
668: * 'update'
669: * );
670: * ```
671: *
672: * It is possible to conditionally allow emptiness on a field by passing a callback
673: * as a second argument. The callback will receive the validation context array as
674: * argument:
675: *
676: * ```
677: * $validator->allowEmpty('email', function ($context) {
678: * return !$context['newRecord'] || $context['data']['role'] === 'admin';
679: * });
680: * ```
681: *
682: * This method will correctly detect empty file uploads and date/time/datetime fields.
683: *
684: * Because this and `notEmpty()` modify the same internal state, the last
685: * method called will take precedence.
686: *
687: * @deprecated 3.7.0 Use allowEmptyString(), allowEmptyArray(), allowEmptyFile(),
688: * allowEmptyDate(), allowEmptyTime() or allowEmptyDateTime() instead.
689: * @param string|array $field the name of the field or a list of fields
690: * @param bool|string|callable $when Indicates when the field is allowed to be empty
691: * Valid values are true (always), 'create', 'update'. If a callable is passed then
692: * the field will allowed to be empty only when the callback returns true.
693: * @param string|null $message The message to show if the field is not
694: * @return $this
695: */
696: public function allowEmpty($field, $when = true, $message = null)
697: {
698: $defaults = [
699: 'when' => $when,
700: 'message' => $message,
701: ];
702: if (!is_array($field)) {
703: $field = $this->_convertValidatorToArray($field, $defaults);
704: }
705:
706: foreach ($field as $fieldName => $setting) {
707: $settings = $this->_convertValidatorToArray($fieldName, $defaults, $setting);
708: $fieldName = array_keys($settings)[0];
709: $this->allowEmptyFor($fieldName, null, $settings[$fieldName]['when'], $settings[$fieldName]['message']);
710: }
711:
712: return $this;
713: }
714:
715: /**
716: * Low-level method to indicate that a field can be empty.
717: *
718: * This method should generally not be used and instead you should
719: * use:
720: *
721: * - `allowEmptyString()`
722: * - `allowEmptyArray()`
723: * - `allowEmptyFile()`
724: * - `allowEmptyDate()`
725: * - `allowEmptyDatetime()`
726: * - `allowEmptyTime()`
727: *
728: * Should be used as their APIs are simpler to operate and read.
729: *
730: * You can also set flags, when and message for all passed fields, the individual
731: * setting takes precedence over group settings.
732: *
733: * ### Example:
734: *
735: * ```
736: * // Email can be empty
737: * $validator->allowEmptyFor('email', Validator::EMPTY_STRING);
738: *
739: * // Email can be empty on create
740: * $validator->allowEmptyFor('email', Validator::EMPTY_STRING, 'create');
741: *
742: * // Email can be empty on update
743: * $validator->allowEmptyFor('email', Validator::EMPTY_STRING, 'update');
744: * ```
745: *
746: * It is possible to conditionally allow emptiness on a field by passing a callback
747: * as a second argument. The callback will receive the validation context array as
748: * argument:
749: *
750: * ```
751: * $validator->allowEmpty('email', Validator::EMPTY_STRING, function ($context) {
752: * return !$context['newRecord'] || $context['data']['role'] === 'admin';
753: * });
754: * ```
755: *
756: * If you want to allow other kind of empty data on a field, you need to pass other
757: * flags:
758: *
759: * ```
760: * $validator->allowEmptyFor('photo', Validator::EMPTY_FILE);
761: * $validator->allowEmptyFor('published', Validator::EMPTY_STRING | Validator::EMPTY_DATE | Validator::EMPTY_TIME);
762: * $validator->allowEmptyFor('items', Validator::EMPTY_STRING | Validator::EMPTY_ARRAY);
763: * ```
764: *
765: * You can also use convenience wrappers of this method. The following calls are the
766: * same as above:
767: *
768: * ```
769: * $validator->allowEmptyFile('photo');
770: * $validator->allowEmptyDateTime('published');
771: * $validator->allowEmptyArray('items');
772: * ```
773: *
774: * @param string $field The name of the field.
775: * @param int|null $flags A bitmask of EMPTY_* flags which specify what is empty
776: * @param bool|string|callable $when Indicates when the field is allowed to be empty
777: * Valid values are true, false, 'create', 'update'. If a callable is passed then
778: * the field will allowed to be empty only when the callback returns true.
779: * @param string|null $message The message to show if the field is not
780: * @since 3.7.0
781: * @return $this
782: */
783: public function allowEmptyFor($field, $flags, $when = true, $message = null)
784: {
785: $this->field($field)->allowEmpty($when);
786: if ($message) {
787: $this->_allowEmptyMessages[$field] = $message;
788: }
789: if ($flags !== null) {
790: $this->_allowEmptyFlags[$field] = $flags;
791: }
792:
793: return $this;
794: }
795:
796: /**
797: * Compatibility shim for the allowEmpty* methods that enable
798: * us to support both the `$when, $message` signature (deprecated)
799: * and the `$message, $when` format which is preferred.
800: *
801: * A deprecation warning will be emitted when a deprecated form
802: * is used.
803: *
804: * @param mixed $first The message or when to be sorted.
805: * @param mixed $second The message or when to be sorted.
806: * @param string $method The called method
807: * @return array A list of [$message, $when]
808: */
809: protected function sortMessageAndWhen($first, $second, $method)
810: {
811: // Called with `$message, $when`. No order change necessary
812: if ((
813: in_array($second, [true, false, 'create', 'update'], true) ||
814: is_callable($second)
815: ) && (
816: is_string($first) || $first === null
817: ) && (
818: $first !== 'create' && $first !== 'update'
819: )
820: ) {
821: return [$first, $second];
822: }
823: deprecationWarning(
824: "You are using a deprecated argument order for ${method}. " .
825: "You should reverse the order of your `when` and `message` arguments " .
826: "so that they are `message, when`."
827: );
828:
829: // Called without the second argument.
830: if (is_bool($second)) {
831: $second = null;
832: }
833:
834: // Called with `$when, $message`. Reverse the
835: // order to match the expected return value.
836: return [$second, $first];
837: }
838:
839: /**
840: * Allows a field to be an empty string.
841: *
842: * This method is equivalent to calling allowEmptyFor() with EMPTY_STRING flag.
843: *
844: * @param string $field The name of the field.
845: * @param string|null $message The message to show if the field is not
846: * @param bool|string|callable $when Indicates when the field is allowed to be empty
847: * Valid values are true, false, 'create', 'update'. If a callable is passed then
848: * the field will allowed to be empty only when the callback returns true.
849: * @return $this
850: * @since 3.7.0
851: * @see \Cake\Validation\Validator::allowEmptyFor() For detail usage
852: */
853: public function allowEmptyString($field, $message = null, $when = true)
854: {
855: list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
856:
857: return $this->allowEmptyFor($field, self::EMPTY_STRING, $when, $message);
858: }
859:
860: /**
861: * Requires a field to be not be an empty string.
862: *
863: * Opposite to allowEmptyString()
864: *
865: * @param string $field The name of the field.
866: * @param string|null $message The message to show if the field is empty.
867: * @param bool|string|callable $when Indicates when the field is not allowed
868: * to be empty. Valid values are false (never), 'create', 'update'. If a
869: * callable is passed then the field will be required to be not empty when
870: * the callback returns true.
871: * @return $this
872: * @see \Cake\Validation\Validator::allowEmptyString()
873: * @since 3.8.0
874: */
875: public function notEmptyString($field, $message = null, $when = false)
876: {
877: $when = $this->invertWhenClause($when);
878:
879: return $this->allowEmptyFor($field, self::EMPTY_STRING, $when, $message);
880: }
881:
882: /**
883: * Allows a field to be an empty array.
884: *
885: * This method is equivalent to calling allowEmptyFor() with EMPTY_STRING +
886: * EMPTY_ARRAY flags.
887: *
888: * @param string $field The name of the field.
889: * @param string|null $message The message to show if the field is not
890: * @param bool|string|callable $when Indicates when the field is allowed to be empty
891: * Valid values are true, false, 'create', 'update'. If a callable is passed then
892: * the field will allowed to be empty only when the callback returns true.
893: * @return $this
894: * @since 3.7.0
895: * @see \Cake\Validation\Validator::allowEmptyFor() for examples.
896: */
897: public function allowEmptyArray($field, $message = null, $when = true)
898: {
899: list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
900:
901: return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_ARRAY, $when, $message);
902: }
903:
904: /**
905: * Require a field to be a non-empty array
906: *
907: * Opposite to allowEmptyArray()
908: *
909: * @param string $field The name of the field.
910: * @param string|null $message The message to show if the field is empty.
911: * @param bool|string|callable $when Indicates when the field is not allowed
912: * to be empty. Valid values are false (never), 'create', 'update'. If a
913: * callable is passed then the field will be required to be not empty when
914: * the callback returns true.
915: * @return $this
916: * @see \Cake\Validation\Validator::allowEmptyArray()
917: * @since 3.8.0
918: */
919: public function notEmptyArray($field, $message = null, $when = false)
920: {
921: $when = $this->invertWhenClause($when);
922:
923: return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_ARRAY, $when, $message);
924: }
925:
926: /**
927: * Allows a field to be an empty file.
928: *
929: * This method is equivalent to calling allowEmptyFor() with EMPTY_FILE flag.
930: * File fields will not accept `''`, or `[]` as empty values. Only `null` and a file
931: * upload with `error` equal to `UPLOAD_ERR_NO_FILE` will be treated as empty.
932: *
933: * @param string $field The name of the field.
934: * @param string|null $message The message to show if the field is not
935: * @param bool|string|callable $when Indicates when the field is allowed to be empty
936: * Valid values are true, 'create', 'update'. If a callable is passed then
937: * the field will allowed to be empty only when the callback returns true.
938: * @return $this
939: * @since 3.7.0
940: * @see \Cake\Validation\Validator::allowEmptyFor() For detail usage
941: */
942: public function allowEmptyFile($field, $message = null, $when = true)
943: {
944: list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
945:
946: return $this->allowEmptyFor($field, self::EMPTY_FILE, $when, $message);
947: }
948:
949: /**
950: * Require a field to be a not-empty file.
951: *
952: * Opposite to allowEmptyFile()
953: *
954: * @param string $field The name of the field.
955: * @param string|null $message The message to show if the field is empty.
956: * @param bool|string|callable $when Indicates when the field is not allowed
957: * to be empty. Valid values are false (never), 'create', 'update'. If a
958: * callable is passed then the field will be required to be not empty when
959: * the callback returns true.
960: * @return $this
961: * @since 3.8.0
962: * @see \Cake\Validation\Validator::allowEmptyFile()
963: */
964: public function notEmptyFile($field, $message = null, $when = false)
965: {
966: $when = $this->invertWhenClause($when);
967:
968: return $this->allowEmptyFor($field, self::EMPTY_FILE, $when, $message);
969: }
970:
971: /**
972: * Allows a field to be an empty date.
973: *
974: * Empty date values are `null`, `''`, `[]` and arrays where all values are `''`
975: * and the `year` key is present.
976: *
977: * @param string $field The name of the field.
978: * @param string|null $message The message to show if the field is not
979: * @param bool|string|callable $when Indicates when the field is allowed to be empty
980: * Valid values are true, false, 'create', 'update'. If a callable is passed then
981: * the field will allowed to be empty only when the callback returns true.
982: * @return $this
983: * @since 3.7.0
984: * @see \Cake\Validation\Validator::allowEmptyFor() for examples
985: */
986: public function allowEmptyDate($field, $message = null, $when = true)
987: {
988: list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
989:
990: return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_DATE, $when, $message);
991: }
992:
993: /**
994: * Require a non-empty date value
995: *
996: * @param string $field The name of the field.
997: * @param string|null $message The message to show if the field is empty.
998: * @param bool|string|callable $when Indicates when the field is not allowed
999: * to be empty. Valid values are false (never), 'create', 'update'. If a
1000: * callable is passed then the field will be required to be not empty when
1001: * the callback returns true.
1002: * @return $this
1003: * @since 3.8.0
1004: * @see \Cake\Validation\Validator::allowEmptyDate() for examples
1005: */
1006: public function notEmptyDate($field, $message = null, $when = false)
1007: {
1008: $when = $this->invertWhenClause($when);
1009:
1010: return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_DATE, $when, $message);
1011: }
1012:
1013: /**
1014: * Allows a field to be an empty time.
1015: *
1016: * Empty date values are `null`, `''`, `[]` and arrays where all values are `''`
1017: * and the `hour` key is present.
1018: *
1019: * This method is equivalent to calling allowEmptyFor() with EMPTY_STRING +
1020: * EMPTY_TIME flags.
1021: *
1022: * @param string $field The name of the field.
1023: * @param string|null $message The message to show if the field is not
1024: * @param bool|string|callable $when Indicates when the field is allowed to be empty
1025: * Valid values are true, false, 'create', 'update'. If a callable is passed then
1026: * the field will allowed to be empty only when the callback returns true.
1027: * @return $this
1028: * @since 3.7.0
1029: * @see \Cake\Validation\Validator::allowEmptyFor() for examples.
1030: */
1031: public function allowEmptyTime($field, $message = null, $when = true)
1032: {
1033: list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
1034:
1035: return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_TIME, $when, $message);
1036: }
1037:
1038: /**
1039: * Require a field to be a non-empty time.
1040: *
1041: * Opposite to allowEmptyTime()
1042: *
1043: * @param string $field The name of the field.
1044: * @param string|null $message The message to show if the field is empty.
1045: * @param bool|string|callable $when Indicates when the field is not allowed
1046: * to be empty. Valid values are false (never), 'create', 'update'. If a
1047: * callable is passed then the field will be required to be not empty when
1048: * the callback returns true.
1049: * @return $this
1050: * @since 3.8.0
1051: * @see \Cake\Validation\Validator::allowEmptyTime()
1052: */
1053: public function notEmptyTime($field, $message = null, $when = false)
1054: {
1055: $when = $this->invertWhenClause($when);
1056:
1057: return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_TIME, $when, $message);
1058: }
1059:
1060: /**
1061: * Allows a field to be an empty date/time.
1062: *
1063: * Empty date values are `null`, `''`, `[]` and arrays where all values are `''`
1064: * and the `year` and `hour` keys are present.
1065: *
1066: * This method is equivalent to calling allowEmptyFor() with EMPTY_STRING +
1067: * EMPTY_DATE + EMPTY_TIME flags.
1068: *
1069: * @param string $field The name of the field.
1070: * @param string|null $message The message to show if the field is not
1071: * @param bool|string|callable $when Indicates when the field is allowed to be empty
1072: * Valid values are true, false, 'create', 'update'. If a callable is passed then
1073: * the field will allowed to be empty only when the callback returns false.
1074: * @return $this
1075: * @since 3.7.0
1076: * @see \Cake\Validation\Validator::allowEmptyFor() for examples.
1077: */
1078: public function allowEmptyDateTime($field, $message = null, $when = true)
1079: {
1080: list($message, $when) = $this->sortMessageAndWhen($message, $when, __METHOD__);
1081:
1082: return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_DATE | self::EMPTY_TIME, $when, $message);
1083: }
1084:
1085: /**
1086: * Require a field to be a non empty date/time.
1087: *
1088: * Opposite to allowEmptyDateTime
1089: *
1090: * @param string $field The name of the field.
1091: * @param string|null $message The message to show if the field is empty.
1092: * @param bool|string|callable $when Indicates when the field is not allowed
1093: * to be empty. Valid values are false (never), 'create', 'update'. If a
1094: * callable is passed then the field will be required to be not empty when
1095: * the callback returns true.
1096: * @return $this
1097: * @since 3.8.0
1098: * @see \Cake\Validation\Validator::allowEmptyDateTime()
1099: */
1100: public function notEmptyDateTime($field, $message = null, $when = false)
1101: {
1102: $when = $this->invertWhenClause($when);
1103:
1104: return $this->allowEmptyFor($field, self::EMPTY_STRING | self::EMPTY_DATE | self::EMPTY_TIME, $when, $message);
1105: }
1106:
1107: /**
1108: * Converts validator to fieldName => $settings array
1109: *
1110: * @param int|string $fieldName name of field
1111: * @param array $defaults default settings
1112: * @param string|array $settings settings from data
1113: * @return array
1114: */
1115: protected function _convertValidatorToArray($fieldName, $defaults = [], $settings = [])
1116: {
1117: if (is_string($settings)) {
1118: $fieldName = $settings;
1119: $settings = [];
1120: }
1121: if (!is_array($settings)) {
1122: throw new InvalidArgumentException(
1123: sprintf('Invalid settings for "%s". Settings must be an array.', $fieldName)
1124: );
1125: }
1126: $settings += $defaults;
1127:
1128: return [$fieldName => $settings];
1129: }
1130:
1131: /**
1132: * Sets a field to require a non-empty value. You can also pass array.
1133: * Using an array will let you provide the following keys:
1134: *
1135: * - `when` individual when condition for field
1136: * - `message` individual error message for field
1137: *
1138: * You can also set `when` and `message` for all passed fields, the individual setting
1139: * takes precedence over group settings.
1140: *
1141: * This is the opposite of `allowEmpty()` which allows a field to be empty.
1142: * By using $mode equal to 'create' or 'update', you can make fields required
1143: * when records are first created, or when they are updated.
1144: *
1145: * ### Example:
1146: *
1147: * ```
1148: * $message = 'This field cannot be empty';
1149: *
1150: * // Email cannot be empty
1151: * $validator->notEmpty('email');
1152: *
1153: * // Email can be empty on update, but not create
1154: * $validator->notEmpty('email', $message, 'create');
1155: *
1156: * // Email can be empty on create, but required on update.
1157: * $validator->notEmpty('email', $message, 'update');
1158: *
1159: * // Email and title can be empty on create, but are required on update.
1160: * $validator->notEmpty(['email', 'title'], $message, 'update');
1161: *
1162: * // Email can be empty on create, title must always be not empty
1163: * $validator->notEmpty(
1164: * [
1165: * 'email',
1166: * 'title' => [
1167: * 'when' => true,
1168: * 'message' => 'Title cannot be empty'
1169: * ]
1170: * ],
1171: * $message,
1172: * 'update'
1173: * );
1174: * ```
1175: *
1176: * It is possible to conditionally disallow emptiness on a field by passing a callback
1177: * as the third argument. The callback will receive the validation context array as
1178: * argument:
1179: *
1180: * ```
1181: * $validator->notEmpty('email', 'Email is required', function ($context) {
1182: * return $context['newRecord'] && $context['data']['role'] !== 'admin';
1183: * });
1184: * ```
1185: *
1186: * Because this and `allowEmpty()` modify the same internal state, the last
1187: * method called will take precedence.
1188: *
1189: * @deprecated 3.7.0 Use notEmptyString(), notEmptyArray(), notEmptyFile(),
1190: * notEmptyDate(), notEmptyTime() or notEmptyDateTime() instead.
1191: * @param string|array $field the name of the field or list of fields
1192: * @param string|null $message The message to show if the field is not
1193: * @param bool|string|callable $when Indicates when the field is not allowed
1194: * to be empty. Valid values are true (always), 'create', 'update'. If a
1195: * callable is passed then the field will allowed to be empty only when
1196: * the callback returns false.
1197: * @return $this
1198: */
1199: public function notEmpty($field, $message = null, $when = false)
1200: {
1201: $defaults = [
1202: 'when' => $when,
1203: 'message' => $message
1204: ];
1205:
1206: if (!is_array($field)) {
1207: $field = $this->_convertValidatorToArray($field, $defaults);
1208: }
1209:
1210: foreach ($field as $fieldName => $setting) {
1211: $settings = $this->_convertValidatorToArray($fieldName, $defaults, $setting);
1212: $fieldName = current(array_keys($settings));
1213:
1214: $whenSetting = $this->invertWhenClause($settings[$fieldName]['when']);
1215:
1216: $this->field($fieldName)->allowEmpty($whenSetting);
1217: if ($settings[$fieldName]['message']) {
1218: $this->_allowEmptyMessages[$fieldName] = $settings[$fieldName]['message'];
1219: }
1220: }
1221:
1222: return $this;
1223: }
1224:
1225: /**
1226: * Invert a when clause for creating notEmpty rules
1227: *
1228: * @param bool|string|callable $when Indicates when the field is not allowed
1229: * to be empty. Valid values are true (always), 'create', 'update'. If a
1230: * callable is passed then the field will allowed to be empty only when
1231: * the callback returns false.
1232: * @return bool|string|callable
1233: */
1234: protected function invertWhenClause($when)
1235: {
1236: if ($when === 'create' || $when === 'update') {
1237: return $when === 'create' ? 'update' : 'create';
1238: } elseif (is_callable($when)) {
1239: return function ($context) use ($when) {
1240: return !$when($context);
1241: };
1242: }
1243:
1244: return $when;
1245: }
1246:
1247: /**
1248: * Add a notBlank rule to a field.
1249: *
1250: * @param string $field The field you want to apply the rule to.
1251: * @param string|null $message The error message when the rule fails.
1252: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1253: * true when the validation rule should be applied.
1254: * @see \Cake\Validation\Validation::notBlank()
1255: * @return $this
1256: */
1257: public function notBlank($field, $message = null, $when = null)
1258: {
1259: $extra = array_filter(['on' => $when, 'message' => $message]);
1260:
1261: return $this->add($field, 'notBlank', $extra + [
1262: 'rule' => 'notBlank',
1263: ]);
1264: }
1265:
1266: /**
1267: * Add an alphanumeric rule to a field.
1268: *
1269: * @param string $field The field you want to apply the rule to.
1270: * @param string|null $message The error message when the rule fails.
1271: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1272: * true when the validation rule should be applied.
1273: * @see \Cake\Validation\Validation::alphaNumeric()
1274: * @return $this
1275: */
1276: public function alphaNumeric($field, $message = null, $when = null)
1277: {
1278: $extra = array_filter(['on' => $when, 'message' => $message]);
1279:
1280: return $this->add($field, 'alphaNumeric', $extra + [
1281: 'rule' => 'alphaNumeric',
1282: ]);
1283: }
1284:
1285: /**
1286: * Add an rule that ensures a string length is within a range.
1287: *
1288: * @param string $field The field you want to apply the rule to.
1289: * @param array $range The inclusive minimum and maximum length you want permitted.
1290: * @param string|null $message The error message when the rule fails.
1291: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1292: * true when the validation rule should be applied.
1293: * @see \Cake\Validation\Validation::alphaNumeric()
1294: * @return $this
1295: */
1296: public function lengthBetween($field, array $range, $message = null, $when = null)
1297: {
1298: if (count($range) !== 2) {
1299: throw new InvalidArgumentException('The $range argument requires 2 numbers');
1300: }
1301: $extra = array_filter(['on' => $when, 'message' => $message]);
1302:
1303: return $this->add($field, 'lengthBetween', $extra + [
1304: 'rule' => ['lengthBetween', array_shift($range), array_shift($range)],
1305: ]);
1306: }
1307:
1308: /**
1309: * Add a credit card rule to a field.
1310: *
1311: * @param string $field The field you want to apply the rule to.
1312: * @param string $type The type of cards you want to allow. Defaults to 'all'.
1313: * You can also supply an array of accepted card types. e.g `['mastercard', 'visa', 'amex']`
1314: * @param string|null $message The error message when the rule fails.
1315: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1316: * true when the validation rule should be applied.
1317: * @see \Cake\Validation\Validation::creditCard()
1318: * @return $this
1319: */
1320: public function creditCard($field, $type = 'all', $message = null, $when = null)
1321: {
1322: $extra = array_filter(['on' => $when, 'message' => $message]);
1323:
1324: return $this->add($field, 'creditCard', $extra + [
1325: 'rule' => ['creditCard', $type, true],
1326: ]);
1327: }
1328:
1329: /**
1330: * Add a greater than comparison rule to a field.
1331: *
1332: * @param string $field The field you want to apply the rule to.
1333: * @param int|float $value The value user data must be greater than.
1334: * @param string|null $message The error message when the rule fails.
1335: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1336: * true when the validation rule should be applied.
1337: * @see \Cake\Validation\Validation::comparison()
1338: * @return $this
1339: */
1340: public function greaterThan($field, $value, $message = null, $when = null)
1341: {
1342: $extra = array_filter(['on' => $when, 'message' => $message]);
1343:
1344: return $this->add($field, 'greaterThan', $extra + [
1345: 'rule' => ['comparison', Validation::COMPARE_GREATER, $value]
1346: ]);
1347: }
1348:
1349: /**
1350: * Add a greater than or equal to comparison rule to a field.
1351: *
1352: * @param string $field The field you want to apply the rule to.
1353: * @param int|float $value The value user data must be greater than or equal to.
1354: * @param string|null $message The error message when the rule fails.
1355: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1356: * true when the validation rule should be applied.
1357: * @see \Cake\Validation\Validation::comparison()
1358: * @return $this
1359: */
1360: public function greaterThanOrEqual($field, $value, $message = null, $when = null)
1361: {
1362: $extra = array_filter(['on' => $when, 'message' => $message]);
1363:
1364: return $this->add($field, 'greaterThanOrEqual', $extra + [
1365: 'rule' => ['comparison', Validation::COMPARE_GREATER_OR_EQUAL, $value]
1366: ]);
1367: }
1368:
1369: /**
1370: * Add a less than comparison rule to a field.
1371: *
1372: * @param string $field The field you want to apply the rule to.
1373: * @param int|float $value The value user data must be less than.
1374: * @param string|null $message The error message when the rule fails.
1375: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1376: * true when the validation rule should be applied.
1377: * @see \Cake\Validation\Validation::comparison()
1378: * @return $this
1379: */
1380: public function lessThan($field, $value, $message = null, $when = null)
1381: {
1382: $extra = array_filter(['on' => $when, 'message' => $message]);
1383:
1384: return $this->add($field, 'lessThan', $extra + [
1385: 'rule' => ['comparison', Validation::COMPARE_LESS, $value]
1386: ]);
1387: }
1388:
1389: /**
1390: * Add a less than or equal comparison rule to a field.
1391: *
1392: * @param string $field The field you want to apply the rule to.
1393: * @param int|float $value The value user data must be less than or equal to.
1394: * @param string|null $message The error message when the rule fails.
1395: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1396: * true when the validation rule should be applied.
1397: * @see \Cake\Validation\Validation::comparison()
1398: * @return $this
1399: */
1400: public function lessThanOrEqual($field, $value, $message = null, $when = null)
1401: {
1402: $extra = array_filter(['on' => $when, 'message' => $message]);
1403:
1404: return $this->add($field, 'lessThanOrEqual', $extra + [
1405: 'rule' => ['comparison', Validation::COMPARE_LESS_OR_EQUAL, $value]
1406: ]);
1407: }
1408:
1409: /**
1410: * Add a equal to comparison rule to a field.
1411: *
1412: * @param string $field The field you want to apply the rule to.
1413: * @param int|float $value The value user data must be equal to.
1414: * @param string|null $message The error message when the rule fails.
1415: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1416: * true when the validation rule should be applied.
1417: * @see \Cake\Validation\Validation::comparison()
1418: * @return $this
1419: */
1420: public function equals($field, $value, $message = null, $when = null)
1421: {
1422: $extra = array_filter(['on' => $when, 'message' => $message]);
1423:
1424: return $this->add($field, 'equals', $extra + [
1425: 'rule' => ['comparison', Validation::COMPARE_EQUAL, $value]
1426: ]);
1427: }
1428:
1429: /**
1430: * Add a not equal to comparison rule to a field.
1431: *
1432: * @param string $field The field you want to apply the rule to.
1433: * @param int|float $value The value user data must be not be equal to.
1434: * @param string|null $message The error message when the rule fails.
1435: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1436: * true when the validation rule should be applied.
1437: * @see \Cake\Validation\Validation::comparison()
1438: * @return $this
1439: */
1440: public function notEquals($field, $value, $message = null, $when = null)
1441: {
1442: $extra = array_filter(['on' => $when, 'message' => $message]);
1443:
1444: return $this->add($field, 'notEquals', $extra + [
1445: 'rule' => ['comparison', Validation::COMPARE_NOT_EQUAL, $value]
1446: ]);
1447: }
1448:
1449: /**
1450: * Add a rule to compare two fields to each other.
1451: *
1452: * If both fields have the exact same value the rule will pass.
1453: *
1454: * @param string $field The field you want to apply the rule to.
1455: * @param string $secondField The field you want to compare against.
1456: * @param string|null $message The error message when the rule fails.
1457: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1458: * true when the validation rule should be applied.
1459: * @see \Cake\Validation\Validation::compareFields()
1460: * @return $this
1461: */
1462: public function sameAs($field, $secondField, $message = null, $when = null)
1463: {
1464: $extra = array_filter(['on' => $when, 'message' => $message]);
1465:
1466: return $this->add($field, 'sameAs', $extra + [
1467: 'rule' => ['compareFields', $secondField, Validation::COMPARE_SAME]
1468: ]);
1469: }
1470:
1471: /**
1472: * Add a rule to compare that two fields have different values.
1473: *
1474: * @param string $field The field you want to apply the rule to.
1475: * @param string $secondField The field you want to compare against.
1476: * @param string|null $message The error message when the rule fails.
1477: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1478: * true when the validation rule should be applied.
1479: * @see \Cake\Validation\Validation::compareFields()
1480: * @return $this
1481: * @since 3.6.0
1482: */
1483: public function notSameAs($field, $secondField, $message = null, $when = null)
1484: {
1485: $extra = array_filter(['on' => $when, 'message' => $message]);
1486:
1487: return $this->add($field, 'notSameAs', $extra + [
1488: 'rule' => ['compareFields', $secondField, Validation::COMPARE_NOT_SAME]
1489: ]);
1490: }
1491:
1492: /**
1493: * Add a rule to compare one field is equal to another.
1494: *
1495: * @param string $field The field you want to apply the rule to.
1496: * @param string $secondField The field you want to compare against.
1497: * @param string|null $message The error message when the rule fails.
1498: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1499: * true when the validation rule should be applied.
1500: * @see \Cake\Validation\Validation::compareFields()
1501: * @return $this
1502: * @since 3.6.0
1503: */
1504: public function equalToField($field, $secondField, $message = null, $when = null)
1505: {
1506: $extra = array_filter(['on' => $when, 'message' => $message]);
1507:
1508: return $this->add($field, 'equalToField', $extra + [
1509: 'rule' => ['compareFields', $secondField, Validation::COMPARE_EQUAL]
1510: ]);
1511: }
1512:
1513: /**
1514: * Add a rule to compare one field is not equal to another.
1515: *
1516: * @param string $field The field you want to apply the rule to.
1517: * @param string $secondField The field you want to compare against.
1518: * @param string|null $message The error message when the rule fails.
1519: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1520: * true when the validation rule should be applied.
1521: * @see \Cake\Validation\Validation::compareFields()
1522: * @return $this
1523: * @since 3.6.0
1524: */
1525: public function notEqualToField($field, $secondField, $message = null, $when = null)
1526: {
1527: $extra = array_filter(['on' => $when, 'message' => $message]);
1528:
1529: return $this->add($field, 'notEqualToField', $extra + [
1530: 'rule' => ['compareFields', $secondField, Validation::COMPARE_NOT_EQUAL]
1531: ]);
1532: }
1533:
1534: /**
1535: * Add a rule to compare one field is greater than another.
1536: *
1537: * @param string $field The field you want to apply the rule to.
1538: * @param string $secondField The field you want to compare against.
1539: * @param string|null $message The error message when the rule fails.
1540: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1541: * true when the validation rule should be applied.
1542: * @see \Cake\Validation\Validation::compareFields()
1543: * @return $this
1544: * @since 3.6.0
1545: */
1546: public function greaterThanField($field, $secondField, $message = null, $when = null)
1547: {
1548: $extra = array_filter(['on' => $when, 'message' => $message]);
1549:
1550: return $this->add($field, 'greaterThanField', $extra + [
1551: 'rule' => ['compareFields', $secondField, Validation::COMPARE_GREATER]
1552: ]);
1553: }
1554:
1555: /**
1556: * Add a rule to compare one field is greater than or equal to another.
1557: *
1558: * @param string $field The field you want to apply the rule to.
1559: * @param string $secondField The field you want to compare against.
1560: * @param string|null $message The error message when the rule fails.
1561: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1562: * true when the validation rule should be applied.
1563: * @see \Cake\Validation\Validation::compareFields()
1564: * @return $this
1565: * @since 3.6.0
1566: */
1567: public function greaterThanOrEqualToField($field, $secondField, $message = null, $when = null)
1568: {
1569: $extra = array_filter(['on' => $when, 'message' => $message]);
1570:
1571: return $this->add($field, 'greaterThanOrEqualToField', $extra + [
1572: 'rule' => ['compareFields', $secondField, Validation::COMPARE_GREATER_OR_EQUAL]
1573: ]);
1574: }
1575:
1576: /**
1577: * Add a rule to compare one field is less than another.
1578: *
1579: * @param string $field The field you want to apply the rule to.
1580: * @param string $secondField The field you want to compare against.
1581: * @param string|null $message The error message when the rule fails.
1582: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1583: * true when the validation rule should be applied.
1584: * @see \Cake\Validation\Validation::compareFields()
1585: * @return $this
1586: * @since 3.6.0
1587: */
1588: public function lessThanField($field, $secondField, $message = null, $when = null)
1589: {
1590: $extra = array_filter(['on' => $when, 'message' => $message]);
1591:
1592: return $this->add($field, 'lessThanField', $extra + [
1593: 'rule' => ['compareFields', $secondField, Validation::COMPARE_LESS]
1594: ]);
1595: }
1596:
1597: /**
1598: * Add a rule to compare one field is less than or equal to another.
1599: *
1600: * @param string $field The field you want to apply the rule to.
1601: * @param string $secondField The field you want to compare against.
1602: * @param string|null $message The error message when the rule fails.
1603: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1604: * true when the validation rule should be applied.
1605: * @see \Cake\Validation\Validation::compareFields()
1606: * @return $this
1607: * @since 3.6.0
1608: */
1609: public function lessThanOrEqualToField($field, $secondField, $message = null, $when = null)
1610: {
1611: $extra = array_filter(['on' => $when, 'message' => $message]);
1612:
1613: return $this->add($field, 'lessThanOrEqualToField', $extra + [
1614: 'rule' => ['compareFields', $secondField, Validation::COMPARE_LESS_OR_EQUAL]
1615: ]);
1616: }
1617:
1618: /**
1619: * Add a rule to check if a field contains non alpha numeric characters.
1620: *
1621: * @param string $field The field you want to apply the rule to.
1622: * @param int $limit The minimum number of non-alphanumeric fields required.
1623: * @param string|null $message The error message when the rule fails.
1624: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1625: * true when the validation rule should be applied.
1626: * @see \Cake\Validation\Validation::containsNonAlphaNumeric()
1627: * @return $this
1628: */
1629: public function containsNonAlphaNumeric($field, $limit = 1, $message = null, $when = null)
1630: {
1631: $extra = array_filter(['on' => $when, 'message' => $message]);
1632:
1633: return $this->add($field, 'containsNonAlphaNumeric', $extra + [
1634: 'rule' => ['containsNonAlphaNumeric', $limit]
1635: ]);
1636: }
1637:
1638: /**
1639: * Add a date format validation rule to a field.
1640: *
1641: * @param string $field The field you want to apply the rule to.
1642: * @param array $formats A list of accepted date formats.
1643: * @param string|null $message The error message when the rule fails.
1644: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1645: * true when the validation rule should be applied.
1646: * @see \Cake\Validation\Validation::date()
1647: * @return $this
1648: */
1649: public function date($field, $formats = ['ymd'], $message = null, $when = null)
1650: {
1651: $extra = array_filter(['on' => $when, 'message' => $message]);
1652:
1653: return $this->add($field, 'date', $extra + [
1654: 'rule' => ['date', $formats]
1655: ]);
1656: }
1657:
1658: /**
1659: * Add a date time format validation rule to a field.
1660: *
1661: * @param string $field The field you want to apply the rule to.
1662: * @param array $formats A list of accepted date formats.
1663: * @param string|null $message The error message when the rule fails.
1664: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1665: * true when the validation rule should be applied.
1666: * @see \Cake\Validation\Validation::datetime()
1667: * @return $this
1668: */
1669: public function dateTime($field, $formats = ['ymd'], $message = null, $when = null)
1670: {
1671: $extra = array_filter(['on' => $when, 'message' => $message]);
1672:
1673: return $this->add($field, 'dateTime', $extra + [
1674: 'rule' => ['datetime', $formats]
1675: ]);
1676: }
1677:
1678: /**
1679: * Add a time format validation rule to a field.
1680: *
1681: * @param string $field The field you want to apply the rule to.
1682: * @param string|null $message The error message when the rule fails.
1683: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1684: * true when the validation rule should be applied.
1685: * @see \Cake\Validation\Validation::time()
1686: * @return $this
1687: */
1688: public function time($field, $message = null, $when = null)
1689: {
1690: $extra = array_filter(['on' => $when, 'message' => $message]);
1691:
1692: return $this->add($field, 'time', $extra + [
1693: 'rule' => 'time'
1694: ]);
1695: }
1696:
1697: /**
1698: * Add a localized time, date or datetime format validation rule to a field.
1699: *
1700: * @param string $field The field you want to apply the rule to.
1701: * @param string $type Parser type, one out of 'date', 'time', and 'datetime'
1702: * @param string|null $message The error message when the rule fails.
1703: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1704: * true when the validation rule should be applied.
1705: * @see \Cake\Validation\Validation::localizedTime()
1706: * @return $this
1707: */
1708: public function localizedTime($field, $type = 'datetime', $message = null, $when = null)
1709: {
1710: $extra = array_filter(['on' => $when, 'message' => $message]);
1711:
1712: return $this->add($field, 'localizedTime', $extra + [
1713: 'rule' => ['localizedTime', $type]
1714: ]);
1715: }
1716:
1717: /**
1718: * Add a boolean validation rule to a field.
1719: *
1720: * @param string $field The field you want to apply the rule to.
1721: * @param string|null $message The error message when the rule fails.
1722: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1723: * true when the validation rule should be applied.
1724: * @see \Cake\Validation\Validation::boolean()
1725: * @return $this
1726: */
1727: public function boolean($field, $message = null, $when = null)
1728: {
1729: $extra = array_filter(['on' => $when, 'message' => $message]);
1730:
1731: return $this->add($field, 'boolean', $extra + [
1732: 'rule' => 'boolean'
1733: ]);
1734: }
1735:
1736: /**
1737: * Add a decimal validation rule to a field.
1738: *
1739: * @param string $field The field you want to apply the rule to.
1740: * @param int|null $places The number of decimal places to require.
1741: * @param string|null $message The error message when the rule fails.
1742: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1743: * true when the validation rule should be applied.
1744: * @see \Cake\Validation\Validation::decimal()
1745: * @return $this
1746: */
1747: public function decimal($field, $places = null, $message = null, $when = null)
1748: {
1749: $extra = array_filter(['on' => $when, 'message' => $message]);
1750:
1751: return $this->add($field, 'decimal', $extra + [
1752: 'rule' => ['decimal', $places]
1753: ]);
1754: }
1755:
1756: /**
1757: * Add an email validation rule to a field.
1758: *
1759: * @param string $field The field you want to apply the rule to.
1760: * @param bool $checkMX Whether or not to check the MX records.
1761: * @param string|null $message The error message when the rule fails.
1762: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1763: * true when the validation rule should be applied.
1764: * @see \Cake\Validation\Validation::email()
1765: * @return $this
1766: */
1767: public function email($field, $checkMX = false, $message = null, $when = null)
1768: {
1769: $extra = array_filter(['on' => $when, 'message' => $message]);
1770:
1771: return $this->add($field, 'email', $extra + [
1772: 'rule' => ['email', $checkMX]
1773: ]);
1774: }
1775:
1776: /**
1777: * Add an IP validation rule to a field.
1778: *
1779: * This rule will accept both IPv4 and IPv6 addresses.
1780: *
1781: * @param string $field The field you want to apply the rule to.
1782: * @param string|null $message The error message when the rule fails.
1783: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1784: * true when the validation rule should be applied.
1785: * @see \Cake\Validation\Validation::ip()
1786: * @return $this
1787: */
1788: public function ip($field, $message = null, $when = null)
1789: {
1790: $extra = array_filter(['on' => $when, 'message' => $message]);
1791:
1792: return $this->add($field, 'ip', $extra + [
1793: 'rule' => 'ip'
1794: ]);
1795: }
1796:
1797: /**
1798: * Add an IPv4 validation rule to a field.
1799: *
1800: * @param string $field The field you want to apply the rule to.
1801: * @param string|null $message The error message when the rule fails.
1802: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1803: * true when the validation rule should be applied.
1804: * @see \Cake\Validation\Validation::ip()
1805: * @return $this
1806: */
1807: public function ipv4($field, $message = null, $when = null)
1808: {
1809: $extra = array_filter(['on' => $when, 'message' => $message]);
1810:
1811: return $this->add($field, 'ipv4', $extra + [
1812: 'rule' => ['ip', 'ipv4']
1813: ]);
1814: }
1815:
1816: /**
1817: * Add an IPv6 validation rule to a field.
1818: *
1819: * @param string $field The field you want to apply the rule to.
1820: * @param string|null $message The error message when the rule fails.
1821: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1822: * true when the validation rule should be applied.
1823: * @see \Cake\Validation\Validation::ip()
1824: * @return $this
1825: */
1826: public function ipv6($field, $message = null, $when = null)
1827: {
1828: $extra = array_filter(['on' => $when, 'message' => $message]);
1829:
1830: return $this->add($field, 'ipv6', $extra + [
1831: 'rule' => ['ip', 'ipv6']
1832: ]);
1833: }
1834:
1835: /**
1836: * Add a string length validation rule to a field.
1837: *
1838: * @param string $field The field you want to apply the rule to.
1839: * @param int $min The minimum length required.
1840: * @param string|null $message The error message when the rule fails.
1841: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1842: * true when the validation rule should be applied.
1843: * @see \Cake\Validation\Validation::minLength()
1844: * @return $this
1845: */
1846: public function minLength($field, $min, $message = null, $when = null)
1847: {
1848: $extra = array_filter(['on' => $when, 'message' => $message]);
1849:
1850: return $this->add($field, 'minLength', $extra + [
1851: 'rule' => ['minLength', $min]
1852: ]);
1853: }
1854:
1855: /**
1856: * Add a string length validation rule to a field.
1857: *
1858: * @param string $field The field you want to apply the rule to.
1859: * @param int $min The minimum length required.
1860: * @param string|null $message The error message when the rule fails.
1861: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1862: * true when the validation rule should be applied.
1863: * @see \Cake\Validation\Validation::minLengthBytes()
1864: * @return $this
1865: */
1866: public function minLengthBytes($field, $min, $message = null, $when = null)
1867: {
1868: $extra = array_filter(['on' => $when, 'message' => $message]);
1869:
1870: return $this->add($field, 'minLengthBytes', $extra + [
1871: 'rule' => ['minLengthBytes', $min]
1872: ]);
1873: }
1874:
1875: /**
1876: * Add a string length validation rule to a field.
1877: *
1878: * @param string $field The field you want to apply the rule to.
1879: * @param int $max The maximum length allowed.
1880: * @param string|null $message The error message when the rule fails.
1881: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1882: * true when the validation rule should be applied.
1883: * @see \Cake\Validation\Validation::maxLength()
1884: * @return $this
1885: */
1886: public function maxLength($field, $max, $message = null, $when = null)
1887: {
1888: $extra = array_filter(['on' => $when, 'message' => $message]);
1889:
1890: return $this->add($field, 'maxLength', $extra + [
1891: 'rule' => ['maxLength', $max]
1892: ]);
1893: }
1894:
1895: /**
1896: * Add a string length validation rule to a field.
1897: *
1898: * @param string $field The field you want to apply the rule to.
1899: * @param int $max The maximum length allowed.
1900: * @param string|null $message The error message when the rule fails.
1901: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1902: * true when the validation rule should be applied.
1903: * @see \Cake\Validation\Validation::maxLengthBytes()
1904: * @return $this
1905: */
1906: public function maxLengthBytes($field, $max, $message = null, $when = null)
1907: {
1908: $extra = array_filter(['on' => $when, 'message' => $message]);
1909:
1910: return $this->add($field, 'maxLengthBytes', $extra + [
1911: 'rule' => ['maxLengthBytes', $max]
1912: ]);
1913: }
1914:
1915: /**
1916: * Add a numeric value validation rule to a field.
1917: *
1918: * @param string $field The field you want to apply the rule to.
1919: * @param string|null $message The error message when the rule fails.
1920: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1921: * true when the validation rule should be applied.
1922: * @see \Cake\Validation\Validation::numeric()
1923: * @return $this
1924: */
1925: public function numeric($field, $message = null, $when = null)
1926: {
1927: $extra = array_filter(['on' => $when, 'message' => $message]);
1928:
1929: return $this->add($field, 'numeric', $extra + [
1930: 'rule' => 'numeric'
1931: ]);
1932: }
1933:
1934: /**
1935: * Add a natural number validation rule to a field.
1936: *
1937: * @param string $field The field you want to apply the rule to.
1938: * @param string|null $message The error message when the rule fails.
1939: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1940: * true when the validation rule should be applied.
1941: * @see \Cake\Validation\Validation::naturalNumber()
1942: * @return $this
1943: */
1944: public function naturalNumber($field, $message = null, $when = null)
1945: {
1946: $extra = array_filter(['on' => $when, 'message' => $message]);
1947:
1948: return $this->add($field, 'naturalNumber', $extra + [
1949: 'rule' => ['naturalNumber', false]
1950: ]);
1951: }
1952:
1953: /**
1954: * Add a validation rule to ensure a field is a non negative integer.
1955: *
1956: * @param string $field The field you want to apply the rule to.
1957: * @param string|null $message The error message when the rule fails.
1958: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1959: * true when the validation rule should be applied.
1960: * @see \Cake\Validation\Validation::naturalNumber()
1961: * @return $this
1962: */
1963: public function nonNegativeInteger($field, $message = null, $when = null)
1964: {
1965: $extra = array_filter(['on' => $when, 'message' => $message]);
1966:
1967: return $this->add($field, 'nonNegativeInteger', $extra + [
1968: 'rule' => ['naturalNumber', true]
1969: ]);
1970: }
1971:
1972: /**
1973: * Add a validation rule to ensure a field is within a numeric range
1974: *
1975: * @param string $field The field you want to apply the rule to.
1976: * @param array $range The inclusive upper and lower bounds of the valid range.
1977: * @param string|null $message The error message when the rule fails.
1978: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
1979: * true when the validation rule should be applied.
1980: * @see \Cake\Validation\Validation::range()
1981: * @return $this
1982: */
1983: public function range($field, array $range, $message = null, $when = null)
1984: {
1985: if (count($range) !== 2) {
1986: throw new InvalidArgumentException('The $range argument requires 2 numbers');
1987: }
1988: $extra = array_filter(['on' => $when, 'message' => $message]);
1989:
1990: return $this->add($field, 'range', $extra + [
1991: 'rule' => ['range', array_shift($range), array_shift($range)]
1992: ]);
1993: }
1994:
1995: /**
1996: * Add a validation rule to ensure a field is a URL.
1997: *
1998: * This validator does not require a protocol.
1999: *
2000: * @param string $field The field you want to apply the rule to.
2001: * @param string|null $message The error message when the rule fails.
2002: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2003: * true when the validation rule should be applied.
2004: * @see \Cake\Validation\Validation::url()
2005: * @return $this
2006: */
2007: public function url($field, $message = null, $when = null)
2008: {
2009: $extra = array_filter(['on' => $when, 'message' => $message]);
2010:
2011: return $this->add($field, 'url', $extra + [
2012: 'rule' => ['url', false]
2013: ]);
2014: }
2015:
2016: /**
2017: * Add a validation rule to ensure a field is a URL.
2018: *
2019: * This validator requires the URL to have a protocol.
2020: *
2021: * @param string $field The field you want to apply the rule to.
2022: * @param string|null $message The error message when the rule fails.
2023: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2024: * true when the validation rule should be applied.
2025: * @see \Cake\Validation\Validation::url()
2026: * @return $this
2027: */
2028: public function urlWithProtocol($field, $message = null, $when = null)
2029: {
2030: $extra = array_filter(['on' => $when, 'message' => $message]);
2031:
2032: return $this->add($field, 'urlWithProtocol', $extra + [
2033: 'rule' => ['url', true]
2034: ]);
2035: }
2036:
2037: /**
2038: * Add a validation rule to ensure the field value is within a whitelist.
2039: *
2040: * @param string $field The field you want to apply the rule to.
2041: * @param array $list The list of valid options.
2042: * @param string|null $message The error message when the rule fails.
2043: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2044: * true when the validation rule should be applied.
2045: * @see \Cake\Validation\Validation::inList()
2046: * @return $this
2047: */
2048: public function inList($field, array $list, $message = null, $when = null)
2049: {
2050: $extra = array_filter(['on' => $when, 'message' => $message]);
2051:
2052: return $this->add($field, 'inList', $extra + [
2053: 'rule' => ['inList', $list]
2054: ]);
2055: }
2056:
2057: /**
2058: * Add a validation rule to ensure the field is a UUID
2059: *
2060: * @param string $field The field you want to apply the rule to.
2061: * @param string|null $message The error message when the rule fails.
2062: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2063: * true when the validation rule should be applied.
2064: * @see \Cake\Validation\Validation::uuid()
2065: * @return $this
2066: */
2067: public function uuid($field, $message = null, $when = null)
2068: {
2069: $extra = array_filter(['on' => $when, 'message' => $message]);
2070:
2071: return $this->add($field, 'uuid', $extra + [
2072: 'rule' => 'uuid'
2073: ]);
2074: }
2075:
2076: /**
2077: * Add a validation rule to ensure the field is an uploaded file
2078: *
2079: * For options see Cake\Validation\Validation::uploadedFile()
2080: *
2081: * @param string $field The field you want to apply the rule to.
2082: * @param array $options An array of options.
2083: * @param string|null $message The error message when the rule fails.
2084: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2085: * true when the validation rule should be applied.
2086: * @see \Cake\Validation\Validation::uploadedFile()
2087: * @return $this
2088: */
2089: public function uploadedFile($field, array $options, $message = null, $when = null)
2090: {
2091: $extra = array_filter(['on' => $when, 'message' => $message]);
2092:
2093: return $this->add($field, 'uploadedFile', $extra + [
2094: 'rule' => ['uploadedFile', $options]
2095: ]);
2096: }
2097:
2098: /**
2099: * Add a validation rule to ensure the field is a lat/long tuple.
2100: *
2101: * e.g. `<lat>, <lng>`
2102: *
2103: * @param string $field The field you want to apply the rule to.
2104: * @param string|null $message The error message when the rule fails.
2105: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2106: * true when the validation rule should be applied.
2107: * @see \Cake\Validation\Validation::uuid()
2108: * @return $this
2109: */
2110: public function latLong($field, $message = null, $when = null)
2111: {
2112: $extra = array_filter(['on' => $when, 'message' => $message]);
2113:
2114: return $this->add($field, 'latLong', $extra + [
2115: 'rule' => 'geoCoordinate'
2116: ]);
2117: }
2118:
2119: /**
2120: * Add a validation rule to ensure the field is a latitude.
2121: *
2122: * @param string $field The field you want to apply the rule to.
2123: * @param string|null $message The error message when the rule fails.
2124: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2125: * true when the validation rule should be applied.
2126: * @see \Cake\Validation\Validation::latitude()
2127: * @return $this
2128: */
2129: public function latitude($field, $message = null, $when = null)
2130: {
2131: $extra = array_filter(['on' => $when, 'message' => $message]);
2132:
2133: return $this->add($field, 'latitude', $extra + [
2134: 'rule' => 'latitude'
2135: ]);
2136: }
2137:
2138: /**
2139: * Add a validation rule to ensure the field is a longitude.
2140: *
2141: * @param string $field The field you want to apply the rule to.
2142: * @param string|null $message The error message when the rule fails.
2143: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2144: * true when the validation rule should be applied.
2145: * @see \Cake\Validation\Validation::longitude()
2146: * @return $this
2147: */
2148: public function longitude($field, $message = null, $when = null)
2149: {
2150: $extra = array_filter(['on' => $when, 'message' => $message]);
2151:
2152: return $this->add($field, 'longitude', $extra + [
2153: 'rule' => 'longitude'
2154: ]);
2155: }
2156:
2157: /**
2158: * Add a validation rule to ensure a field contains only ascii bytes
2159: *
2160: * @param string $field The field you want to apply the rule to.
2161: * @param string|null $message The error message when the rule fails.
2162: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2163: * true when the validation rule should be applied.
2164: * @see \Cake\Validation\Validation::ascii()
2165: * @return $this
2166: */
2167: public function ascii($field, $message = null, $when = null)
2168: {
2169: $extra = array_filter(['on' => $when, 'message' => $message]);
2170:
2171: return $this->add($field, 'ascii', $extra + [
2172: 'rule' => 'ascii'
2173: ]);
2174: }
2175:
2176: /**
2177: * Add a validation rule to ensure a field contains only BMP utf8 bytes
2178: *
2179: * @param string $field The field you want to apply the rule to.
2180: * @param string|null $message The error message when the rule fails.
2181: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2182: * true when the validation rule should be applied.
2183: * @see \Cake\Validation\Validation::utf8()
2184: * @return $this
2185: */
2186: public function utf8($field, $message = null, $when = null)
2187: {
2188: $extra = array_filter(['on' => $when, 'message' => $message]);
2189:
2190: return $this->add($field, 'utf8', $extra + [
2191: 'rule' => ['utf8', ['extended' => false]]
2192: ]);
2193: }
2194:
2195: /**
2196: * Add a validation rule to ensure a field contains only utf8 bytes.
2197: *
2198: * This rule will accept 3 and 4 byte UTF8 sequences, which are necessary for emoji.
2199: *
2200: * @param string $field The field you want to apply the rule to.
2201: * @param string|null $message The error message when the rule fails.
2202: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2203: * true when the validation rule should be applied.
2204: * @see \Cake\Validation\Validation::utf8()
2205: * @return $this
2206: */
2207: public function utf8Extended($field, $message = null, $when = null)
2208: {
2209: $extra = array_filter(['on' => $when, 'message' => $message]);
2210:
2211: return $this->add($field, 'utf8Extended', $extra + [
2212: 'rule' => ['utf8', ['extended' => true]]
2213: ]);
2214: }
2215:
2216: /**
2217: * Add a validation rule to ensure a field is an integer value.
2218: *
2219: * @param string $field The field you want to apply the rule to.
2220: * @param string|null $message The error message when the rule fails.
2221: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2222: * true when the validation rule should be applied.
2223: * @see \Cake\Validation\Validation::isInteger()
2224: * @return $this
2225: */
2226: public function integer($field, $message = null, $when = null)
2227: {
2228: $extra = array_filter(['on' => $when, 'message' => $message]);
2229:
2230: return $this->add($field, 'integer', $extra + [
2231: 'rule' => 'isInteger'
2232: ]);
2233: }
2234:
2235: /**
2236: * Add a validation rule to ensure that a field contains an array.
2237: *
2238: * @param string $field The field you want to apply the rule to.
2239: * @param string|null $message The error message when the rule fails.
2240: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2241: * true when the validation rule should be applied.
2242: * @see \Cake\Validation\Validation::isArray()
2243: * @return $this
2244: */
2245: public function isArray($field, $message = null, $when = null)
2246: {
2247: $extra = array_filter(['on' => $when, 'message' => $message]);
2248:
2249: return $this->add($field, 'isArray', $extra + [
2250: 'rule' => 'isArray'
2251: ]);
2252: }
2253:
2254: /**
2255: * Add a validation rule to ensure that a field contains a scalar.
2256: *
2257: * @param string $field The field you want to apply the rule to.
2258: * @param string|null $message The error message when the rule fails.
2259: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2260: * true when the validation rule should be applied.
2261: * @see \Cake\Validation\Validation::isScalar()
2262: * @return $this
2263: */
2264: public function scalar($field, $message = null, $when = null)
2265: {
2266: $extra = array_filter(['on' => $when, 'message' => $message]);
2267:
2268: return $this->add($field, 'scalar', $extra + [
2269: 'rule' => 'isScalar'
2270: ]);
2271: }
2272:
2273: /**
2274: * Add a validation rule to ensure a field is a 6 digits hex color value.
2275: *
2276: * @param string $field The field you want to apply the rule to.
2277: * @param string|null $message The error message when the rule fails.
2278: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2279: * true when the validation rule should be applied.
2280: * @see \Cake\Validation\Validation::hexColor()
2281: * @return $this
2282: */
2283: public function hexColor($field, $message = null, $when = null)
2284: {
2285: $extra = array_filter(['on' => $when, 'message' => $message]);
2286:
2287: return $this->add($field, 'hexColor', $extra + [
2288: 'rule' => 'hexColor',
2289: ]);
2290: }
2291:
2292: /**
2293: * Add a validation rule for a multiple select. Comparison is case sensitive by default.
2294: *
2295: * @param string $field The field you want to apply the rule to.
2296: * @param array $options The options for the validator. Includes the options defined in
2297: * \Cake\Validation\Validation::multiple() and the `caseInsensitive` parameter.
2298: * @param string|null $message The error message when the rule fails.
2299: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2300: * true when the validation rule should be applied.
2301: * @see \Cake\Validation\Validation::multiple()
2302: * @return $this
2303: */
2304: public function multipleOptions($field, array $options = [], $message = null, $when = null)
2305: {
2306: $extra = array_filter(['on' => $when, 'message' => $message]);
2307: $caseInsensitive = isset($options['caseInsensitive']) ? $options['caseInsensitive'] : false;
2308: unset($options['caseInsensitive']);
2309:
2310: return $this->add($field, 'multipleOptions', $extra + [
2311: 'rule' => ['multiple', $options, $caseInsensitive]
2312: ]);
2313: }
2314:
2315: /**
2316: * Add a validation rule to ensure that a field is an array containing at least
2317: * the specified amount of elements
2318: *
2319: * @param string $field The field you want to apply the rule to.
2320: * @param int $count The number of elements the array should at least have
2321: * @param string|null $message The error message when the rule fails.
2322: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2323: * true when the validation rule should be applied.
2324: * @see \Cake\Validation\Validation::numElements()
2325: * @return $this
2326: */
2327: public function hasAtLeast($field, $count, $message = null, $when = null)
2328: {
2329: $extra = array_filter(['on' => $when, 'message' => $message]);
2330:
2331: return $this->add($field, 'hasAtLeast', $extra + [
2332: 'rule' => function ($value) use ($count) {
2333: if (is_array($value) && isset($value['_ids'])) {
2334: $value = $value['_ids'];
2335: }
2336:
2337: return Validation::numElements($value, Validation::COMPARE_GREATER_OR_EQUAL, $count);
2338: }
2339: ]);
2340: }
2341:
2342: /**
2343: * Add a validation rule to ensure that a field is an array containing at most
2344: * the specified amount of elements
2345: *
2346: * @param string $field The field you want to apply the rule to.
2347: * @param int $count The number maximum amount of elements the field should have
2348: * @param string|null $message The error message when the rule fails.
2349: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2350: * true when the validation rule should be applied.
2351: * @see \Cake\Validation\Validation::numElements()
2352: * @return $this
2353: */
2354: public function hasAtMost($field, $count, $message = null, $when = null)
2355: {
2356: $extra = array_filter(['on' => $when, 'message' => $message]);
2357:
2358: return $this->add($field, 'hasAtMost', $extra + [
2359: 'rule' => function ($value) use ($count) {
2360: if (is_array($value) && isset($value['_ids'])) {
2361: $value = $value['_ids'];
2362: }
2363:
2364: return Validation::numElements($value, Validation::COMPARE_LESS_OR_EQUAL, $count);
2365: }
2366: ]);
2367: }
2368:
2369: /**
2370: * Returns whether or not a field can be left empty for a new or already existing
2371: * record.
2372: *
2373: * @param string $field Field name.
2374: * @param bool $newRecord whether the data to be validated is new or to be updated.
2375: * @return bool
2376: */
2377: public function isEmptyAllowed($field, $newRecord)
2378: {
2379: $providers = $this->_providers;
2380: $data = [];
2381: $context = compact('data', 'newRecord', 'field', 'providers');
2382:
2383: return $this->_canBeEmpty($this->field($field), $context);
2384: }
2385:
2386: /**
2387: * Returns whether or not a field can be left out for a new or already existing
2388: * record.
2389: *
2390: * @param string $field Field name.
2391: * @param bool $newRecord Whether the data to be validated is new or to be updated.
2392: * @return bool
2393: */
2394: public function isPresenceRequired($field, $newRecord)
2395: {
2396: $providers = $this->_providers;
2397: $data = [];
2398: $context = compact('data', 'newRecord', 'field', 'providers');
2399:
2400: return !$this->_checkPresence($this->field($field), $context);
2401: }
2402:
2403: /**
2404: * Returns whether or not a field matches against a regular expression.
2405: *
2406: * @param string $field Field name.
2407: * @param string $regex Regular expression.
2408: * @param string|null $message The error message when the rule fails.
2409: * @param string|callable|null $when Either 'create' or 'update' or a callable that returns
2410: * true when the validation rule should be applied.
2411: * @return $this
2412: */
2413: public function regex($field, $regex, $message = null, $when = null)
2414: {
2415: $extra = array_filter(['on' => $when, 'message' => $message]);
2416:
2417: return $this->add($field, 'regex', $extra + [
2418: 'rule' => ['custom', $regex]
2419: ]);
2420: }
2421:
2422: /**
2423: * Gets the required message for a field
2424: *
2425: * @param string $field Field name
2426: * @return string|null
2427: */
2428: public function getRequiredMessage($field)
2429: {
2430: if (!isset($this->_fields[$field])) {
2431: return null;
2432: }
2433:
2434: $defaultMessage = 'This field is required';
2435: if ($this->_useI18n) {
2436: $defaultMessage = __d('cake', 'This field is required');
2437: }
2438:
2439: return isset($this->_presenceMessages[$field])
2440: ? $this->_presenceMessages[$field]
2441: : $defaultMessage;
2442: }
2443:
2444: /**
2445: * Gets the notEmpty message for a field
2446: *
2447: * @param string $field Field name
2448: * @return string|null
2449: */
2450: public function getNotEmptyMessage($field)
2451: {
2452: if (!isset($this->_fields[$field])) {
2453: return null;
2454: }
2455:
2456: $defaultMessage = 'This field cannot be left empty';
2457: if ($this->_useI18n) {
2458: $defaultMessage = __d('cake', 'This field cannot be left empty');
2459: }
2460:
2461: $notBlankMessage = null;
2462: foreach ($this->_fields[$field] as $rule) {
2463: if ($rule->get('rule') === 'notBlank' && $rule->get('message')) {
2464: return $rule->get('message');
2465: }
2466: }
2467:
2468: return isset($this->_allowEmptyMessages[$field])
2469: ? $this->_allowEmptyMessages[$field]
2470: : $defaultMessage;
2471: }
2472:
2473: /**
2474: * Returns false if any validation for the passed rule set should be stopped
2475: * due to the field missing in the data array
2476: *
2477: * @param \Cake\Validation\ValidationSet $field The set of rules for a field.
2478: * @param array $context A key value list of data containing the validation context.
2479: * @return bool
2480: */
2481: protected function _checkPresence($field, $context)
2482: {
2483: $required = $field->isPresenceRequired();
2484:
2485: if (!is_string($required) && is_callable($required)) {
2486: return !$required($context);
2487: }
2488:
2489: $newRecord = $context['newRecord'];
2490: if (in_array($required, ['create', 'update'], true)) {
2491: return (
2492: ($required === 'create' && !$newRecord) ||
2493: ($required === 'update' && $newRecord)
2494: );
2495: }
2496:
2497: return !$required;
2498: }
2499:
2500: /**
2501: * Returns whether the field can be left blank according to `allowEmpty`
2502: *
2503: * @param \Cake\Validation\ValidationSet $field the set of rules for a field
2504: * @param array $context a key value list of data containing the validation context.
2505: * @return bool
2506: */
2507: protected function _canBeEmpty($field, $context)
2508: {
2509: $allowed = $field->isEmptyAllowed();
2510:
2511: if (!is_string($allowed) && is_callable($allowed)) {
2512: return $allowed($context);
2513: }
2514:
2515: $newRecord = $context['newRecord'];
2516: if (in_array($allowed, ['create', 'update'], true)) {
2517: $allowed = (
2518: ($allowed === 'create' && $newRecord) ||
2519: ($allowed === 'update' && !$newRecord)
2520: );
2521: }
2522:
2523: return $allowed;
2524: }
2525:
2526: /**
2527: * Returns true if the field is empty in the passed data array
2528: *
2529: * @param mixed $data Value to check against.
2530: * @return bool
2531: * @deprecated 3.7.0 Use isEmpty() instead
2532: */
2533: protected function _fieldIsEmpty($data)
2534: {
2535: return $this->isEmpty($data, static::EMPTY_ALL);
2536: }
2537:
2538: /**
2539: * Returns true if the field is empty in the passed data array
2540: *
2541: * @param mixed $data Value to check against.
2542: * @param int $flags A bitmask of EMPTY_* flags which specify what is empty
2543: * @return bool
2544: */
2545: protected function isEmpty($data, $flags)
2546: {
2547: if ($data === null) {
2548: return true;
2549: }
2550:
2551: if ($data === '' && ($flags & self::EMPTY_STRING)) {
2552: return true;
2553: }
2554:
2555: $arrayTypes = self::EMPTY_ARRAY | self::EMPTY_DATE | self::EMPTY_TIME;
2556: if ($data === [] && ($flags & $arrayTypes)) {
2557: return true;
2558: }
2559:
2560: if (is_array($data)) {
2561: if (($flags & self::EMPTY_FILE)
2562: && isset($data['name'], $data['type'], $data['tmp_name'], $data['error'])
2563: && (int)$data['error'] === UPLOAD_ERR_NO_FILE
2564: ) {
2565: return true;
2566: }
2567:
2568: $allFieldsAreEmpty = true;
2569: foreach ($data as $field) {
2570: if ($field !== null && $field !== '') {
2571: $allFieldsAreEmpty = false;
2572: break;
2573: }
2574: }
2575:
2576: if ($allFieldsAreEmpty) {
2577: if (($flags & self::EMPTY_DATE) && isset($data['year'])) {
2578: return true;
2579: }
2580:
2581: if (($flags & self::EMPTY_TIME) && isset($data['hour'])) {
2582: return true;
2583: }
2584: }
2585: }
2586:
2587: return false;
2588: }
2589:
2590: /**
2591: * Iterates over each rule in the validation set and collects the errors resulting
2592: * from executing them
2593: *
2594: * @param string $field The name of the field that is being processed
2595: * @param \Cake\Validation\ValidationSet $rules the list of rules for a field
2596: * @param array $data the full data passed to the validator
2597: * @param bool $newRecord whether is it a new record or an existing one
2598: * @return array
2599: */
2600: protected function _processRules($field, ValidationSet $rules, $data, $newRecord)
2601: {
2602: $errors = [];
2603: // Loading default provider in case there is none
2604: $this->getProvider('default');
2605: $message = 'The provided value is invalid';
2606:
2607: if ($this->_useI18n) {
2608: $message = __d('cake', 'The provided value is invalid');
2609: }
2610:
2611: foreach ($rules as $name => $rule) {
2612: $result = $rule->process($data[$field], $this->_providers, compact('newRecord', 'data', 'field'));
2613: if ($result === true) {
2614: continue;
2615: }
2616:
2617: $errors[$name] = $message;
2618: if (is_array($result) && $name === static::NESTED) {
2619: $errors = $result;
2620: }
2621: if (is_string($result)) {
2622: $errors[$name] = $result;
2623: }
2624:
2625: if ($rule->isLast()) {
2626: break;
2627: }
2628: }
2629:
2630: return $errors;
2631: }
2632:
2633: /**
2634: * Get the printable version of this object.
2635: *
2636: * @return array
2637: */
2638: public function __debugInfo()
2639: {
2640: $fields = [];
2641: foreach ($this->_fields as $name => $fieldSet) {
2642: $fields[$name] = [
2643: 'isPresenceRequired' => $fieldSet->isPresenceRequired(),
2644: 'isEmptyAllowed' => $fieldSet->isEmptyAllowed(),
2645: 'rules' => array_keys($fieldSet->rules()),
2646: ];
2647: }
2648:
2649: return [
2650: '_presenceMessages' => $this->_presenceMessages,
2651: '_allowEmptyMessages' => $this->_allowEmptyMessages,
2652: '_allowEmptyFlags' => $this->_allowEmptyFlags,
2653: '_useI18n' => $this->_useI18n,
2654: '_providers' => array_keys($this->_providers),
2655: '_fields' => $fields
2656: ];
2657: }
2658: }
2659: