field = $fieldName; if (!is_array($ruleSet) || (is_array($ruleSet) && isset($ruleSet['rule']))) { $ruleSet = array($ruleSet); } foreach ($ruleSet as $index => $validateProp) { $this->_rules[$index] = new CakeValidationRule($validateProp); } $this->ruleSet = $ruleSet; } /** * Sets the list of methods to use for validation * * @param array &$methods Methods list * @return void */ public function setMethods(&$methods) { $this->_methods =& $methods; } /** * Sets the I18n domain for validation messages. * * @param string $validationDomain The validation domain to be used. * @return void */ public function setValidationDomain($validationDomain) { $this->_validationDomain = $validationDomain; } /** * Runs all validation rules in this set and returns a list of * validation errors * * @param array $data Data array * @param bool $isUpdate Is record being updated or created * @return array list of validation errors for this field */ public function validate($data, $isUpdate = false) { $this->reset(); $errors = array(); foreach ($this->getRules() as $name => $rule) { $rule->isUpdate($isUpdate); if ($rule->skip()) { continue; } $checkRequired = $rule->checkRequired($this->field, $data); if (!$checkRequired && array_key_exists($this->field, $data)) { if ($rule->checkEmpty($this->field, $data)) { break; } $rule->process($this->field, $data, $this->_methods); } if ($checkRequired || !$rule->isValid()) { $errors[] = $this->_processValidationResponse($name, $rule); if ($rule->isLast()) { break; } } } return $errors; } /** * Resets internal state for all validation rules in this set * * @return void */ public function reset() { foreach ($this->getRules() as $rule) { $rule->reset(); } } /** * Gets a rule for a given name if exists * * @param string $name Field name. * @return CakeValidationRule */ public function getRule($name) { if (!empty($this->_rules[$name])) { return $this->_rules[$name]; } } /** * Returns all rules for this validation set * * @return CakeValidationRule[] */ public function getRules() { return $this->_rules; } /** * Sets a CakeValidationRule $rule with a $name * * ## Example: * * ``` * $set * ->setRule('required', array('rule' => 'notBlank', 'required' => true)) * ->setRule('between', array('rule' => array('lengthBetween', 4, 10)) * ``` * * @param string $name The name under which the rule should be set * @param CakeValidationRule|array $rule The validation rule to be set * @return self */ public function setRule($name, $rule) { if (!($rule instanceof CakeValidationRule)) { $rule = new CakeValidationRule($rule); } $this->_rules[$name] = $rule; return $this; } /** * Removes a validation rule from the set * * ## Example: * * ``` * $set * ->removeRule('required') * ->removeRule('inRange') * ``` * * @param string $name The name under which the rule should be unset * @return self */ public function removeRule($name) { unset($this->_rules[$name]); return $this; } /** * Sets the rules for a given field * * ## Example: * * ``` * $set->setRules(array( * 'required' => array('rule' => 'notBlank', 'required' => true), * 'inRange' => array('rule' => array('between', 4, 10) * )); * ``` * * @param array $rules The rules to be set * @param bool $mergeVars [optional] If true, merges vars instead of replace. Defaults to true. * @return self */ public function setRules($rules = array(), $mergeVars = true) { if ($mergeVars === false) { $this->_rules = array(); } foreach ($rules as $name => $rule) { $this->setRule($name, $rule); } return $this; } /** * Fetches the correct error message for a failed validation * * @param string $name the name of the rule as it was configured * @param CakeValidationRule $rule the object containing validation information * @return string */ protected function _processValidationResponse($name, $rule) { $message = $rule->getValidationResult(); if (is_string($message)) { return $message; } $message = $rule->message; if ($message !== null) { $args = null; if (is_array($message)) { $result = $message[0]; $args = array_slice($message, 1); } else { $result = $message; } if (is_array($rule->rule) && $args === null) { $args = array_slice($rule->rule, 1); } $args = $this->_translateArgs($args); $message = __d($this->_validationDomain, $result, $args); } elseif (is_string($name)) { if (is_array($rule->rule)) { $args = array_slice($rule->rule, 1); $args = $this->_translateArgs($args); $message = __d($this->_validationDomain, $name, $args); } else { $message = __d($this->_validationDomain, $name); } } else { $message = __d('cake', 'This field cannot be left blank'); } return $message; } /** * Applies translations to validator arguments. * * @param array $args The args to translate * @return array Translated args. */ protected function _translateArgs($args) { foreach ((array)$args as $k => $arg) { if (is_string($arg)) { $args[$k] = __d($this->_validationDomain, $arg); } } return $args; } /** * Returns whether an index exists in the rule set * * @param string $index name of the rule * @return bool */ public function offsetExists($index) { return isset($this->_rules[$index]); } /** * Returns a rule object by its index * * @param string $index name of the rule * @return CakeValidationRule */ public function offsetGet($index) { return $this->_rules[$index]; } /** * Sets or replace a validation rule. * * This is a wrapper for ArrayAccess. Use setRule() directly for * chainable access. * * @param string $index Name of the rule. * @param CakeValidationRule|array $rule Rule to add to $index. * @return void * @see http://www.php.net/manual/en/arrayobject.offsetset.php */ public function offsetSet($index, $rule) { $this->setRule($index, $rule); } /** * Unsets a validation rule * * @param string $index name of the rule * @return void */ public function offsetUnset($index) { unset($this->_rules[$index]); } /** * Returns an iterator for each of the rules to be applied * * @return ArrayIterator */ public function getIterator() { return new ArrayIterator($this->_rules); } /** * Returns the number of rules in this set * * @return int */ public function count() { return count($this->_rules); } }