diff --git a/cake/libs/validation.php b/cake/libs/validation.php index 326c49698..5714b6594 100644 --- a/cake/libs/validation.php +++ b/cake/libs/validation.php @@ -2,15 +2,15 @@ /** * Validation Class. Used for validation of model data * - * PHP versions 4 and 5 + * PHP Version 5.x * * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) - * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * - * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://cakephp.org CakePHP(tm) Project * @package cake * @subpackage cake.cake.libs @@ -20,6 +20,7 @@ if (!class_exists('Multibyte')) { App::import('Core', 'Multibyte', false); } + /** * Offers different validation methods. * @@ -29,82 +30,22 @@ if (!class_exists('Multibyte')) { */ class Validation extends Object { -/** - * Set the the value of methods $check param. - * - * @var string - * @access public - */ - public $check = null; - -/** - * Set to a valid regular expression in the class methods. - * Can be set from $regex param also - * - * @var string - * @access public - */ - public $regex = null; - /** * Some complex patterns needed in multiple places * * @var array - * @access private */ - private $__pattern = array( + private static $__pattern = array( 'hostname' => '(?:[a-z0-9][-a-z0-9]*\.)*(?:[a-z0-9][-a-z0-9]{0,62})\.(?:(?:[a-z]{2}\.)?[a-z]{2,4}|museum|travel)' ); -/** - * Some class methods use a country to determine proper validation. - * This can be passed to methods in the $country param - * - * @var string - * @access public - */ - public $country = null; - -/** - * Some class methods use a deeper validation when set to true - * - * @var string - * @access public - */ - public $deep = null; - -/** - * Some class methods use the $type param to determine which validation to perfom in the method - * - * @var string - * @access public - */ - public $type = null; - /** * Holds an array of errors messages set in this class. * These are used for debugging purposes * * @var array - * @access public */ - public $errors = array(); - -/** - * Gets a reference to the Validation object instance - * - * @return object Validation instance - * @access public - * @static - */ - function &getInstance() { - static $instance = array(); - - if (!$instance) { - $instance[0] =& new Validation(); - } - return $instance[0]; - } + public static $errors = array(); /** * Checks that a string contains something other than whitespace @@ -117,20 +58,15 @@ class Validation extends Object { * @param mixed $check Value to check * @return boolean Success */ - public function notEmpty($check) { - $_this =& Validation::getInstance(); - $_this->__reset(); - $_this->check = $check; - + public static function notEmpty($check) { if (is_array($check)) { - $_this->_extract($check); + extract(self::_defaults($check)); } - if (empty($_this->check) && $_this->check != '0') { + if (empty($check) && $check != '0') { return false; } - $_this->regex = '/[^\s]+/m'; - return $_this->_check(); + return self::_check($check, '/[^\s]+/m'); } /** @@ -144,20 +80,15 @@ class Validation extends Object { * @param mixed $check Value to check * @return boolean Success */ - public function alphaNumeric($check) { - $_this =& Validation::getInstance(); - $_this->__reset(); - $_this->check = $check; - + public static function alphaNumeric($check) { if (is_array($check)) { - $_this->_extract($check); + extract(self::_defaults($check)); } - if (empty($_this->check) && $_this->check != '0') { + if (empty($check) && $check != '0') { return false; } - $_this->regex = '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/mu'; - return $_this->_check(); + return self::_check($check, '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/mu'); } /** @@ -170,7 +101,7 @@ class Validation extends Object { * @param integer $max Maximum value in range (inclusive) * @return boolean Success */ - public function between($check, $min, $max) { + public static function between($check, $min, $max) { $length = mb_strlen($check); return ($length >= $min && $length <= $max); } @@ -185,17 +116,11 @@ class Validation extends Object { * @param mixed $check Value to check * @return boolean Success */ - public function blank($check) { - $_this =& Validation::getInstance(); - $_this->__reset(); - $_this->check = $check; - + public static function blank($check) { if (is_array($check)) { - $_this->_extract($check); + extract(self::_defaults($check)); } - - $_this->regex = '/[^\\s]/'; - return !$_this->_check(); + return !self::_check($check, '/[^\\s]/'); } /** @@ -209,29 +134,21 @@ class Validation extends Object { * @param boolean $deep set to true this will check the Luhn algorithm of the credit card. * @param string $regex A custom regex can also be passed, this will be used instead of the defined regex values * @return boolean Success - * @access public * @see Validation::luhn() */ - function cc($check, $type = 'fast', $deep = false, $regex = null) { - $_this =& Validation::getInstance(); - $_this->__reset(); - $_this->check = $check; - $_this->type = $type; - $_this->deep = $deep; - $_this->regex = $regex; - + public static function cc($check, $type = 'fast', $deep = false, $regex = null) { if (is_array($check)) { - $_this->_extract($check); + extract(self::_defaults($check)); } - $_this->check = str_replace(array('-', ' '), '', $_this->check); - if (mb_strlen($_this->check) < 13) { + $check = str_replace(array('-', ' '), '', $check); + if (mb_strlen($check) < 13) { return false; } - if (!is_null($_this->regex)) { - if ($_this->_check()) { - return $_this->luhn(); + if (!is_null($regex)) { + if (self::_check($check, $regex)) { + return self::luhn($check, $deep); } } $cards = array( @@ -248,32 +165,30 @@ class Validation extends Object { 'solo' => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/', 'switch' => '/^(?:49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})\\d{10}(\\d{2,3})?)|(?:564182\\d{10}(\\d{2,3})?)|(6(3(33[0-4][0-9])|759[0-9]{2})\\d{10}(\\d{2,3})?)$/', 'visa' => '/^4\\d{12}(\\d{3})?$/', - 'voyager' => '/^8699[0-9]{11}$/' - ), - 'fast' => '/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$/' - ); + 'voyager' => '/^8699[0-9]{11}$/'), + 'fast' => '/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$/'); - if (is_array($_this->type)) { - foreach ($_this->type as $value) { - $_this->regex = $cards['all'][strtolower($value)]; + if (is_array($type)) { + foreach ($type as $value) { + $regex = $cards['all'][strtolower($value)]; - if ($_this->_check()) { - return $_this->luhn(); + if (self::_check($check, $regex)) { + return self::luhn($check, $deep); } } - } elseif ($_this->type == 'all') { + } elseif ($type == 'all') { foreach ($cards['all'] as $value) { - $_this->regex = $value; + $regex = $value; - if ($_this->_check()) { - return $_this->luhn(); + if (self::_check($check, $regex)) { + return self::luhn($check, $deep); } } } else { - $_this->regex = $cards['fast']; + $regex = $cards['fast']; - if ($_this->_check()) { - return $_this->luhn(); + if (self::_check($check, $regex)) { + return self::luhn($check, $deep); } } } @@ -289,7 +204,7 @@ class Validation extends Object { * @param integer $check2 only needed if $check1 is a string * @return boolean Success */ - public function comparison($check1, $operator = null, $check2 = null) { + public static function comparison($check1, $operator = null, $check2 = null) { if (is_array($check1)) { extract($check1, EXTR_OVERWRITE); } @@ -333,8 +248,7 @@ class Validation extends Object { } break; default: - $_this =& Validation::getInstance(); - $_this->errors[] = __('You must define the $operator parameter for Validation::comparison()'); + self::$errors[] = __('You must define the $operator parameter for Validation::comparison()', true); break; } return false; @@ -348,19 +262,15 @@ class Validation extends Object { * @param string $regex If $check is passed as a string, $regex must also be set to valid regular expression * @return boolean Success */ - public function custom($check, $regex = null) { - $_this =& Validation::getInstance(); - $_this->__reset(); - $_this->check = $check; - $_this->regex = $regex; + public static function custom($check, $regex = null) { if (is_array($check)) { - $_this->_extract($check); + extract(self::_defaults($check)); } - if ($_this->regex === null) { - $_this->errors[] = __('You must define a regular expression for Validation::custom()'); + if ($regex === null) { + self::$errors[] = __('You must define a regular expression for Validation::custom()', true); return false; } - return $_this->_check(); + return self::_check($check, $regex); } /** @@ -369,24 +279,19 @@ class Validation extends Object { * * @param string $check a valid date string * @param mixed $format Use a string or an array of the keys below. Arrays should be passed as array('dmy', 'mdy', etc) - * Keys: dmy 27-12-2006 or 27-12-06 separators can be a space, period, dash, forward slash - * mdy 12-27-2006 or 12-27-06 separators can be a space, period, dash, forward slash - * ymd 2006-12-27 or 06-12-27 separators can be a space, period, dash, forward slash - * dMy 27 December 2006 or 27 Dec 2006 - * Mdy December 27, 2006 or Dec 27, 2006 comma is optional - * My December 2006 or Dec 2006 - * my 12/2006 separators can be a space, period, dash, forward slash + * Keys: dmy 27-12-2006 or 27-12-06 separators can be a space, period, dash, forward slash + * mdy 12-27-2006 or 12-27-06 separators can be a space, period, dash, forward slash + * ymd 2006-12-27 or 06-12-27 separators can be a space, period, dash, forward slash + * dMy 27 December 2006 or 27 Dec 2006 + * Mdy December 27, 2006 or Dec 27, 2006 comma is optional + * My December 2006 or Dec 2006 + * my 12/2006 separators can be a space, period, dash, forward slash * @param string $regex If a custom regular expression is used this is the only validation that will occur. * @return boolean Success */ - public function date($check, $format = 'ymd', $regex = null) { - $_this =& Validation::getInstance(); - $_this->__reset(); - $_this->check = $check; - $_this->regex = $regex; - - if (!is_null($_this->regex)) { - return $_this->_check(); + public static function date($check, $format = 'ymd', $regex = null) { + if (!is_null($regex)) { + return self::_check($check, $regex); } $regex['dmy'] = '%^(?:(?:31(\\/|-|\\.|\\x20)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\\/|-|\\.|\\x20)(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:29(\\/|-|\\.|\\x20)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.|\\x20)(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%'; @@ -399,9 +304,9 @@ class Validation extends Object { $format = (is_array($format)) ? array_values($format) : array($format); foreach ($format as $key) { - $_this->regex = $regex[$key]; + $regex = $regex[$key]; - if ($_this->_check() === true) { + if (self::_check($check, $regex) === true) { return true; } } @@ -416,13 +321,8 @@ class Validation extends Object { * @param string $check a valid time string * @return boolean Success */ - - public function time($check) { - $_this =& Validation::getInstance(); - $_this->__reset(); - $_this->check = $check; - $_this->regex = '%^((0?[1-9]|1[012])(:[0-5]\d){0,2}([AP]M|[ap]m))$|^([01]\d|2[0-3])(:[0-5]\d){0,2}$%'; - return $_this->_check(); + public static function time($check) { + return self::_check($check, '%^((0?[1-9]|1[012])(:[0-5]\d){0,2}([AP]M|[ap]m))$|^([01]\d|2[0-3])(:[0-5]\d){0,2}$%'); } /** @@ -431,7 +331,7 @@ class Validation extends Object { * @param string $check a valid boolean * @return boolean Success */ - public function boolean($check) { + public static function boolean($check) { $booleanList = array(0, 1, '0', '1', true, false); return in_array($check, $booleanList, true); } @@ -445,58 +345,49 @@ class Validation extends Object { * @param string $regex If a custom regular expression is used this is the only validation that will occur. * @return boolean Success */ - public function decimal($check, $places = null, $regex = null) { - $_this =& Validation::getInstance(); - $_this->__reset(); - $_this->regex = $regex; - $_this->check = $check; - - if (is_null($_this->regex)) { + public static function decimal($check, $places = null, $regex = null) { + if (is_null($regex)) { if (is_null($places)) { - $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?$/'; + $regex = '/^[-+]?[0-9]*\\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?$/'; } else { - $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]{'.$places.'}$/'; + $regex = '/^[-+]?[0-9]*\\.{1}[0-9]{'.$places.'}$/'; } } - return $_this->_check(); + return self::_check($check, $regex); } /** * Validates for an email address. * + * Only uses getmxrr() checking for deep validation if PHP 5.3.0+ is used, or + * any PHP version on a non-windows distribution + * * @param string $check Value to check * @param boolean $deep Perform a deeper validation (if true), by also checking availability of host * @param string $regex Regex to use (if none it will use built in regex) * @return boolean Success */ - public function email($check, $deep = false, $regex = null) { - $_this =& Validation::getInstance(); - $_this->__reset(); - $_this->check = $check; - $_this->regex = $regex; - $_this->deep = $deep; - + public static function email($check, $deep = false, $regex = null) { if (is_array($check)) { - $_this->_extract($check); + extract(self::_defaults($check)); } - if (is_null($_this->regex)) { - $_this->regex = '/^[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@' . $_this->__pattern['hostname'] . '$/i'; + if (is_null($regex)) { + $regex = '/^[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@' . self::$__pattern['hostname'] . '$/i'; } - $return = $_this->_check(); - - if ($_this->deep === false || $_this->deep === null) { + $return = self::_check($check, $regex); + if ($deep === false || $deep === null) { return $return; } - if ($return === true && preg_match('/@(' . $_this->__pattern['hostname'] . ')$/i', $_this->check, $regs)) { - if (function_exists('getmxrr')) { - return getmxrr($regs[1], $mxhosts); + if ($return === true && preg_match('/@(' . self::$__pattern['hostname'] . ')$/i', $check, $regs)) { + $host = gethostbynamel($regs[1]); + $return = is_array($host); + $isWindows = (DIRECTORY_SEPARATOR === '\\'); + if (!$isWindows || (version_compare(PHP_VERSION, '5.3.0', '>=') && $isWindows)) { + $return = $return && getmxrr($regs[1], $mxhosts); } - if (function_exists('checkdnsrr')) { - return checkdnsrr($regs[1], 'MX'); - } - return is_array(gethostbynamel($regs[1])); + return $return; } return false; } @@ -508,7 +399,7 @@ class Validation extends Object { * @param mixed $comparedTo Value to compare * @return boolean Success */ - public function equalTo($check, $comparedTo) { + public static function equalTo($check, $comparedTo) { return ($check === $comparedTo); } @@ -519,9 +410,9 @@ class Validation extends Object { * @param array $extensions file extenstions to allow * @return boolean Success */ - public function extension($check, $extensions = array('gif', 'jpeg', 'png', 'jpg')) { + public static function extension($check, $extensions = array('gif', 'jpeg', 'png', 'jpg')) { if (is_array($check)) { - return Validation::extension(array_shift($check), $extensions); + return self::extension(array_shift($check), $extensions); } $extension = strtolower(array_pop(explode('.', $check))); foreach ($extensions as $value) { @@ -535,58 +426,12 @@ class Validation extends Object { /** * Validation of an IP address. * - * Valid IP version strings for type restriction are: - * - both: Check both IPv4 and IPv6, return true if the supplied address matches either version - * - IPv4: Version 4 (Eg: 127.0.0.1, 192.168.10.123, 203.211.24.8) - * - IPv6: Version 6 (Eg: ::1, 2001:0db8::1428:57ab) - * * @param string $check The string to test. - * @param string $type The IP Version to test against + * @param string $ipVersion The IP Protocol version to validate against * @return boolean Success */ - public function ip($check, $type = 'both') { - $_this =& Validation::getInstance(); - $success = false; - $type = strtolower($type); - if ($type === 'ipv4' || $type === 'both') { - $success |= $_this->_ipv4($check); - } - if ($type === 'ipv6' || $type === 'both') { - $success |= $_this->_ipv6($check); - } - return $success; - } - -/** - * Validation of IPv4 addresses. - * - * @param string $check IP Address to test - * @return boolean Success - */ - protected function _ipv4($check) { - if (function_exists('filter_var')) { - return filter_var($check, FILTER_VALIDATE_IP, array('flags' => FILTER_FLAG_IPV4)) !== false; - } - $this->__populateIp(); - $this->check = $check; - $this->regex = '/^' . $this->__pattern['IPv4'] . '$/'; - return $this->_check(); - } - -/** - * Validation of IPv6 addresses. - * - * @param string $check IP Address to test - * @return boolean Success - */ - protected function _ipv6($check) { - if (function_exists('filter_var')) { - return filter_var($check, FILTER_VALIDATE_IP, array('flags' => FILTER_FLAG_IPV6)) !== false; - } - $this->__populateIp(); - $this->check = $check; - $this->regex = '/^' . $this->__pattern['IPv6'] . '$/'; - return $this->_check(); + public function ip($check, $type = 'IPv4') { + return (boolean) filter_var($check, FILTER_VALIDATE_IP); } /** @@ -596,9 +441,8 @@ class Validation extends Object { * @param integer $min The minimal string length * @return boolean Success */ - public function minLength($check, $min) { - $length = mb_strlen($check); - return ($length >= $min); + public static function minLength($check, $min) { + return mb_strlen($check) >= $min; } /** @@ -608,9 +452,8 @@ class Validation extends Object { * @param integer $max The maximal string length * @return boolean Success */ - public function maxLength($check, $max) { - $length = mb_strlen($check); - return ($length <= $max); + public static function maxLength($check, $max) { + return mb_strlen($check) <= $max; } /** @@ -620,16 +463,13 @@ class Validation extends Object { * @param string $symbolPosition Where symbol is located (left/right) * @return boolean Success */ - public function money($check, $symbolPosition = 'left') { - $_this =& Validation::getInstance(); - $_this->check = $check; - + public static function money($check, $symbolPosition = 'left') { if ($symbolPosition == 'right') { - $_this->regex = '/^(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?(?regex = '/^(?!\x{00a2})\p{Sc}?(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?$/u'; + $regex = '/^(?!\x{00a2})\p{Sc}?(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?$/u'; } - return $_this->_check(); + return self::_check($check, $regex); } /** @@ -645,7 +485,7 @@ class Validation extends Object { * @param mixed $options Options for the check. * @return boolean Success */ - public function multiple($check, $options = array()) { + public static function multiple($check, $options = array()) { $defaults = array('in' => null, 'max' => null, 'min' => null); $options = array_merge($defaults, $options); $check = array_filter((array)$check); @@ -674,7 +514,7 @@ class Validation extends Object { * @param string $check Value to check * @return boolean Succcess */ - public function numeric($check) { + public static function numeric($check) { return is_numeric($check); } @@ -686,29 +526,25 @@ class Validation extends Object { * @param string $country Country code (defaults to 'all') * @return boolean Success */ - public function phone($check, $regex = null, $country = 'all') { - $_this =& Validation::getInstance(); - $_this->check = $check; - $_this->regex = $regex; - $_this->country = $country; + public static function phone($check, $regex = null, $country = 'all') { if (is_array($check)) { - $_this->_extract($check); + extract(self::_defaults($check)); } - if (is_null($_this->regex)) { - switch ($_this->country) { + if (is_null($regex)) { + switch ($country) { case 'us': case 'all': case 'can': // includes all NANPA members. see http://en.wikipedia.org/wiki/North_American_Numbering_Plan#List_of_NANPA_countries_and_territories - $_this->regex = '/^(?:\+?1)?[-. ]?\\(?[2-9][0-8][0-9]\\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}$/'; + $regex = '/^(?:\+?1)?[-. ]?\\(?[2-9][0-8][0-9]\\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}$/'; break; } } - if (empty($_this->regex)) { - return $_this->_pass('phone', $check, $country); + if (empty($regex)) { + return self::_pass('phone', $check, $country); } - return $_this->_check(); + return self::_check($check, $regex); } /** @@ -719,42 +555,35 @@ class Validation extends Object { * @param string $country Country to use for formatting * @return boolean Success */ - public function postal($check, $regex = null, $country = null) { - $_this =& Validation::getInstance(); - $_this->check = $check; - $_this->regex = $regex; - $_this->country = $country; + public static function postal($check, $regex = null, $country = 'us') { if (is_array($check)) { - $_this->_extract($check); - } - if (empty($country)) { - $_this->country = 'us'; + extract(self::_defaults($check)); } - if (is_null($_this->regex)) { - switch ($_this->country) { + if (is_null($regex)) { + switch ($country) { case 'uk': - $_this->regex = '/\\A\\b[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}\\b\\z/i'; + $regex = '/\\A\\b[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}\\b\\z/i'; break; case 'ca': - $_this->regex = '/\\A\\b[ABCEGHJKLMNPRSTVXY][0-9][A-Z] ?[0-9][A-Z][0-9]\\b\\z/i'; + $regex = '/\\A\\b[ABCEGHJKLMNPRSTVXY][0-9][A-Z] [0-9][A-Z][0-9]\\b\\z/i'; break; case 'it': case 'de': - $_this->regex = '/^[0-9]{5}$/i'; + $regex = '/^[0-9]{5}$/i'; break; case 'be': - $_this->regex = '/^[1-9]{1}[0-9]{3}$/i'; + $regex = '/^[1-9]{1}[0-9]{3}$/i'; break; case 'us': - $_this->regex = '/\\A\\b[0-9]{5}(?:-[0-9]{4})?\\b\\z/i'; + $regex = '/\\A\\b[0-9]{5}(?:-[0-9]{4})?\\b\\z/i'; break; } } - if (empty($_this->regex)) { - return $_this->_pass('postal', $check, $country); + if (empty($regex)) { + return self::_pass('postal', $check, $country); } - return $_this->_check(); + return self::_check($check, $regex); } /** @@ -767,7 +596,7 @@ class Validation extends Object { * @param integer $upper Upper limit * @return boolean Success */ - public function range($check, $lower = null, $upper = null) { + public static function range($check, $lower = null, $upper = null) { if (!is_numeric($check)) { return false; } @@ -785,45 +614,28 @@ class Validation extends Object { * @param string $country Country * @return boolean Success */ - public function ssn($check, $regex = null, $country = null) { - $_this =& Validation::getInstance(); - $_this->check = $check; - $_this->regex = $regex; - $_this->country = $country; + public static function ssn($check, $regex = null, $country = null) { if (is_array($check)) { - $_this->_extract($check); + extract(self::_defaults($check)); } - if (is_null($_this->regex)) { - switch ($_this->country) { + if (is_null($regex)) { + switch ($country) { case 'dk': - $_this->regex = '/\\A\\b[0-9]{6}-[0-9]{4}\\b\\z/i'; + $regex = '/\\A\\b[0-9]{6}-[0-9]{4}\\b\\z/i'; break; case 'nl': - $_this->regex = '/\\A\\b[0-9]{9}\\b\\z/i'; + $regex = '/\\A\\b[0-9]{9}\\b\\z/i'; break; case 'us': - $_this->regex = '/\\A\\b[0-9]{3}-[0-9]{2}-[0-9]{4}\\b\\z/i'; + $regex = '/\\A\\b[0-9]{3}-[0-9]{2}-[0-9]{4}\\b\\z/i'; break; } } - if (empty($_this->regex)) { - return $_this->_pass('ssn', $check, $country); + if (empty($regex)) { + return self::_pass('ssn', $check, $country); } - return $_this->_check(); - } - -/** - * Checks that a value is a valid uuid - http://tools.ietf.org/html/rfc4122 - * - * @param string $check Value to check - * @return boolean Success - */ - public function uuid($check) { - $_this =& Validation::getInstance(); - $_this->check = $check; - $_this->regex = '/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i'; - return $_this->_check(); + return self::_check($check, $regex); } /** @@ -841,20 +653,18 @@ class Validation extends Object { * * @param string $check Value to check * @param boolean $strict Require URL to be prefixed by a valid scheme (one of http(s)/ftp(s)/file/news/gopher) + * @param string $ipVersion The IP Protocol version to validate against * @return boolean Success */ - public function url($check, $strict = false) { - $_this =& Validation::getInstance(); - $_this->__populateIp(); - $_this->check = $check; + public static function url($check, $strict = false) { + self::__populateIp(); $validChars = '([' . preg_quote('!"$&\'()*+,-.@_:;=~') . '\/0-9a-z]|(%[0-9a-f]{2}))'; - $_this->regex = '/^(?:(?:https?|ftps?|file|news|gopher):\/\/)' . (!empty($strict) ? '' : '?') . - '(?:' . $_this->__pattern['IPv4'] . '|\[' . $_this->__pattern['IPv6'] . '\]|' . $_this->__pattern['hostname'] . ')' . - '(?::[1-9][0-9]{0,4})?' . + $regex = '/^(?:(?:https?|ftps?|file|news|gopher):\/\/)' . (!empty($strict) ? '' : '?') . + '(?:' . self::$__pattern['IPv4'] . '|' . self::$__pattern['hostname'] . ')(?::[1-9][0-9]{0,3})?' . '(?:\/?|\/' . $validChars . '*)?' . '(?:\?' . $validChars . '*)?' . '(?:#' . $validChars . '*)?$/i'; - return $_this->_check(); + return self::_check($check, $regex); } /** @@ -864,7 +674,7 @@ class Validation extends Object { * @param array $list List to check against * @return boolean Succcess */ - public function inList($check, $list) { + public static function inList($check, $list) { return in_array($check, $list); } @@ -877,8 +687,8 @@ class Validation extends Object { * @param array $args arguments to send to method * @return mixed user-defined class class method returns */ - public function userDefined($check, $object, $method, $args = null) { - return call_user_func_array(array(&$object, $method), array($check, $args)); + public static function userDefined($check, $object, $method, $args = null) { + return call_user_func_array(array($object, $method), array($check, $args)); } /** @@ -891,14 +701,14 @@ class Validation extends Object { * @param string $classPrefix The prefix for the class to do the validation. * @return mixed Return of Passed method, false on failure */ - protected function _pass($method, $check, $classPrefix) { + protected static function _pass($method, $check, $classPrefix) { $className = ucwords($classPrefix) . 'Validation'; if (!class_exists($className)) { - trigger_error(sprintf(__('Could not find %s class, unable to complete validation.'), $className), E_USER_WARNING); + trigger_error(sprintf(__('Could not find %s class, unable to complete validation.', true), $className), E_USER_WARNING); return false; } - if (!is_callable(array($className, $method))) { - trigger_error(sprintf(__('Method %s does not exist on %s unable to complete validation.'), $method, $className), E_USER_WARNING); + if (!method_exists($className, $method)) { + trigger_error(sprintf(__('Method %s does not exist on %s unable to complete validation.', true), $method, $className), E_USER_WARNING); return false; } $check = (array)$check; @@ -908,15 +718,16 @@ class Validation extends Object { /** * Runs a regular expression match. * + * @param mixed $check Value to check against the $regex expression + * @param string $regex Regular expression * @return boolean Success of match */ - protected function _check() { - $_this =& Validation::getInstance(); - if (preg_match($_this->regex, $_this->check)) { - $_this->error[] = false; + protected static function _check($check, $regex) { + if (preg_match($regex, $check)) { + self::$errors[] = false; return true; } else { - $_this->error[] = true; + self::$errors[] = true; return false; } } @@ -928,25 +739,20 @@ class Validation extends Object { * @param array $params Parameters sent to validation method * @return void */ - protected function _extract($params) { - $_this =& Validation::getInstance(); - extract($params, EXTR_OVERWRITE); - - if (isset($check)) { - $_this->check = $check; - } - if (isset($regex)) { - $_this->regex = $regex; - } - if (isset($country)) { - $_this->country = mb_strtolower($country); - } - if (isset($deep)) { - $_this->deep = $deep; - } - if (isset($type)) { - $_this->type = $type; + protected static function _defaults($params) { + self::__reset(); + $defaults = array( + 'check' => null, + 'regex' => null, + 'country' => null, + 'deep' => false, + 'type' => null + ); + $params = array_merge($defaults, $params); + if ($params['country'] !== null) { + $params['country'] = mb_strtolower($params['country']); } + return $params; } /** @@ -955,37 +761,38 @@ class Validation extends Object { * @see http://en.wikipedia.org/wiki/Luhn_algorithm * @return boolean Success */ - public function luhn() { - $_this =& Validation::getInstance(); - if ($_this->deep !== true) { + public static function luhn($check, $deep = false) { + if (is_array($check)) { + extract(self::_defaults($check)); + } + if ($deep !== true) { return true; } - if ($_this->check == 0) { + if ($check == 0) { return false; } $sum = 0; - $length = strlen($_this->check); + $length = strlen($check); for ($position = 1 - ($length % 2); $position < $length; $position += 2) { - $sum += $_this->check[$position]; + $sum += $check[$position]; } for ($position = ($length % 2); $position < $length; $position += 2) { - $number = $_this->check[$position] * 2; + $number = $check[$position] * 2; $sum += ($number < 10) ? $number : $number - 9; } return ($sum % 10 == 0); } -/* +/** * Lazily popualate the IP address patterns used for validations * * @return void - * @access private */ - private function __populateIp() { - if (!isset($this->__pattern['IPv6'])) { + private static function __populateIp() { + if (!isset(self::$__pattern['IPv6'])) { $pattern = '((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}'; $pattern .= '(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})'; $pattern .= '|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})'; @@ -1001,11 +808,11 @@ class Validation extends Object { $pattern .= '\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4})'; $pattern .= '{1,2})))|(((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))(%.+)?'; - $this->__pattern['IPv6'] = $pattern; + self::$__pattern['IPv6'] = $pattern; } - if (!isset($this->__pattern['IPv4'])) { + if (!isset(self::$__pattern['IPv4'])) { $pattern = '(?:(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])'; - $this->__pattern['IPv4'] = $pattern; + self::$__pattern['IPv4'] = $pattern; } } @@ -1013,16 +820,9 @@ class Validation extends Object { * Reset internal variables for another validation run. * * @return void - * @access private */ - private function __reset() { - $this->check = null; - $this->regex = null; - $this->country = null; - $this->deep = null; - $this->type = null; - $this->error = array(); - $this->errors = array(); + private static function __reset() { + self::$errors = array(); } } ?> \ No newline at end of file diff --git a/cake/tests/cases/libs/validation.test.php b/cake/tests/cases/libs/validation.test.php index dc8f961ae..48dce6859 100644 --- a/cake/tests/cases/libs/validation.test.php +++ b/cake/tests/cases/libs/validation.test.php @@ -2,15 +2,15 @@ /** * ValidationTest file * - * PHP versions 4 and 5 + * PHP Version 5.x * * CakePHP(tm) Tests - * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org) * - * Licensed under The Open Group Test Suite License - * Redistributions of files must retain the above copyright notice. + * Licensed under The Open Group Test Suite License + * Redistributions of files must retain the above copyright notice. * - * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org) * @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests * @package cake * @subpackage cake.tests.cases.libs @@ -32,8 +32,9 @@ class CustomValidator { * * @param string $email * @return boolean + * @access public */ - public function customValidate($check) { + function customValidate($check) { return preg_match('/^[0-9]{3}$/', $check); } } @@ -92,14 +93,6 @@ class TestDeValidation { */ class ValidationTest extends CakeTestCase { -/** - * Validation property - * - * @var mixed null - * @access public - */ - public $Validation = null; - /** * setup method * @@ -107,7 +100,6 @@ class ValidationTest extends CakeTestCase { * @return void */ function setUp() { - $this->Validation =& Validation::getInstance(); $this->_appEncoding = Configure::read('App.encoding'); } @@ -137,15 +129,15 @@ class ValidationTest extends CakeTestCase { $this->assertTrue(Validation::notEmpty('π')); $this->assertFalse(Validation::notEmpty("\t ")); $this->assertFalse(Validation::notEmpty("")); - } /** * testNotEmptyISO88591Encoding method * * @return void + * @access public */ - public function testNotEmptyISO88591AppEncoding() { + function testNotEmptyISO88591AppEncoding() { Configure::write('App.encoding', 'ISO-8859-1'); $this->assertTrue(Validation::notEmpty('abcdefg')); $this->assertTrue(Validation::notEmpty('fasdf ')); @@ -170,11 +162,10 @@ class ValidationTest extends CakeTestCase { $this->assertTrue(Validation::alphaNumeric('0')); $this->assertTrue(Validation::alphaNumeric('abçďĕʑʘπй')); $this->assertTrue(Validation::alphaNumeric('ˇˆๆゞ')); - $this->assertTrue(Validation::alphaNumeric('אกあアꀀ豈')); + $this->assertTrue(Validation::alphaNumeric('אกあアꀀ豈')); $this->assertTrue(Validation::alphaNumeric('Džᾈᾨ')); $this->assertTrue(Validation::alphaNumeric('ÆΔΩЖÇ')); - $this->assertFalse(Validation::alphaNumeric('12 234')); $this->assertFalse(Validation::alphaNumeric('dfd 234')); $this->assertFalse(Validation::alphaNumeric("\n")); @@ -213,7 +204,7 @@ class ValidationTest extends CakeTestCase { function testBetween() { $this->assertTrue(Validation::between('abcdefg', 1, 7)); $this->assertTrue(Validation::between('', 0, 7)); - $this->assertTrue(Validation::between('אกあアꀀ豈', 1, 7)); + $this->assertTrue(Validation::between('אกあアꀀ豈', 1, 7)); $this->assertFalse(Validation::between('abcdefg', 1, 6)); $this->assertFalse(Validation::between('ÆΔΩЖÇ', 1, 3)); @@ -257,7 +248,7 @@ class ValidationTest extends CakeTestCase { * @access public * @return void */ - function testcc() { + function testCc() { //American Express $this->assertTrue(Validation::cc('370482756063980', array('amex'))); $this->assertTrue(Validation::cc('349106433773483', array('amex'))); @@ -703,77 +694,52 @@ class ValidationTest extends CakeTestCase { * @return void */ function testLuhn() { - $this->Validation->deep = true; - //American Express - $this->Validation->check = '370482756063980'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('370482756063980', true)); //BankCard - $this->Validation->check = '5610745867413420'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('5610745867413420', true)); //Diners Club 14 - $this->Validation->check = '30155483651028'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('30155483651028', true)); //2004 MasterCard/Diners Club Alliance International 14 - $this->Validation->check = '36747701998969'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('36747701998969', true)); //2004 MasterCard/Diners Club Alliance US & Canada 16 - $this->Validation->check = '5597511346169950'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('5597511346169950', true)); //Discover - $this->Validation->check = '6011802876467237'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('6011802876467237', true)); //enRoute - $this->Validation->check = '201496944158937'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('201496944158937', true)); //JCB 15 digit - $this->Validation->check = '210034762247893'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('210034762247893', true)); //JCB 16 digit - $this->Validation->check = '3096806857839939'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('3096806857839939', true)); //Maestro (debit card) - $this->Validation->check = '5020147409985219'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('5020147409985219', true)); //Mastercard - $this->Validation->check = '5580424361774366'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('5580424361774366', true)); //Solo 16 - $this->Validation->check = '6767432107064987'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('6767432107064987', true)); //Solo 18 - $this->Validation->check = '676714834398858593'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('676714834398858593', true)); //Solo 19 - $this->Validation->check = '6767838565218340113'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('6767838565218340113', true)); //Switch 16 - $this->Validation->check = '5641829171515733'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('5641829171515733', true)); //Switch 18 - $this->Validation->check = '493622764224625174'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('493622764224625174', true)); //Switch 19 - $this->Validation->check = '6759603460617628716'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('6759603460617628716', true)); //VISA 13 digit - $this->Validation->check = '4024007174754'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('4024007174754', true)); //VISA 16 digit - $this->Validation->check = '4916375389940009'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('4916375389940009', true)); //Visa Electron - $this->Validation->check = '4175003346287100'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('4175003346287100', true)); //Voyager - $this->Validation->check = '869940697287073'; - $this->assertTrue($this->Validation->luhn()); + $this->assertTrue(Validation::luhn('869940697287073', true)); - $this->Validation->check = '0000000000000000'; - $this->assertFalse($this->Validation->luhn()); + $this->assertFalse(Validation::luhn('0000000000000000', true)); - $this->Validation->check = '869940697287173'; - $this->assertFalse($this->Validation->luhn()); + $this->assertFalse(Validation::luhn('869940697287173', true)); } /** @@ -1718,21 +1684,18 @@ class ValidationTest extends CakeTestCase { } /** - * testIp method + * testIpV4 method * * @access public * @return void */ - function testIpv4() { - $this->assertTrue(Validation::ip('0.0.0.0', 'IPv4')); - $this->assertTrue(Validation::ip('192.168.1.156', 'IPv4')); - $this->assertTrue(Validation::ip('255.255.255.255', 'IPv4')); - - $this->assertFalse(Validation::ip('127.0.0', 'IPv4')); - $this->assertFalse(Validation::ip('127.0.0.a', 'IPv4')); - $this->assertFalse(Validation::ip('127.0.0.256', 'IPv4')); - - $this->assertFalse(Validation::ip('2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'IPv4')); + function testIpV4() { + $this->assertTrue(Validation::ip('0.0.0.0')); + $this->assertTrue(Validation::ip('192.168.1.156')); + $this->assertTrue(Validation::ip('255.255.255.255')); + $this->assertFalse(Validation::ip('127.0.0')); + $this->assertFalse(Validation::ip('127.0.0.a')); + $this->assertFalse(Validation::ip('127.0.0.256')); } /** @@ -1773,31 +1736,6 @@ class ValidationTest extends CakeTestCase { $this->assertFalse(Validation::ip('1:2:3::4:5:6:7:8:9', 'IPv6')); $this->assertFalse(Validation::ip('::ffff:2.3.4', 'IPv6')); $this->assertFalse(Validation::ip('::ffff:257.1.2.3', 'IPv6')); - - $this->assertFalse(Validation::ip('0.0.0.0', 'IPv6')); - } - -/** - * testIpBoth method - * - * @return void - */ - function testIpBoth() { - $this->assertTrue(Validation::ip('0.0.0.0')); - $this->assertTrue(Validation::ip('192.168.1.156')); - $this->assertTrue(Validation::ip('255.255.255.255')); - - $this->assertFalse(Validation::ip('127.0.0')); - $this->assertFalse(Validation::ip('127.0.0.a')); - $this->assertFalse(Validation::ip('127.0.0.256')); - - $this->assertTrue(Validation::ip('2001:0db8:85a3:0000:0000:8a2e:0370:7334')); - $this->assertTrue(Validation::ip('2001:db8:85a3:0:0:8a2e:370:7334')); - $this->assertTrue(Validation::ip('2001:db8:85a3::8a2e:370:7334')); - - $this->assertFalse(Validation::ip('2001:db8:85a3::8a2e:37023:7334')); - $this->assertFalse(Validation::ip('2001:db8:85a3::8a2e:370k:7334')); - $this->assertFalse(Validation::ip('1:2:3:4:5:6:7:8:9')); } /** @@ -1873,37 +1811,6 @@ class ValidationTest extends CakeTestCase { $this->assertFalse(Validation::url('www.cakephp.org', true)); $this->assertTrue(Validation::url('http://www.cakephp.org', true)); $this->assertTrue(Validation::url('http://example.com/~userdir/')); - $this->assertTrue(Validation::url('http://example.com/~userdir/subdir/index.html')); - $this->assertTrue(Validation::url('http://www.zwischenraume.de')); - $this->assertTrue(Validation::url('http://www.zwischenraume.cz')); - - $this->assertTrue(Validation::url('http://cakephp.org:80')); - $this->assertTrue(Validation::url('http://cakephp.org:443')); - $this->assertTrue(Validation::url('http://cakephp.org:2000')); - $this->assertTrue(Validation::url('http://cakephp.org:27000')); - $this->assertTrue(Validation::url('http://cakephp.org:65000')); - - $this->assertTrue(Validation::url('[2001:0db8::1428:57ab]')); - $this->assertTrue(Validation::url('[::1]')); - $this->assertTrue(Validation::url('[2001:0db8::1428:57ab]:80')); - $this->assertTrue(Validation::url('[::1]:80')); - $this->assertTrue(Validation::url('http://[2001:0db8::1428:57ab]')); - $this->assertTrue(Validation::url('http://[::1]')); - $this->assertTrue(Validation::url('http://[2001:0db8::1428:57ab]:80')); - $this->assertTrue(Validation::url('http://[::1]:80')); - - $this->assertFalse(Validation::url('[1::2::3]')); - } - - function testUuid() { - $this->assertTrue(Validation::uuid('550e8400-e29b-11d4-a716-446655440000')); - $this->assertFalse(Validation::uuid('BRAP-e29b-11d4-a716-446655440000')); - $this->assertTrue(Validation::uuid('550E8400-e29b-11D4-A716-446655440000')); - $this->assertFalse(Validation::uuid('550e8400-e29b11d4-a716-446655440000')); - $this->assertFalse(Validation::uuid('550e8400-e29b-11d4-a716-4466440000')); - $this->assertFalse(Validation::uuid('550e8400-e29b-11d4-a71-446655440000')); - $this->assertFalse(Validation::uuid('550e8400-e29b-11d-a716-446655440000')); - $this->assertFalse(Validation::uuid('550e8400-e29-11d4-a716-446655440000')); } /** @@ -2121,7 +2028,6 @@ class ValidationTest extends CakeTestCase { $this->assertFalse(Validation::postal('B2A 2AB', null, 'ca')); $this->assertTrue(Validation::postal('X0A 0A2', null, 'ca')); $this->assertTrue(Validation::postal('G4V 4C3', null, 'ca')); - $this->assertTrue(Validation::postal('L4J8D6', null, 'ca')); $this->assertFalse(Validation::postal('111', null, 'us')); $this->assertFalse(Validation::postal('1111', null, 'us')); @@ -2201,5 +2107,12 @@ class ValidationTest extends CakeTestCase { $this->assertTrue(Validation::userDefined('333', $validator, 'customValidate')); } + // function testFile() { + // $this->assertTrue(Validation::file(WWW_ROOT . 'img' . DS . 'cake.icon.gif')); + // $this->assertTrue(Validation::file(WWW_ROOT. 'favicon.ico')); + // $this->assertTrue(Validation::file(WWW_ROOT. 'index.php')); + // $this->assertTrue(Validation::file(WWW_ROOT. 'css' . DS . 'cake.generic.css')); + // $this->assertTrue(Validation::file(TEST_CAKE_CORE_INCLUDE_PATH. 'VERSION.txt')); + // } } ?> \ No newline at end of file