diff options
Diffstat (limited to 'kohana/libraries/Validation.php')
| -rw-r--r-- | kohana/libraries/Validation.php | 773 |
1 files changed, 0 insertions, 773 deletions
diff --git a/kohana/libraries/Validation.php b/kohana/libraries/Validation.php deleted file mode 100644 index 172ff66e..00000000 --- a/kohana/libraries/Validation.php +++ /dev/null @@ -1,773 +0,0 @@ -<?php defined('SYSPATH') or die('No direct script access.'); -/** - * Validation library. - * - * $Id$ - * - * @package Validation - * @author Kohana Team - * @copyright (c) 2007-2008 Kohana Team - * @license http://kohanaphp.com/license.html - */ -class Validation_Core extends ArrayObject { - - // Unique "any field" key - protected $any_field; - - // Array fields - protected $array_fields = array(); - - // Filters - protected $pre_filters = array(); - protected $post_filters = array(); - - // Rules and callbacks - protected $rules = array(); - protected $callbacks = array(); - - // Rules that are allowed to run on empty fields - protected $empty_rules = array('required', 'matches'); - - // Errors - protected $errors = array(); - protected $messages = array(); - - // Checks if there is data to validate. - protected $submitted; - - /** - * Creates a new Validation instance. - * - * @param array array to use for validation - * @return object - */ - public static function factory($array = NULL) - { - return new Validation( ! is_array($array) ? $_POST : $array); - } - - /** - * Sets the unique "any field" key and creates an ArrayObject from the - * passed array. - * - * @param array array to validate - * @return void - */ - public function __construct(array $array) - { - // Set a dynamic, unique "any field" key - $this->any_field = uniqid(NULL, TRUE); - - // Test if there is any actual data - $this->submitted = (count($array) > 0); - - parent::__construct($array, ArrayObject::ARRAY_AS_PROPS | ArrayObject::STD_PROP_LIST); - } - - /** - * Test if the data has been submitted. - * - * @return boolean - */ - public function submitted($value = NULL) - { - if (is_bool($value)) - { - $this->submitted = $value; - } - - return $this->submitted; - } - - /** - * Returns the ArrayObject values. - * - * @return array - */ - public function as_array() - { - return $this->getArrayCopy(); - } - - /** - * Returns the ArrayObject values, removing all inputs without rules. - * To choose specific inputs, list the field name as arguments. - * - * @return array - */ - public function safe_array() - { - // All the fields that are being validated - $all_fields = array_unique(array_merge - ( - array_keys($this->pre_filters), - array_keys($this->rules), - array_keys($this->callbacks), - array_keys($this->post_filters) - )); - - // Load choices - $choices = func_get_args(); - $choices = empty($choices) ? NULL : array_combine($choices, $choices); - - $safe = array(); - foreach ($all_fields as $i => $field) - { - // Ignore "any field" key - if ($field === $this->any_field) continue; - - if (isset($this->array_fields[$field])) - { - // Use the key field - $field = $this->array_fields[$field]; - } - - if ($choices === NULL OR isset($choices[$field])) - { - // Make sure all fields are defined - $safe[$field] = isset($this[$field]) ? $this[$field] : NULL; - } - } - - return $safe; - } - - /** - * Add additional rules that will forced, even for empty fields. All arguments - * passed will be appended to the list. - * - * @chainable - * @param string rule name - * @return object - */ - public function allow_empty_rules($rules) - { - // Any number of args are supported - $rules = func_get_args(); - - // Merge the allowed rules - $this->empty_rules = array_merge($this->empty_rules, $rules); - - return $this; - } - - /** - * Add a pre-filter to one or more inputs. - * - * @chainable - * @param callback filter - * @param string fields to apply filter to, use TRUE for all fields - * @return object - */ - public function pre_filter($filter, $field = TRUE) - { - if ( ! is_callable($filter)) - throw new Kohana_Exception('validation.filter_not_callable'); - - $filter = (is_string($filter) AND strpos($filter, '::') !== FALSE) ? explode('::', $filter) : $filter; - - if ($field === TRUE) - { - // Handle "any field" filters - $fields = array($this->any_field); - } - else - { - // Add the filter to specific inputs - $fields = func_get_args(); - $fields = array_slice($fields, 1); - } - - foreach ($fields as $field) - { - if (strpos($field, '.') > 0) - { - // Field keys - $keys = explode('.', $field); - - // Add to array fields - $this->array_fields[$field] = $keys[0]; - } - - // Add the filter to specified field - $this->pre_filters[$field][] = $filter; - } - - return $this; - } - - /** - * Add a post-filter to one or more inputs. - * - * @chainable - * @param callback filter - * @param string fields to apply filter to, use TRUE for all fields - * @return object - */ - public function post_filter($filter, $field = TRUE) - { - if ( ! is_callable($filter, TRUE)) - throw new Kohana_Exception('validation.filter_not_callable'); - - $filter = (is_string($filter) AND strpos($filter, '::') !== FALSE) ? explode('::', $filter) : $filter; - - if ($field === TRUE) - { - // Handle "any field" filters - $fields = array($this->any_field); - } - else - { - // Add the filter to specific inputs - $fields = func_get_args(); - $fields = array_slice($fields, 1); - } - - foreach ($fields as $field) - { - if (strpos($field, '.') > 0) - { - // Field keys - $keys = explode('.', $field); - - // Add to array fields - $this->array_fields[$field] = $keys[0]; - } - - // Add the filter to specified field - $this->post_filters[$field][] = $filter; - } - - return $this; - } - - /** - * Add rules to a field. Rules are callbacks or validation methods. Rules can - * only return TRUE or FALSE. - * - * @chainable - * @param string field name - * @param callback rules (unlimited number) - * @return object - */ - public function add_rules($field, $rules) - { - // Handle "any field" filters - ($field === TRUE) and $field = $this->any_field; - - // Get the rules - $rules = func_get_args(); - $rules = array_slice($rules, 1); - - foreach ($rules as $rule) - { - // Rule arguments - $args = NULL; - - if (is_string($rule)) - { - if (preg_match('/^([^\[]++)\[(.+)\]$/', $rule, $matches)) - { - // Split the rule into the function and args - $rule = $matches[1]; - $args = preg_split('/(?<!\\\\),\s*/', $matches[2]); - - // Replace escaped comma with comma - $args = str_replace('\,', ',', $args); - } - - if (method_exists($this, $rule)) - { - // Make the rule a valid callback - $rule = array($this, $rule); - } - elseif (method_exists('valid', $rule)) - { - // Make the rule a callback for the valid:: helper - $rule = array('valid', $rule); - } - } - - if ( ! is_callable($rule, TRUE)) - throw new Kohana_Exception('validation.rule_not_callable'); - - $rule = (is_string($rule) AND strpos($rule, '::') !== FALSE) ? explode('::', $rule) : $rule; - - if (strpos($field, '.') > 0) - { - // Field keys - $keys = explode('.', $field); - - // Add to array fields - $this->array_fields[$field] = $keys[0]; - } - - // Add the rule to specified field - $this->rules[$field][] = array($rule, $args); - } - - return $this; - } - - /** - * Add callbacks to a field. Callbacks must accept the Validation object - * and the input name. Callback returns are not processed. - * - * @chainable - * @param string field name - * @param callbacks callbacks (unlimited number) - * @return object - */ - public function add_callbacks($field, $callbacks) - { - // Handle "any field" filters - ($field === TRUE) and $field = $this->any_field; - - if (func_get_args() > 2) - { - // Multiple callback - $callbacks = array_slice(func_get_args(), 1); - } - else - { - // Only one callback - $callbacks = array($callbacks); - } - - foreach ($callbacks as $callback) - { - if ( ! is_callable($callback, TRUE)) - throw new Kohana_Exception('validation.callback_not_callable'); - - $callback = (is_string($callback) AND strpos($callback, '::') !== FALSE) ? explode('::', $callback) : $callback; - - if (strpos($field, '.') > 0) - { - // Field keys - $keys = explode('.', $field); - - // Add to array fields - $this->array_fields[$field] = $keys[0]; - } - - // Add the callback to specified field - $this->callbacks[$field][] = $callback; - } - - return $this; - } - - /** - * Validate by processing pre-filters, rules, callbacks, and post-filters. - * All fields that have filters, rules, or callbacks will be initialized if - * they are undefined. Validation will only be run if there is data already - * in the array. - * - * @return bool - */ - public function validate() - { - // All the fields that are being validated - $all_fields = array_unique(array_merge - ( - array_keys($this->pre_filters), - array_keys($this->rules), - array_keys($this->callbacks), - array_keys($this->post_filters) - )); - - // Copy the array from the object, to optimize multiple sets - $object_array = $this->getArrayCopy(); - - foreach ($all_fields as $i => $field) - { - if ($field === $this->any_field) - { - // Remove "any field" from the list of fields - unset($all_fields[$i]); - continue; - } - - if (substr($field, -2) === '.*') - { - // Set the key to be an array - Kohana::key_string_set($object_array, substr($field, 0, -2), array()); - } - else - { - // Set the key to be NULL - Kohana::key_string_set($object_array, $field, NULL); - } - } - - // Swap the array back into the object - $this->exchangeArray($object_array); - - // Reset all fields to ALL defined fields - $all_fields = array_keys($this->getArrayCopy()); - - foreach ($this->pre_filters as $field => $calls) - { - foreach ($calls as $func) - { - if ($field === $this->any_field) - { - foreach ($all_fields as $f) - { - // Process each filter - $this[$f] = is_array($this[$f]) ? arr::map_recursive($func, $this[$f]) : call_user_func($func, $this[$f]); - } - } - else - { - // Process each filter - $this[$field] = is_array($this[$field]) ? arr::map_recursive($func, $this[$field]) : call_user_func($func, $this[$field]); - } - } - } - - if ($this->submitted === FALSE) - return FALSE; - - foreach ($this->rules as $field => $calls) - { - foreach ($calls as $call) - { - // Split the rule into function and args - list($func, $args) = $call; - - if ($field === $this->any_field) - { - foreach ($all_fields as $f) - { - if (isset($this->array_fields[$f])) - { - // Use the field key - $f_key = $this->array_fields[$f]; - - // Prevent other rules from running when this field already has errors - if ( ! empty($this->errors[$f_key])) break; - - // Don't process rules on empty fields - if ( ! in_array($func[1], $this->empty_rules, TRUE) AND $this[$f_key] == NULL) - continue; - - foreach ($this[$f_key] as $k => $v) - { - if ( ! call_user_func($func, $this[$f_key][$k], $args)) - { - // Run each rule - $this->errors[$f_key] = is_array($func) ? $func[1] : $func; - } - } - } - else - { - // Prevent other rules from running when this field already has errors - if ( ! empty($this->errors[$f])) break; - - // Don't process rules on empty fields - if ( ! in_array($func[1], $this->empty_rules, TRUE) AND $this[$f] == NULL) - continue; - - if ( ! call_user_func($func, $this[$f], $args)) - { - // Run each rule - $this->errors[$f] = is_array($func) ? $func[1] : $func; - } - } - } - } - else - { - if (isset($this->array_fields[$field])) - { - // Use the field key - $field_key = $this->array_fields[$field]; - - // Prevent other rules from running when this field already has errors - if ( ! empty($this->errors[$field_key])) break; - - // Don't process rules on empty fields - if ( ! in_array($func[1], $this->empty_rules, TRUE) AND $this[$field_key] == NULL) - continue; - - foreach ($this[$field_key] as $k => $val) - { - if ( ! call_user_func($func, $this[$field_key][$k], $args)) - { - // Run each rule - $this->errors[$field_key] = is_array($func) ? $func[1] : $func; - - // Stop after an error is found - break 2; - } - } - } - else - { - // Prevent other rules from running when this field already has errors - if ( ! empty($this->errors[$field])) break; - - // Don't process rules on empty fields - if ( ! in_array($func[1], $this->empty_rules, TRUE) AND $this[$field] == NULL) - continue; - - if ( ! call_user_func($func, $this[$field], $args)) - { - // Run each rule - $this->errors[$field] = is_array($func) ? $func[1] : $func; - - // Stop after an error is found - break; - } - } - } - } - } - - foreach ($this->callbacks as $field => $calls) - { - foreach ($calls as $func) - { - if ($field === $this->any_field) - { - foreach ($all_fields as $f) - { - // Execute the callback - call_user_func($func, $this, $f); - - // Stop after an error is found - if ( ! empty($errors[$f])) break 2; - } - } - else - { - // Execute the callback - call_user_func($func, $this, $field); - - // Stop after an error is found - if ( ! empty($errors[$field])) break; - } - } - } - - foreach ($this->post_filters as $field => $calls) - { - foreach ($calls as $func) - { - if ($field === $this->any_field) - { - foreach ($all_fields as $f) - { - if (isset($this->array_fields[$f])) - { - // Use the field key - $f = $this->array_fields[$f]; - } - - // Process each filter - $this[$f] = is_array($this[$f]) ? array_map($func, $this[$f]) : call_user_func($func, $this[$f]); - } - } - else - { - if (isset($this->array_fields[$field])) - { - // Use the field key - $field = $this->array_fields[$field]; - } - - // Process each filter - $this[$field] = is_array($this[$field]) ? array_map($func, $this[$field]) : call_user_func($func, $this[$field]); - } - } - } - - // Return TRUE if there are no errors - return (count($this->errors) === 0); - } - - /** - * Add an error to an input. - * - * @chainable - * @param string input name - * @param string unique error name - * @return object - */ - public function add_error($field, $name) - { - if (isset($this[$field])) - { - $this->errors[$field] = $name; - } - - return $this; - } - - /** - * Sets or returns the message for an input. - * - * @chainable - * @param string input key - * @param string message to set - * @return string|object - */ - public function message($input = NULL, $message = NULL) - { - if ($message === NULL) - { - if ($input === NULL) - { - $messages = array(); - $keys = array_keys($this->messages); - - foreach ($keys as $input) - { - $messages[] = $this->message($input); - } - - return implode("\n", $messages); - } - - // Return nothing if no message exists - if (empty($this->messages[$input])) - return ''; - - // Return the HTML message string - return $this->messages[$input]; - } - else - { - $this->messages[$input] = $message; - } - - return $this; - } - - /** - * Return the errors array. - * - * @param boolean load errors from a lang file - * @return array - */ - public function errors($file = NULL) - { - if ($file === NULL) - { - return $this->errors; - } - else - { - $errors = array(); - foreach ($this->errors as $input => $error) - { - // Key for this input error - $key = "$file.$input.$error"; - - if (($errors[$input] = Kohana::lang($key)) === $key) - { - // Get the default error message - $errors[$input] = Kohana::lang("$file.$input.default"); - } - } - - return $errors; - } - } - - /** - * Rule: required. Generates an error if the field has an empty value. - * - * @param mixed input value - * @return bool - */ - public function required($str) - { - return ! ($str === '' OR $str === NULL OR $str === FALSE OR (is_array($str) AND empty($str))); - } - - /** - * Rule: matches. Generates an error if the field does not match one or more - * other fields. - * - * @param mixed input value - * @param array input names to match against - * @return bool - */ - public function matches($str, array $inputs) - { - foreach ($inputs as $key) - { - if ($str !== (isset($this[$key]) ? $this[$key] : NULL)) - return FALSE; - } - - return TRUE; - } - - /** - * Rule: length. Generates an error if the field is too long or too short. - * - * @param mixed input value - * @param array minimum, maximum, or exact length to match - * @return bool - */ - public function length($str, array $length) - { - if ( ! is_string($str)) - return FALSE; - - $size = utf8::strlen($str); - $status = FALSE; - - if (count($length) > 1) - { - list ($min, $max) = $length; - - if ($size >= $min AND $size <= $max) - { - $status = TRUE; - } - } - else - { - $status = ($size === (int) $length[0]); - } - - return $status; - } - - /** - * Rule: depends_on. Generates an error if the field does not depend on one - * or more other fields. - * - * @param mixed field name - * @param array field names to check dependency - * @return bool - */ - public function depends_on($field, array $fields) - { - foreach ($fields as $depends_on) - { - if ( ! isset($this[$depends_on]) OR $this[$depends_on] == NULL) - return FALSE; - } - - return TRUE; - } - - /** - * Rule: chars. Generates an error if the field contains characters outside of the list. - * - * @param string field value - * @param array allowed characters - * @return bool - */ - public function chars($value, array $chars) - { - return ! preg_match('![^'.preg_quote(implode(',', $chars)).']!', $value); - } - -} // End Validation |
