|
|
@@ -38,6 +38,48 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
|
|
|
const NESTED = '_nested';
|
|
|
|
|
|
/**
|
|
|
+ * A flag for allowEmptyByFlags()
|
|
|
+ *
|
|
|
+ * @var int
|
|
|
+ */
|
|
|
+ const EMPTY_STRING = 1;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * A flag for allowEmptyByFlags()
|
|
|
+ *
|
|
|
+ * @var int
|
|
|
+ */
|
|
|
+ const EMPTY_ARRAY = 2;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * A flag for allowEmptyByFlags()
|
|
|
+ *
|
|
|
+ * @var int
|
|
|
+ */
|
|
|
+ const EMPTY_FILE = 4;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * A flag for allowEmptyByFlags()
|
|
|
+ *
|
|
|
+ * @var int
|
|
|
+ */
|
|
|
+ const EMPTY_DATE = 8;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * A flag for allowEmptyByFlags()
|
|
|
+ *
|
|
|
+ * @var int
|
|
|
+ */
|
|
|
+ const EMPTY_TIME = 16;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * A combination of the all EMPTY_* flags
|
|
|
+ *
|
|
|
+ * @var int
|
|
|
+ */
|
|
|
+ const EMPTY_ALL = self::EMPTY_STRING | self::EMPTY_ARRAY | self::EMPTY_FILE | self::EMPTY_DATE | self::EMPTY_TIME;
|
|
|
+
|
|
|
+ /**
|
|
|
* Holds the ValidationSet objects array
|
|
|
*
|
|
|
* @var array
|
|
|
@@ -83,6 +125,13 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
|
|
|
protected $_allowEmptyMessages = [];
|
|
|
|
|
|
/**
|
|
|
+ * Contains the flags which specify what is empty for each corresponding field.
|
|
|
+ *
|
|
|
+ * @var array
|
|
|
+ */
|
|
|
+ protected $_allowEmptyFlags = [];
|
|
|
+
|
|
|
+ /**
|
|
|
* Constructor
|
|
|
*
|
|
|
*/
|
|
|
@@ -119,7 +168,13 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
|
|
|
}
|
|
|
|
|
|
$canBeEmpty = $this->_canBeEmpty($field, $context);
|
|
|
- $isEmpty = $this->_fieldIsEmpty($data[$name]);
|
|
|
+
|
|
|
+ $flags = self::EMPTY_ALL;
|
|
|
+ if (isset($this->_allowEmptyFlags[$name])) {
|
|
|
+ $flags = $this->_allowEmptyFlags[$name];
|
|
|
+ }
|
|
|
+
|
|
|
+ $isEmpty = $this->isEmpty($data[$name], $flags);
|
|
|
|
|
|
if (!$canBeEmpty && $isEmpty) {
|
|
|
$errors[$name]['_empty'] = $this->getNotEmptyMessage($name);
|
|
|
@@ -615,6 +670,8 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
|
|
|
* Because this and `notEmpty()` modify the same internal state, the last
|
|
|
* method called will take precedence.
|
|
|
*
|
|
|
+ * @deprecated Use allowEmptyString(), allowEmptyArray(), allowEmptyFile(),
|
|
|
+ * allowEmptyDate(), allowEmptyTime() or allowEmptyDateTime() instead.
|
|
|
* @param string|array $field the name of the field or a list of fields
|
|
|
* @param bool|string|callable $when Indicates when the field is allowed to be empty
|
|
|
* Valid values are true (always), 'create', 'update'. If a callable is passed then
|
|
|
@@ -624,7 +681,91 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
|
|
|
*/
|
|
|
public function allowEmpty($field, $when = true, $message = null)
|
|
|
{
|
|
|
+ return $this->allowEmptyByFlags($field, null, $when, $message);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows a field to be empty. You can also pass array.
|
|
|
+ * Using an array will let you provide the following keys:
|
|
|
+ *
|
|
|
+ * - `flags` individual flags for field
|
|
|
+ * - `when` individual when condition for field
|
|
|
+ * - 'message' individual message for field
|
|
|
+ *
|
|
|
+ * You can also set flags, when and message for all passed fields, the individual
|
|
|
+ * setting takes precedence over group settings.
|
|
|
+ *
|
|
|
+ * ### Example:
|
|
|
+ *
|
|
|
+ * ```
|
|
|
+ * // Email can be empty
|
|
|
+ * $validator->allowEmptyByFlags('email', Validator::EMPTY_STRING);
|
|
|
+ *
|
|
|
+ * // Email can be empty on create
|
|
|
+ * $validator->allowEmptyByFlags('email', Validator::EMPTY_STRING, 'create');
|
|
|
+ *
|
|
|
+ * // Email can be empty on update
|
|
|
+ * $validator->allowEmptyByFlags('email', Validator::EMPTY_STRING, 'update');
|
|
|
+ *
|
|
|
+ * // Email and subject can be empty on update
|
|
|
+ * $validator->allowEmptyByFlags(['email', 'subject'], Validator::EMPTY_STRING, 'update');
|
|
|
+ *
|
|
|
+ * // Email can be always empty, subject and content can be empty on update.
|
|
|
+ * $validator->allowEmptyByFlags(
|
|
|
+ * [
|
|
|
+ * 'email' => [
|
|
|
+ * 'when' => true
|
|
|
+ * ],
|
|
|
+ * 'content' => [
|
|
|
+ * 'message' => 'Content cannot be empty'
|
|
|
+ * ],
|
|
|
+ * 'subject'
|
|
|
+ * ],
|
|
|
+ * Validator::EMPTY_STRING,
|
|
|
+ * 'update'
|
|
|
+ * );
|
|
|
+ * ```
|
|
|
+ *
|
|
|
+ * It is possible to conditionally allow emptiness on a field by passing a callback
|
|
|
+ * as a second argument. The callback will receive the validation context array as
|
|
|
+ * argument:
|
|
|
+ *
|
|
|
+ * ```
|
|
|
+ * $validator->allowEmpty('email', Validator::EMPTY_STRING, function ($context) {
|
|
|
+ * return !$context['newRecord'] || $context['data']['role'] === 'admin';
|
|
|
+ * });
|
|
|
+ * ```
|
|
|
+ *
|
|
|
+ * If you want to allow other kind of empty data on a field, you need to pass other
|
|
|
+ * flags:
|
|
|
+ *
|
|
|
+ * ```
|
|
|
+ * $validator->allowEmptyByFlags('photo', Validator::EMPTY_FILE);
|
|
|
+ * $validator->allowEmptyByFlags('published', Validator::EMPTY_STRING | Validator::EMPTY_DATE | Validator::EMPTY_TIME);
|
|
|
+ * $validator->allowEmptyByFlags('items', Validator::EMPTY_STRING | Validator::EMPTY_ARRAY);
|
|
|
+ * ```
|
|
|
+ *
|
|
|
+ * You can also use convenience wrappers of this method. The following calls are the
|
|
|
+ * same as above:
|
|
|
+ *
|
|
|
+ * ```
|
|
|
+ * $validator->allowEmptyFile('photo');
|
|
|
+ * $validator->allowEmptyDateTime('published');
|
|
|
+ * $validator->allowEmptyArray('items');
|
|
|
+ * ```
|
|
|
+ *
|
|
|
+ * @param string|array $field the name of the field or a list of fields
|
|
|
+ * @param int|null $flags A bitmask of EMPTY_* flags which specify what is empty
|
|
|
+ * @param bool|string|callable $when Indicates when the field is allowed to be empty
|
|
|
+ * Valid values are true (always), 'create', 'update'. If a callable is passed then
|
|
|
+ * the field will allowed to be empty only when the callback returns true.
|
|
|
+ * @param string|null $message The message to show if the field is not
|
|
|
+ * @return $this
|
|
|
+ */
|
|
|
+ public function allowEmptyByFlags($field, $flags, $when = true, $message = null)
|
|
|
+ {
|
|
|
$settingsDefault = [
|
|
|
+ 'flags' => $flags,
|
|
|
'when' => $when,
|
|
|
'message' => $message
|
|
|
];
|
|
|
@@ -641,12 +782,127 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
|
|
|
if ($settings[$fieldName]['message']) {
|
|
|
$this->_allowEmptyMessages[$fieldName] = $settings[$fieldName]['message'];
|
|
|
}
|
|
|
+ if ($settings[$fieldName]['flags'] !== null) {
|
|
|
+ $this->_allowEmptyFlags[$fieldName] = $settings[$fieldName]['flags'];
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return $this;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * Allows a field to be an empty string.
|
|
|
+ *
|
|
|
+ * This method is equivalent to calling allowEmptyByFlags() with EMPTY_STRING flag.
|
|
|
+ *
|
|
|
+ * @param string|array $field the name of the field or a list of fields
|
|
|
+ * @param bool|string|callable $when Indicates when the field is allowed to be empty
|
|
|
+ * Valid values are true (always), 'create', 'update'. If a callable is passed then
|
|
|
+ * the field will allowed to be empty only when the callback returns true.
|
|
|
+ * @param string|null $message The message to show if the field is not
|
|
|
+ * @return $this
|
|
|
+ * @see \Cake\Validation\Validator::allowEmptyByFlags() For detail usage
|
|
|
+ */
|
|
|
+ public function allowEmptyString($field, $when = true, $message = null)
|
|
|
+ {
|
|
|
+ return $this->allowEmptyByFlags($field, self::EMPTY_STRING, $when, $message);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows a field to be an empty array.
|
|
|
+ *
|
|
|
+ * This method is equivalent to calling allowEmptyByFlags() with EMPTY_STRING +
|
|
|
+ * EMPTY_ARRAY flags.
|
|
|
+ *
|
|
|
+ * @param string|array $field the name of the field or a list of fields
|
|
|
+ * @param bool|string|callable $when Indicates when the field is allowed to be empty
|
|
|
+ * Valid values are true (always), 'create', 'update'. If a callable is passed then
|
|
|
+ * the field will allowed to be empty only when the callback returns true.
|
|
|
+ * @param string|null $message The message to show if the field is not
|
|
|
+ * @return $this
|
|
|
+ * @see \Cake\Validation\Validator::allowEmptyByFlags() For detail usage
|
|
|
+ */
|
|
|
+ public function allowEmptyArray($field, $when = true, $message = null)
|
|
|
+ {
|
|
|
+ return $this->allowEmptyByFlags($field, self::EMPTY_STRING | self::EMPTY_ARRAY, $when, $message);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows a field to be an empty file.
|
|
|
+ *
|
|
|
+ * This method is equivalent to calling allowEmptyByFlags() with EMPTY_FILE flag.
|
|
|
+ *
|
|
|
+ * @param string|array $field the name of the field or a list of fields
|
|
|
+ * @param bool|string|callable $when Indicates when the field is allowed to be empty
|
|
|
+ * Valid values are true (always), 'create', 'update'. If a callable is passed then
|
|
|
+ * the field will allowed to be empty only when the callback returns true.
|
|
|
+ * @param string|null $message The message to show if the field is not
|
|
|
+ * @return $this
|
|
|
+ * @see \Cake\Validation\Validator::allowEmptyByFlags() For detail usage
|
|
|
+ */
|
|
|
+ public function allowEmptyFile($field, $when = true, $message = null)
|
|
|
+ {
|
|
|
+ return $this->allowEmptyByFlags($field, self::EMPTY_FILE, $when, $message);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows a field to be an empty date.
|
|
|
+ *
|
|
|
+ * This method is equivalent to calling allowEmptyByFlags() with EMPTY_STRING +
|
|
|
+ * EMPTY_DATE flags.
|
|
|
+ *
|
|
|
+ * @param string|array $field the name of the field or a list of fields
|
|
|
+ * @param bool|string|callable $when Indicates when the field is allowed to be empty
|
|
|
+ * Valid values are true (always), 'create', 'update'. If a callable is passed then
|
|
|
+ * the field will allowed to be empty only when the callback returns true.
|
|
|
+ * @param string|null $message The message to show if the field is not
|
|
|
+ * @return $this
|
|
|
+ * @see \Cake\Validation\Validator::allowEmptyByFlags() For detail usage
|
|
|
+ */
|
|
|
+ public function allowEmptyDate($field, $when = true, $message = null)
|
|
|
+ {
|
|
|
+ return $this->allowEmptyByFlags($field, self::EMPTY_STRING | self::EMPTY_DATE, $when, $message);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows a field to be an empty time.
|
|
|
+ *
|
|
|
+ * This method is equivalent to calling allowEmptyByFlags() with EMPTY_STRING +
|
|
|
+ * EMPTY_TIME flags.
|
|
|
+ *
|
|
|
+ * @param string|array $field the name of the field or a list of fields
|
|
|
+ * @param bool|string|callable $when Indicates when the field is allowed to be empty
|
|
|
+ * Valid values are true (always), 'create', 'update'. If a callable is passed then
|
|
|
+ * the field will allowed to be empty only when the callback returns true.
|
|
|
+ * @param string|null $message The message to show if the field is not
|
|
|
+ * @return $this
|
|
|
+ * @see \Cake\Validation\Validator::allowEmptyByFlags() For detail usage
|
|
|
+ */
|
|
|
+ public function allowEmptyTime($field, $when = true, $message = null)
|
|
|
+ {
|
|
|
+ return $this->allowEmptyByFlags($field, self::EMPTY_STRING | self::EMPTY_TIME, $when, $message);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allows a field to be an empty date/time.
|
|
|
+ *
|
|
|
+ * This method is equivalent to calling allowEmptyByFlags() with EMPTY_STRING +
|
|
|
+ * EMPTY_DATE + EMPTY_TIME flags.
|
|
|
+ *
|
|
|
+ * @param string|array $field the name of the field or a list of fields
|
|
|
+ * @param bool|string|callable $when Indicates when the field is allowed to be empty
|
|
|
+ * Valid values are true (always), 'create', 'update'. If a callable is passed then
|
|
|
+ * the field will allowed to be empty only when the callback returns true.
|
|
|
+ * @param string|null $message The message to show if the field is not
|
|
|
+ * @return $this
|
|
|
+ * @see \Cake\Validation\Validator::allowEmptyByFlags() For detail usage
|
|
|
+ */
|
|
|
+ public function allowEmptyDateTime($field, $when = true, $message = null)
|
|
|
+ {
|
|
|
+ return $this->allowEmptyByFlags($field, self::EMPTY_STRING | self::EMPTY_DATE | self::EMPTY_TIME, $when, $message);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* Converts validator to fieldName => $settings array
|
|
|
*
|
|
|
* @param int|string $fieldName name of field
|
|
|
@@ -728,6 +984,9 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
|
|
|
* Because this and `allowEmpty()` modify the same internal state, the last
|
|
|
* method called will take precedence.
|
|
|
*
|
|
|
+ * @deprecated Use allowEmptyString(), allowEmptyArray(), allowEmptyFile(),
|
|
|
+ * allowEmptyDate(), allowEmptyTime() or allowEmptyDateTime() with oppsite
|
|
|
+ * conditions instead.
|
|
|
* @param string|array $field the name of the field or list of fields
|
|
|
* @param string|null $message The message to show if the field is not
|
|
|
* @param bool|string|callable $when Indicates when the field is not allowed
|
|
|
@@ -2053,20 +2312,59 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
|
|
|
*
|
|
|
* @param mixed $data value to check against
|
|
|
* @return bool
|
|
|
+ * @deprecated Use isEmpty() instead
|
|
|
*/
|
|
|
protected function _fieldIsEmpty($data)
|
|
|
{
|
|
|
- if (empty($data) && !is_bool($data) && !is_numeric($data)) {
|
|
|
+ return $this->isEmpty($data, self::EMPTY_ALL);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Returns true if the field is empty in the passed data array
|
|
|
+ *
|
|
|
+ * @param mixed $data value to check against
|
|
|
+ * @param int $flags A bitmask of EMPTY_* flags which specify what is empty
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ protected function isEmpty($data, $flags)
|
|
|
+ {
|
|
|
+ if ($data === null) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($data === '' && ($flags & self::EMPTY_STRING)) {
|
|
|
return true;
|
|
|
}
|
|
|
- $isArray = is_array($data);
|
|
|
- if ($isArray && (isset($data['year']) || isset($data['hour']))) {
|
|
|
- $value = implode('', $data);
|
|
|
|
|
|
- return strlen($value) === 0;
|
|
|
+ if ($data === [] && ($flags & self::EMPTY_ARRAY)) {
|
|
|
+ return true;
|
|
|
}
|
|
|
- if ($isArray && isset($data['name'], $data['type'], $data['tmp_name'], $data['error'])) {
|
|
|
- return (int)$data['error'] === UPLOAD_ERR_NO_FILE;
|
|
|
+
|
|
|
+ if (is_array($data)) {
|
|
|
+ if (($flags & self::EMPTY_FILE)
|
|
|
+ && isset($data['name'], $data['type'], $data['tmp_name'], $data['error'])
|
|
|
+ && (int)$data['error'] === UPLOAD_ERR_NO_FILE
|
|
|
+ ) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ $allFieldsAreEmpty = true;
|
|
|
+ foreach ($data as $field) {
|
|
|
+ if ($field !== null && $field !== '') {
|
|
|
+ $allFieldsAreEmpty = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($allFieldsAreEmpty) {
|
|
|
+ if (($flags & self::EMPTY_DATE) && isset($data['year'])) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (($flags & self::EMPTY_TIME) && isset($data['hour'])) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
@@ -2134,6 +2432,7 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
|
|
|
return [
|
|
|
'_presenceMessages' => $this->_presenceMessages,
|
|
|
'_allowEmptyMessages' => $this->_allowEmptyMessages,
|
|
|
+ '_allowEmptyFlags' => $this->_allowEmptyFlags,
|
|
|
'_useI18n' => $this->_useI18n,
|
|
|
'_providers' => array_keys($this->_providers),
|
|
|
'_fields' => $fields
|