diff options
| author | Patrick Seeger <pseeger@ccwn.org> | 2012-04-13 23:11:05 +0200 |
|---|---|---|
| committer | Patrick Seeger <pseeger@ccwn.org> | 2012-04-13 23:11:05 +0200 |
| commit | 341cc4dd9c53ffbfb863e026dd58549c1082c7a7 (patch) | |
| tree | 1bbbed20313bafb9b063b6b4d894fe580d8b000f /framework/validators | |
Diffstat (limited to 'framework/validators')
21 files changed, 2508 insertions, 0 deletions
diff --git a/framework/validators/CBooleanValidator.php b/framework/validators/CBooleanValidator.php new file mode 100644 index 0000000..d61afc5 --- /dev/null +++ b/framework/validators/CBooleanValidator.php @@ -0,0 +1,93 @@ +<?php +/** + * CBooleanValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CBooleanValidator validates that the attribute value is either {@link trueValue} or {@link falseValue}. + * + * When using the {@link message} property to define a custom error message, the message + * may contain additional placeholders that will be replaced with the actual content. In addition + * to the "{attribute}" placeholder, recognized by all validators (see {@link CValidator}), + * CBooleanValidator allows for the following placeholders to be specified: + * <ul> + * <li>{true}: replaced with value representing the true status {@link trueValue}.</li> + * <li>{false}: replaced with value representing the false status {@link falseValue}.</li> + * </ul> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CBooleanValidator.php 3515 2011-12-28 12:29:24Z mdomba $ + * @package system.validators + */ +class CBooleanValidator extends CValidator +{ + /** + * @var mixed the value representing true status. Defaults to '1'. + */ + public $trueValue='1'; + /** + * @var mixed the value representing false status. Defaults to '0'. + */ + public $falseValue='0'; + /** + * @var boolean whether the comparison to {@link trueValue} and {@link falseValue} is strict. + * When this is true, the attribute value and type must both match those of {@link trueValue} or {@link falseValue}. + * Defaults to false, meaning only the value needs to be matched. + */ + public $strict=false; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + if(!$this->strict && $value!=$this->trueValue && $value!=$this->falseValue + || $this->strict && $value!==$this->trueValue && $value!==$this->falseValue) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be either {true} or {false}.'); + $this->addError($object,$attribute,$message,array( + '{true}'=>$this->trueValue, + '{false}'=>$this->falseValue, + )); + } + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + $message=$this->message!==null ? $this->message : Yii::t('yii','{attribute} must be either {true} or {false}.'); + $message=strtr($message, array( + '{attribute}'=>$object->getAttributeLabel($attribute), + '{true}'=>$this->trueValue, + '{false}'=>$this->falseValue, + )); + return " +if(".($this->allowEmpty ? "$.trim(value)!='' && " : '')."value!=".CJSON::encode($this->trueValue)." && value!=".CJSON::encode($this->falseValue).") { + messages.push(".CJSON::encode($message)."); +} +"; + } +} diff --git a/framework/validators/CCaptchaValidator.php b/framework/validators/CCaptchaValidator.php new file mode 100644 index 0000000..87f844c --- /dev/null +++ b/framework/validators/CCaptchaValidator.php @@ -0,0 +1,123 @@ +<?php +/** + * CCaptchaValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CCaptchaValidator validates that the attribute value is the same as the verification code displayed in the CAPTCHA. + * + * CCaptchaValidator should be used together with {@link CCaptchaAction}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CCaptchaValidator.php 3124 2011-03-25 15:48:05Z qiang.xue $ + * @package system.validators + * @since 1.0 + */ +class CCaptchaValidator extends CValidator +{ + /** + * @var boolean whether the comparison is case sensitive. Defaults to false. + */ + public $caseSensitive=false; + /** + * @var string ID of the action that renders the CAPTCHA image. Defaults to 'captcha', + * meaning the 'captcha' action declared in the current controller. + * This can also be a route consisting of controller ID and action ID. + */ + public $captchaAction='captcha'; + /** + * @var boolean whether the attribute value can be null or empty. + * Defaults to false, meaning the attribute is invalid if it is empty. + */ + public $allowEmpty=false; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + $captcha=$this->getCaptchaAction(); + if(!$captcha->validate($value,$this->caseSensitive)) + { + $message=$this->message!==null?$this->message:Yii::t('yii','The verification code is incorrect.'); + $this->addError($object,$attribute,$message); + } + } + + /** + * Returns the CAPTCHA action object. + * @return CCaptchaAction the action object + * @since 1.1.7 + */ + protected function getCaptchaAction() + { + if(($captcha=Yii::app()->getController()->createAction($this->captchaAction))===null) + { + if(strpos($this->captchaAction,'/')!==false) // contains controller or module + { + if(($ca=Yii::app()->createController($this->captchaAction))!==null) + { + list($controller,$actionID)=$ca; + $captcha=$controller->createAction($actionID); + } + } + if($captcha===null) + throw new CException(Yii::t('yii','CCaptchaValidator.action "{id}" is invalid. Unable to find such an action in the current controller.', + array('{id}'=>$this->captchaAction))); + } + return $captcha; + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + $captcha=$this->getCaptchaAction(); + $message=$this->message!==null ? $this->message : Yii::t('yii','The verification code is incorrect.'); + $message=strtr($message, array( + '{attribute}'=>$object->getAttributeLabel($attribute), + )); + $code=$captcha->getVerifyCode(false); + $hash=$captcha->generateValidationHash($this->caseSensitive ? $code : strtolower($code)); + $js=" +var hash = $('body').data('{$this->captchaAction}.hash'); +if (hash == null) + hash = $hash; +else + hash = hash[".($this->caseSensitive ? 0 : 1)."]; +for(var i=value.length-1, h=0; i >= 0; --i) h+=value.".($this->caseSensitive ? '' : 'toLowerCase().')."charCodeAt(i); +if(h != hash) { + messages.push(".CJSON::encode($message)."); +} +"; + + if($this->allowEmpty) + { + $js=" +if($.trim(value)!='') { + $js +} +"; + } + + return $js; + } +} + diff --git a/framework/validators/CCompareValidator.php b/framework/validators/CCompareValidator.php new file mode 100644 index 0000000..c226b3b --- /dev/null +++ b/framework/validators/CCompareValidator.php @@ -0,0 +1,216 @@ +<?php +/** + * CCompareValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CCompareValidator compares the specified attribute value with another value and validates if they are equal. + * + * The value being compared with can be another attribute value + * (specified via {@link compareAttribute}) or a constant (specified via + * {@link compareValue}. When both are specified, the latter takes + * precedence. If neither is specified, the attribute will be compared + * with another attribute whose name is by appending "_repeat" to the source + * attribute name. + * + * The comparison can be either {@link strict} or not. + * + * CCompareValidator supports different comparison operators. + * Previously, it only compares to see if two values are equal or not. + * + * When using the {@link message} property to define a custom error message, the message + * may contain additional placeholders that will be replaced with the actual content. In addition + * to the "{attribute}" placeholder, recognized by all validators (see {@link CValidator}), + * CCompareValidator allows for the following placeholders to be specified: + * <ul> + * <li>{compareValue}: replaced with the constant value being compared with {@link compareValue}.</li> + * </ul> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CCompareValidator.php 3515 2011-12-28 12:29:24Z mdomba $ + * @package system.validators + * @since 1.0 + */ +class CCompareValidator extends CValidator +{ + /** + * @var string the name of the attribute to be compared with + */ + public $compareAttribute; + /** + * @var string the constant value to be compared with + */ + public $compareValue; + /** + * @var boolean whether the comparison is strict (both value and type must be the same.) + * Defaults to false. + */ + public $strict=false; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to false. + * If this is true, it means the attribute is considered valid when it is empty. + */ + public $allowEmpty=false; + /** + * @var string the operator for comparison. Defaults to '='. + * The followings are valid operators: + * <ul> + * <li>'=' or '==': validates to see if the two values are equal. If {@link strict} is true, the comparison + * will be done in strict mode (i.e. checking value type as well).</li> + * <li>'!=': validates to see if the two values are NOT equal. If {@link strict} is true, the comparison + * will be done in strict mode (i.e. checking value type as well).</li> + * <li>'>': validates to see if the value being validated is greater than the value being compared with.</li> + * <li>'>=': validates to see if the value being validated is greater than or equal to the value being compared with.</li> + * <li>'<': validates to see if the value being validated is less than the value being compared with.</li> + * <li>'<=': validates to see if the value being validated is less than or equal to the value being compared with.</li> + * </ul> + */ + public $operator='='; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + if($this->compareValue!==null) + $compareTo=$compareValue=$this->compareValue; + else + { + $compareAttribute=$this->compareAttribute===null ? $attribute.'_repeat' : $this->compareAttribute; + $compareValue=$object->$compareAttribute; + $compareTo=$object->getAttributeLabel($compareAttribute); + } + + switch($this->operator) + { + case '=': + case '==': + if(($this->strict && $value!==$compareValue) || (!$this->strict && $value!=$compareValue)) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be repeated exactly.'); + $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo)); + } + break; + case '!=': + if(($this->strict && $value===$compareValue) || (!$this->strict && $value==$compareValue)) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must not be equal to "{compareValue}".'); + $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo,'{compareValue}'=>$compareValue)); + } + break; + case '>': + if($value<=$compareValue) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be greater than "{compareValue}".'); + $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo,'{compareValue}'=>$compareValue)); + } + break; + case '>=': + if($value<$compareValue) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be greater than or equal to "{compareValue}".'); + $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo,'{compareValue}'=>$compareValue)); + } + break; + case '<': + if($value>=$compareValue) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be less than "{compareValue}".'); + $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo,'{compareValue}'=>$compareValue)); + } + break; + case '<=': + if($value>$compareValue) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be less than or equal to "{compareValue}".'); + $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo,'{compareValue}'=>$compareValue)); + } + break; + default: + throw new CException(Yii::t('yii','Invalid operator "{operator}".',array('{operator}'=>$this->operator))); + } + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + if($this->compareValue !== null) + { + $compareTo=$this->compareValue; + $compareValue=CJSON::encode($this->compareValue); + } + else + { + $compareAttribute=$this->compareAttribute === null ? $attribute . '_repeat' : $this->compareAttribute; + $compareValue="\$('#" . (CHtml::activeId($object, $compareAttribute)) . "').val()"; + $compareTo=$object->getAttributeLabel($compareAttribute); + } + + $message=$this->message; + switch($this->operator) + { + case '=': + case '==': + if($message===null) + $message=Yii::t('yii','{attribute} must be repeated exactly.'); + $condition='value!='.$compareValue; + break; + case '!=': + if($message===null) + $message=Yii::t('yii','{attribute} must not be equal to "{compareValue}".'); + $condition='value=='.$compareValue; + break; + case '>': + if($message===null) + $message=Yii::t('yii','{attribute} must be greater than "{compareValue}".'); + $condition='parseFloat(value)<=parseFloat('.$compareValue.')'; + break; + case '>=': + if($message===null) + $message=Yii::t('yii','{attribute} must be greater than or equal to "{compareValue}".'); + $condition='parseFloat(value)<parseFloat('.$compareValue.')'; + break; + case '<': + if($message===null) + $message=Yii::t('yii','{attribute} must be less than "{compareValue}".'); + $condition='parseFloat(value)>=parseFloat('.$compareValue.')'; + break; + case '<=': + if($message===null) + $message=Yii::t('yii','{attribute} must be less than or equal to "{compareValue}".'); + $condition='parseFloat(value)>parseFloat('.$compareValue.')'; + break; + default: + throw new CException(Yii::t('yii','Invalid operator "{operator}".',array('{operator}'=>$this->operator))); + } + + $message=strtr($message,array( + '{attribute}'=>$object->getAttributeLabel($attribute), + '{compareValue}'=>$compareTo, + )); + + return " +if(".($this->allowEmpty ? "$.trim(value)!='' && " : '').$condition.") { + messages.push(".CJSON::encode($message)."); +} +"; + } +} diff --git a/framework/validators/CDateValidator.php b/framework/validators/CDateValidator.php new file mode 100644 index 0000000..74b921b --- /dev/null +++ b/framework/validators/CDateValidator.php @@ -0,0 +1,76 @@ +<?php +/** + * CDateValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CDateValidator verifies if the attribute represents a date, time or datetime. + * + * By setting the {@link format} property, one can specify what format the date value + * must be in. If the given date value doesn't follow the format, the attribute is considered as invalid. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CDateValidator.php 2799 2011-01-01 19:31:13Z qiang.xue $ + * @package system.validators + * @since 1.1.7 + */ +class CDateValidator extends CValidator +{ + /** + * @var mixed the format pattern that the date value should follow. + * This can be either a string or an array representing multiple formats. + * Defaults to 'MM/dd/yyyy'. Please see {@link CDateTimeParser} for details + * about how to specify a date format. + */ + public $format='MM/dd/yyyy'; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + /** + * @var string the name of the attribute to receive the parsing result. + * When this property is not null and the validation is successful, the named attribute will + * receive the parsing result. + */ + public $timestampAttribute; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + + $formats=is_string($this->format) ? array($this->format) : $this->format; + $valid=false; + foreach($formats as $format) + { + $timestamp=CDateTimeParser::parse($value,$format,array('month'=>1,'day'=>1,'hour'=>0,'minute'=>0,'second'=>0)); + if($timestamp!==false) + { + $valid=true; + if($this->timestampAttribute!==null) + $object->{$this->timestampAttribute}=$timestamp; + break; + } + } + + if(!$valid) + { + $message=$this->message!==null?$this->message : Yii::t('yii','The format of {attribute} is invalid.'); + $this->addError($object,$attribute,$message); + } + } +} + diff --git a/framework/validators/CDefaultValueValidator.php b/framework/validators/CDefaultValueValidator.php new file mode 100644 index 0000000..24f9e05 --- /dev/null +++ b/framework/validators/CDefaultValueValidator.php @@ -0,0 +1,50 @@ +<?php +/** + * CDefaultValueValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CDefaultValueValidator sets the attributes with the specified value. + * It does not do validation. Its existence is mainly to allow + * specifying attribute default values in a dynamic way. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CDefaultValueValidator.php 3515 2011-12-28 12:29:24Z mdomba $ + * @package system.validators + */ +class CDefaultValueValidator extends CValidator +{ + /** + * @var mixed the default value to be set to the specified attributes. + */ + public $value; + /** + * @var boolean whether to set the default value only when the attribute value is null or empty string. + * Defaults to true. If false, the attribute will always be assigned with the default value, + * even if it is already explicitly assigned a value. + */ + public $setOnEmpty=true; + + /** + * Validates the attribute of the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + if(!$this->setOnEmpty) + $object->$attribute=$this->value; + else + { + $value=$object->$attribute; + if($value===null || $value==='') + $object->$attribute=$this->value; + } + } +} + diff --git a/framework/validators/CEmailValidator.php b/framework/validators/CEmailValidator.php new file mode 100644 index 0000000..68def75 --- /dev/null +++ b/framework/validators/CEmailValidator.php @@ -0,0 +1,118 @@ +<?php +/** + * CEmailValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CEmailValidator validates that the attribute value is a valid email address. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CEmailValidator.php 3515 2011-12-28 12:29:24Z mdomba $ + * @package system.validators + * @since 1.0 + */ +class CEmailValidator extends CValidator +{ + /** + * @var string the regular expression used to validate the attribute value. + * @see http://www.regular-expressions.info/email.html + */ + public $pattern='/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/'; + /** + * @var string the regular expression used to validate email addresses with the name part. + * This property is used only when {@link allowName} is true. + * @see allowName + */ + public $fullPattern='/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/'; + /** + * @var boolean whether to allow name in the email address (e.g. "Qiang Xue <qiang.xue@gmail.com>"). Defaults to false. + * @see fullPattern + */ + public $allowName=false; + /** + * @var boolean whether to check the MX record for the email address. + * Defaults to false. To enable it, you need to make sure the PHP function 'checkdnsrr' + * exists in your PHP installation. + */ + public $checkMX=false; + /** + * @var boolean whether to check port 25 for the email address. + * Defaults to false. + */ + public $checkPort=false; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + if(!$this->validateValue($value)) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} is not a valid email address.'); + $this->addError($object,$attribute,$message); + } + } + + /** + * Validates a static value to see if it is a valid email. + * Note that this method does not respect {@link allowEmpty} property. + * This method is provided so that you can call it directly without going through the model validation rule mechanism. + * @param mixed $value the value to be validated + * @return boolean whether the value is a valid email + * @since 1.1.1 + */ + public function validateValue($value) + { + // make sure string length is limited to avoid DOS attacks + $valid=is_string($value) && strlen($value)<=254 && (preg_match($this->pattern,$value) || $this->allowName && preg_match($this->fullPattern,$value)); + if($valid) + $domain=rtrim(substr($value,strpos($value,'@')+1),'>'); + if($valid && $this->checkMX && function_exists('checkdnsrr')) + $valid=checkdnsrr($domain,'MX'); + if($valid && $this->checkPort && function_exists('fsockopen')) + $valid=fsockopen($domain,25)!==false; + return $valid; + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + $message=$this->message!==null ? $this->message : Yii::t('yii','{attribute} is not a valid email address.'); + $message=strtr($message, array( + '{attribute}'=>$object->getAttributeLabel($attribute), + )); + + $condition="!value.match({$this->pattern})"; + if($this->allowName) + $condition.=" && !value.match({$this->fullPattern})"; + + return " +if(".($this->allowEmpty ? "$.trim(value)!='' && " : '').$condition.") { + messages.push(".CJSON::encode($message)."); +} +"; + } +} diff --git a/framework/validators/CExistValidator.php b/framework/validators/CExistValidator.php new file mode 100644 index 0000000..9c1d5ce --- /dev/null +++ b/framework/validators/CExistValidator.php @@ -0,0 +1,92 @@ +<?php +/** + * CExistValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CExistValidator validates that the attribute value exists in a table. + * + * This validator is often used to verify that a foreign key contains a value + * that can be found in the foreign table. + * + * When using the {@link message} property to define a custom error message, the message + * may contain additional placeholders that will be replaced with the actual content. In addition + * to the "{attribute}" placeholder, recognized by all validators (see {@link CValidator}), + * CExistValidator allows for the following placeholders to be specified: + * <ul> + * <li>{value}: replaced with value of the attribute.</li> + * </ul> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CExistValidator.php 3549 2012-01-27 15:36:43Z qiang.xue $ + * @package system.validators + */ +class CExistValidator extends CValidator +{ + /** + * @var string the ActiveRecord class name that should be used to + * look for the attribute value being validated. Defaults to null, + * meaning using the ActiveRecord class of the attribute being validated. + * You may use path alias to reference a class name here. + * @see attributeName + */ + public $className; + /** + * @var string the ActiveRecord class attribute name that should be + * used to look for the attribute value being validated. Defaults to null, + * meaning using the name of the attribute being validated. + * @see className + */ + public $attributeName; + /** + * @var array additional query criteria. This will be combined with the condition + * that checks if the attribute value exists in the corresponding table column. + * This array will be used to instantiate a {@link CDbCriteria} object. + */ + public $criteria=array(); + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + + $className=$this->className===null?get_class($object):Yii::import($this->className); + $attributeName=$this->attributeName===null?$attribute:$this->attributeName; + $finder=CActiveRecord::model($className); + $table=$finder->getTableSchema(); + if(($column=$table->getColumn($attributeName))===null) + throw new CException(Yii::t('yii','Table "{table}" does not have a column named "{column}".', + array('{column}'=>$attributeName,'{table}'=>$table->name))); + + $criteria=array('condition'=>$column->rawName.'=:vp','params'=>array(':vp'=>$value)); + if($this->criteria!==array()) + { + $criteria=new CDbCriteria($criteria); + $criteria->mergeWith($this->criteria); + } + + if(!$finder->exists($criteria)) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} "{value}" is invalid.'); + $this->addError($object,$attribute,$message,array('{value}'=>CHtml::encode($value))); + } + } +} + diff --git a/framework/validators/CFileValidator.php b/framework/validators/CFileValidator.php new file mode 100644 index 0000000..d90d70e --- /dev/null +++ b/framework/validators/CFileValidator.php @@ -0,0 +1,251 @@ +<?php +/** + * CFileValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CFileValidator verifies if an attribute is receiving a valid uploaded file. + * + * It uses the model class and attribute name to retrieve the information + * about the uploaded file. It then checks if a file is uploaded successfully, + * if the file size is within the limit and if the file type is allowed. + * + * This validator will attempt to fetch uploaded data if attribute is not + * previously set. Please note that this cannot be done if input is tabular: + * <pre> + * foreach($models as $i=>$model) + * $model->attribute = CUploadedFile::getInstance($model, "[$i]attribute"); + * </pre> + * Please note that you must use {@link CUploadedFile::getInstances} for multiple + * file uploads. + * + * When using CFileValidator with an active record, the following code is often used: + * <pre> + * if($model->save()) + * { + * // single upload + * $model->attribute->saveAs($path); + * // multiple upload + * foreach($model->attribute as $file) + * $file->saveAs($path); + * } + * </pre> + * + * You can use {@link CFileValidator} to validate the file attribute. + * + * In addition to the {@link message} property for setting a custom error message, + * CFileValidator has a few custom error messages you can set that correspond to different + * validation scenarios. When the file is too large, you may use the {@link tooLarge} property + * to define a custom error message. Similarly for {@link tooSmall}, {@link wrongType} and + * {@link tooMany}. The messages may contain additional placeholders that will be replaced + * with the actual content. In addition to the "{attribute}" placeholder, recognized by all + * validators (see {@link CValidator}), CFileValidator allows for the following placeholders + * to be specified: + * <ul> + * <li>{file}: replaced with the name of the file.</li> + * <li>{limit}: when using {@link tooLarge}, replaced with {@link maxSize}; + * when using {@link tooSmall}, replaced with {@link maxSize}; and when using {@link tooMany} + * replaced with {@link maxFiles}.</li> + * <li>{extensions}: when using {@link wrongType}, it will be replaced with the allowed extensions.</li> + * </ul> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CFileValidator.php 3491 2011-12-17 05:17:57Z jefftulsa $ + * @package system.validators + * @since 1.0 + */ +class CFileValidator extends CValidator +{ + /** + * @var boolean whether the attribute requires a file to be uploaded or not. + * Defaults to false, meaning a file is required to be uploaded. + */ + public $allowEmpty=false; + /** + * @var mixed a list of file name extensions that are allowed to be uploaded. + * This can be either an array or a string consisting of file extension names + * separated by space or comma (e.g. "gif, jpg"). + * Extension names are case-insensitive. Defaults to null, meaning all file name + * extensions are allowed. + */ + public $types; + /** + * @var integer the minimum number of bytes required for the uploaded file. + * Defaults to null, meaning no limit. + * @see tooSmall + */ + public $minSize; + /** + * @var integer the maximum number of bytes required for the uploaded file. + * Defaults to null, meaning no limit. + * Note, the size limit is also affected by 'upload_max_filesize' INI setting + * and the 'MAX_FILE_SIZE' hidden field value. + * @see tooLarge + */ + public $maxSize; + /** + * @var string the error message used when the uploaded file is too large. + * @see maxSize + */ + public $tooLarge; + /** + * @var string the error message used when the uploaded file is too small. + * @see minSize + */ + public $tooSmall; + /** + * @var string the error message used when the uploaded file has an extension name + * that is not listed among {@link extensions}. + */ + public $wrongType; + /** + * @var integer the maximum file count the given attribute can hold. + * It defaults to 1, meaning single file upload. By defining a higher number, + * multiple uploads become possible. + */ + public $maxFiles=1; + /** + * @var string the error message used if the count of multiple uploads exceeds + * limit. + */ + public $tooMany; + + /** + * Set the attribute and then validates using {@link validateFile}. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object, $attribute) + { + if($this->maxFiles > 1) + { + $files=$object->$attribute; + if(!is_array($files) || !isset($files[0]) || !$files[0] instanceof CUploadedFile) + $files = CUploadedFile::getInstances($object, $attribute); + if(array()===$files) + return $this->emptyAttribute($object, $attribute); + if(count($files) > $this->maxFiles) + { + $message=$this->tooMany!==null?$this->tooMany : Yii::t('yii', '{attribute} cannot accept more than {limit} files.'); + $this->addError($object, $attribute, $message, array('{attribute}'=>$attribute, '{limit}'=>$this->maxFiles)); + } + else + foreach($files as $file) + $this->validateFile($object, $attribute, $file); + } + else + { + $file = $object->$attribute; + if(!$file instanceof CUploadedFile) + { + $file = CUploadedFile::getInstance($object, $attribute); + if(null===$file) + return $this->emptyAttribute($object, $attribute); + } + $this->validateFile($object, $attribute, $file); + } + } + + /** + * Internally validates a file object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + * @param CUploadedFile $file uploaded file passed to check against a set of rules + */ + protected function validateFile($object, $attribute, $file) + { + if(null===$file || ($error=$file->getError())==UPLOAD_ERR_NO_FILE) + return $this->emptyAttribute($object, $attribute); + else if($error==UPLOAD_ERR_INI_SIZE || $error==UPLOAD_ERR_FORM_SIZE || $this->maxSize!==null && $file->getSize()>$this->maxSize) + { + $message=$this->tooLarge!==null?$this->tooLarge : Yii::t('yii','The file "{file}" is too large. Its size cannot exceed {limit} bytes.'); + $this->addError($object,$attribute,$message,array('{file}'=>$file->getName(), '{limit}'=>$this->getSizeLimit())); + } + else if($error==UPLOAD_ERR_PARTIAL) + throw new CException(Yii::t('yii','The file "{file}" was only partially uploaded.',array('{file}'=>$file->getName()))); + else if($error==UPLOAD_ERR_NO_TMP_DIR) + throw new CException(Yii::t('yii','Missing the temporary folder to store the uploaded file "{file}".',array('{file}'=>$file->getName()))); + else if($error==UPLOAD_ERR_CANT_WRITE) + throw new CException(Yii::t('yii','Failed to write the uploaded file "{file}" to disk.',array('{file}'=>$file->getName()))); + else if(defined('UPLOAD_ERR_EXTENSION') && $error==UPLOAD_ERR_EXTENSION) // available for PHP 5.2.0 or above + throw new CException(Yii::t('yii','File upload was stopped by extension.')); + + if($this->minSize!==null && $file->getSize()<$this->minSize) + { + $message=$this->tooSmall!==null?$this->tooSmall : Yii::t('yii','The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.'); + $this->addError($object,$attribute,$message,array('{file}'=>$file->getName(), '{limit}'=>$this->minSize)); + } + + if($this->types!==null) + { + if(is_string($this->types)) + $types=preg_split('/[\s,]+/',strtolower($this->types),-1,PREG_SPLIT_NO_EMPTY); + else + $types=$this->types; + if(!in_array(strtolower($file->getExtensionName()),$types)) + { + $message=$this->wrongType!==null?$this->wrongType : Yii::t('yii','The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.'); + $this->addError($object,$attribute,$message,array('{file}'=>$file->getName(), '{extensions}'=>implode(', ',$types))); + } + } + } + + /** + * Raises an error to inform end user about blank attribute. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function emptyAttribute($object, $attribute) + { + if(!$this->allowEmpty) + { + $message=$this->message!==null?$this->message : Yii::t('yii','{attribute} cannot be blank.'); + $this->addError($object,$attribute,$message); + } + } + + /** + * Returns the maximum size allowed for uploaded files. + * This is determined based on three factors: + * <ul> + * <li>'upload_max_filesize' in php.ini</li> + * <li>'MAX_FILE_SIZE' hidden field</li> + * <li>{@link maxSize}</li> + * </ul> + * + * @return integer the size limit for uploaded files. + */ + protected function getSizeLimit() + { + $limit=ini_get('upload_max_filesize'); + $limit=$this->sizeToBytes($limit); + if($this->maxSize!==null && $limit>0 && $this->maxSize<$limit) + $limit=$this->maxSize; + if(isset($_POST['MAX_FILE_SIZE']) && $_POST['MAX_FILE_SIZE']>0 && $_POST['MAX_FILE_SIZE']<$limit) + $limit=$_POST['MAX_FILE_SIZE']; + return $limit; + } + + /** + * Converts php.ini style size to bytes + * + * @param string $sizeStr $sizeStr + * @return int + */ + private function sizeToBytes($sizeStr) + { + switch (substr($sizeStr, -1)) + { + case 'M': case 'm': return (int)$sizeStr * 1048576; + case 'K': case 'k': return (int)$sizeStr * 1024; + case 'G': case 'g': return (int)$sizeStr * 1073741824; + default: return (int)$sizeStr; + } + } +}
\ No newline at end of file diff --git a/framework/validators/CFilterValidator.php b/framework/validators/CFilterValidator.php new file mode 100644 index 0000000..6e8f564 --- /dev/null +++ b/framework/validators/CFilterValidator.php @@ -0,0 +1,49 @@ +<?php +/** + * CFilterValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CFilterValidator transforms the data being validated based on a filter. + * + * CFilterValidator is actually not a validator but a data processor. + * It invokes the specified filter method to process the attribute value + * and save the processed value back to the attribute. The filter method + * must follow the following signature: + * <pre> + * function foo($value) {...return $newValue; } + * </pre> + * Many PHP functions qualify this signature (e.g. trim). + * + * To specify the filter method, set {@link filter} property to be the function name. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CFilterValidator.php 2799 2011-01-01 19:31:13Z qiang.xue $ + * @package system.validators + * @since 1.0 + */ +class CFilterValidator extends CValidator +{ + /** + * @var callback the filter method + */ + public $filter; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + if($this->filter===null || !is_callable($this->filter)) + throw new CException(Yii::t('yii','The "filter" property must be specified with a valid callback.')); + $object->$attribute=call_user_func_array($this->filter,array($object->$attribute)); + } +} diff --git a/framework/validators/CInlineValidator.php b/framework/validators/CInlineValidator.php new file mode 100644 index 0000000..f88350d --- /dev/null +++ b/framework/validators/CInlineValidator.php @@ -0,0 +1,81 @@ +<?php +/** + * CInlineValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CInlineValidator represents a validator which is defined as a method in the object being validated. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CInlineValidator.php 3517 2011-12-28 23:22:21Z mdomba $ + * @package system.validators + * @since 1.0 + */ +class CInlineValidator extends CValidator +{ + /** + * @var string the name of the validation method defined in the active record class + */ + public $method; + /** + * @var array additional parameters that are passed to the validation method + */ + public $params; + /** + * @var string the name of the method that returns the client validation code (See {@link clientValidateAttribute}). + */ + public $clientValidate; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $method=$this->method; + $object->$method($attribute,$this->params); + } + + /** + * Returns the JavaScript code needed to perform client-side validation by calling the {@link clientValidate} method. + * In the client validation code, these variables are predefined: + * <ul> + * <li>value: the current input value associated with this attribute.</li> + * <li>messages: an array that may be appended with new error messages for the attribute.</li> + * <li>attribute: a data structure keeping all client-side options for the attribute</li> + * </ul> + * <b>Example</b>: + * + * If {@link clientValidate} is set to "clientValidate123", clientValidate123() is the name of + * the method that returns the client validation code and can look like: + * <pre> + * <?php + * public function clientValidate123($attribute) + * { + * $js = "if(value != '123') { messages.push('Value should be 123'); }"; + * return $js; + * } + * ?> + * </pre> + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.9 + */ + public function clientValidateAttribute($object,$attribute) + { + if($this->clientValidate!==null) + { + $method=$this->clientValidate; + return $object->$method($attribute); + } + } +} diff --git a/framework/validators/CNumberValidator.php b/framework/validators/CNumberValidator.php new file mode 100644 index 0000000..d40322b --- /dev/null +++ b/framework/validators/CNumberValidator.php @@ -0,0 +1,176 @@ +<?php +/** + * CNumberValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CNumberValidator validates that the attribute value is a number. + * + * In addition to the {@link message} property for setting a custom error message, + * CNumberValidator has a couple custom error messages you can set that correspond to different + * validation scenarios. To specify a custom message when the numeric value is too big, + * you may use the {@link tooBig} property. Similarly with {@link tooSmall}. + * The messages may contain additional placeholders that will be replaced + * with the actual content. In addition to the "{attribute}" placeholder, recognized by all + * validators (see {@link CValidator}), CNumberValidator allows for the following placeholders + * to be specified: + * <ul> + * <li>{min}: when using {@link tooSmall}, replaced with the lower limit of the number {@link min}.</li> + * <li>{max}: when using {@link tooBig}, replaced with the upper limit of the number {@link max}.</li> + * </ul> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CNumberValidator.php 3491 2011-12-17 05:17:57Z jefftulsa $ + * @package system.validators + * @since 1.0 + */ +class CNumberValidator extends CValidator +{ + /** + * @var boolean whether the attribute value can only be an integer. Defaults to false. + */ + public $integerOnly=false; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + /** + * @var integer|float upper limit of the number. Defaults to null, meaning no upper limit. + */ + public $max; + /** + * @var integer|float lower limit of the number. Defaults to null, meaning no lower limit. + */ + public $min; + /** + * @var string user-defined error message used when the value is too big. + */ + public $tooBig; + /** + * @var string user-defined error message used when the value is too small. + */ + public $tooSmall; + /** + * @var string the regular expression for matching integers. + * @since 1.1.7 + */ + public $integerPattern='/^\s*[+-]?\d+\s*$/'; + /** + * @var string the regular expression for matching numbers. + * @since 1.1.7 + */ + public $numberPattern='/^\s*[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s*$/'; + + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + if($this->integerOnly) + { + if(!preg_match($this->integerPattern,"$value")) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be an integer.'); + $this->addError($object,$attribute,$message); + } + } + else + { + if(!preg_match($this->numberPattern,"$value")) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be a number.'); + $this->addError($object,$attribute,$message); + } + } + if($this->min!==null && $value<$this->min) + { + $message=$this->tooSmall!==null?$this->tooSmall:Yii::t('yii','{attribute} is too small (minimum is {min}).'); + $this->addError($object,$attribute,$message,array('{min}'=>$this->min)); + } + if($this->max!==null && $value>$this->max) + { + $message=$this->tooBig!==null?$this->tooBig:Yii::t('yii','{attribute} is too big (maximum is {max}).'); + $this->addError($object,$attribute,$message,array('{max}'=>$this->max)); + } + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + $label=$object->getAttributeLabel($attribute); + + if(($message=$this->message)===null) + $message=$this->integerOnly ? Yii::t('yii','{attribute} must be an integer.') : Yii::t('yii','{attribute} must be a number.'); + $message=strtr($message, array( + '{attribute}'=>$label, + )); + + if(($tooBig=$this->tooBig)===null) + $tooBig=Yii::t('yii','{attribute} is too big (maximum is {max}).'); + $tooBig=strtr($tooBig, array( + '{attribute}'=>$label, + '{max}'=>$this->max, + )); + + if(($tooSmall=$this->tooSmall)===null) + $tooSmall=Yii::t('yii','{attribute} is too small (minimum is {min}).'); + $tooSmall=strtr($tooSmall, array( + '{attribute}'=>$label, + '{min}'=>$this->min, + )); + + $pattern=$this->integerOnly ? $this->integerPattern : $this->numberPattern; + $js=" +if(!value.match($pattern)) { + messages.push(".CJSON::encode($message)."); +} +"; + if($this->min!==null) + { + $js.=" +if(value<{$this->min}) { + messages.push(".CJSON::encode($tooSmall)."); +} +"; + } + if($this->max!==null) + { + $js.=" +if(value>{$this->max}) { + messages.push(".CJSON::encode($tooBig)."); +} +"; + } + + if($this->allowEmpty) + { + $js=" +if($.trim(value)!='') { + $js +} +"; + } + + return $js; + } +} diff --git a/framework/validators/CRangeValidator.php b/framework/validators/CRangeValidator.php new file mode 100644 index 0000000..bc844ba --- /dev/null +++ b/framework/validators/CRangeValidator.php @@ -0,0 +1,97 @@ +<?php +/** + * CRangeValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CRangeValidator validates that the attribute value is among the list (specified via {@link range}). + * You may invert the validation logic with help of the {@link not} property (available since 1.1.5). + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CRangeValidator.php 3120 2011-03-25 01:50:48Z qiang.xue $ + * @package system.validators + * @since 1.0 + */ +class CRangeValidator extends CValidator +{ + /** + * @var array list of valid values that the attribute value should be among + */ + public $range; + /** + * @var boolean whether the comparison is strict (both type and value must be the same) + */ + public $strict=false; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + /** + * @var boolean whether to invert the validation logic. Defaults to false. If set to true, + * the attribute value should NOT be among the list of values defined via {@link range}. + * @since 1.1.5 + **/ + public $not=false; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + if(!is_array($this->range)) + throw new CException(Yii::t('yii','The "range" property must be specified with a list of values.')); + if(!$this->not && !in_array($value,$this->range,$this->strict)) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} is not in the list.'); + $this->addError($object,$attribute,$message); + } + else if($this->not && in_array($value,$this->range,$this->strict)) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} is in the list.'); + $this->addError($object,$attribute,$message); + } + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + if(!is_array($this->range)) + throw new CException(Yii::t('yii','The "range" property must be specified with a list of values.')); + + if(($message=$this->message)===null) + $message=$this->not ? Yii::t('yii','{attribute} is in the list.') : Yii::t('yii','{attribute} is not in the list.'); + $message=strtr($message,array( + '{attribute}'=>$object->getAttributeLabel($attribute), + )); + + $range=array(); + foreach($this->range as $value) + $range[]=(string)$value; + $range=CJSON::encode($range); + + return " +if(".($this->allowEmpty ? "$.trim(value)!='' && " : '').($this->not ? "$.inArray(value, $range)>=0" : "$.inArray(value, $range)<0").") { + messages.push(".CJSON::encode($message)."); +} +"; + } +}
\ No newline at end of file diff --git a/framework/validators/CRegularExpressionValidator.php b/framework/validators/CRegularExpressionValidator.php new file mode 100644 index 0000000..3506d99 --- /dev/null +++ b/framework/validators/CRegularExpressionValidator.php @@ -0,0 +1,94 @@ +<?php +/** + * CRegularExpressionValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CRegularExpressionValidator validates that the attribute value matches to the specified {@link pattern regular expression}. + * You may invert the validation logic with help of the {@link not} property (available since 1.1.5). + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CRegularExpressionValidator.php 3120 2011-03-25 01:50:48Z qiang.xue $ + * @package system.validators + * @since 1.0 + */ +class CRegularExpressionValidator extends CValidator +{ + /** + * @var string the regular expression to be matched with + */ + public $pattern; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + /** + * @var boolean whether to invert the validation logic. Defaults to false. If set to true, + * the regular expression defined via {@link pattern} should NOT match the attribute value. + * @since 1.1.5 + **/ + public $not=false; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + if($this->pattern===null) + throw new CException(Yii::t('yii','The "pattern" property must be specified with a valid regular expression.')); + if((!$this->not && !preg_match($this->pattern,$value)) || ($this->not && preg_match($this->pattern,$value))) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} is invalid.'); + $this->addError($object,$attribute,$message); + } + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + if($this->pattern===null) + throw new CException(Yii::t('yii','The "pattern" property must be specified with a valid regular expression.')); + + $message=$this->message!==null ? $this->message : Yii::t('yii','{attribute} is invalid.'); + $message=strtr($message, array( + '{attribute}'=>$object->getAttributeLabel($attribute), + )); + + $pattern=$this->pattern; + $pattern=preg_replace('/\\\\x\{?([0-9a-fA-F]+)\}?/', '\u$1', $pattern); + $delim=substr($pattern, 0, 1); + $endpos=strrpos($pattern, $delim, 1); + $flag=substr($pattern, $endpos + 1); + if ($delim!=='/') + $pattern='/' . str_replace('/', '\\/', substr($pattern, 1, $endpos - 1)) . '/'; + else + $pattern = substr($pattern, 0, $endpos + 1); + if (!empty($flag)) + $pattern .= preg_replace('/[^igm]/', '', $flag); + + return " +if(".($this->allowEmpty ? "$.trim(value)!='' && " : '').($this->not ? '' : '!')."value.match($pattern)) { + messages.push(".CJSON::encode($message)."); +} +"; + } +}
\ No newline at end of file diff --git a/framework/validators/CRequiredValidator.php b/framework/validators/CRequiredValidator.php new file mode 100644 index 0000000..fd54629 --- /dev/null +++ b/framework/validators/CRequiredValidator.php @@ -0,0 +1,108 @@ +<?php +/** + * CRequiredValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CRequiredValidator validates that the specified attribute does not have null or empty value. + * + * When using the {@link message} property to define a custom error message, the message + * may contain additional placeholders that will be replaced with the actual content. In addition + * to the "{attribute}" placeholder, recognized by all validators (see {@link CValidator}), + * CRequiredValidator allows for the following placeholders to be specified: + * <ul> + * <li>{value}: replaced with the desired value {@link requiredValue}.</li> + * </ul> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CRequiredValidator.php 3515 2011-12-28 12:29:24Z mdomba $ + * @package system.validators + * @since 1.0 + */ +class CRequiredValidator extends CValidator +{ + /** + * @var mixed the desired value that the attribute must have. + * If this is null, the validator will validate that the specified attribute does not have null or empty value. + * If this is set as a value that is not null, the validator will validate that + * the attribute has a value that is the same as this property value. + * Defaults to null. + */ + public $requiredValue; + /** + * @var boolean whether the comparison to {@link requiredValue} is strict. + * When this is true, the attribute value and type must both match those of {@link requiredValue}. + * Defaults to false, meaning only the value needs to be matched. + * This property is only used when {@link requiredValue} is not null. + */ + public $strict=false; + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->requiredValue!==null) + { + if(!$this->strict && $value!=$this->requiredValue || $this->strict && $value!==$this->requiredValue) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be {value}.', + array('{value}'=>$this->requiredValue)); + $this->addError($object,$attribute,$message); + } + } + else if($this->isEmpty($value,true)) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} cannot be blank.'); + $this->addError($object,$attribute,$message); + } + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + $message=$this->message; + if($this->requiredValue!==null) + { + if($message===null) + $message=Yii::t('yii','{attribute} must be {value}.'); + $message=strtr($message, array( + '{value}'=>$this->requiredValue, + '{attribute}'=>$object->getAttributeLabel($attribute), + )); + return " +if(value!=" . CJSON::encode($this->requiredValue) . ") { + messages.push(".CJSON::encode($message)."); +} +"; + } + else + { + if($message===null) + $message=Yii::t('yii','{attribute} cannot be blank.'); + $message=strtr($message, array( + '{attribute}'=>$object->getAttributeLabel($attribute), + )); + return " +if($.trim(value)=='') { + messages.push(".CJSON::encode($message)."); +} +"; + } + } +} diff --git a/framework/validators/CSafeValidator.php b/framework/validators/CSafeValidator.php new file mode 100644 index 0000000..edcfa1e --- /dev/null +++ b/framework/validators/CSafeValidator.php @@ -0,0 +1,31 @@ +<?php +/** + * CSafeValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CSafeValidator marks the associated attributes to be safe for massive assignments. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CSafeValidator.php 2799 2011-01-01 19:31:13Z qiang.xue $ + * @package system.validators + * @since 1.1 + */ +class CSafeValidator extends CValidator +{ + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + } +} + diff --git a/framework/validators/CStringValidator.php b/framework/validators/CStringValidator.php new file mode 100644 index 0000000..2553af6 --- /dev/null +++ b/framework/validators/CStringValidator.php @@ -0,0 +1,177 @@ +<?php +/** + * CStringValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CStringValidator validates that the attribute value is of certain length. + * + * Note, this validator should only be used with string-typed attributes. + * + * In addition to the {@link message} property for setting a custom error message, + * CStringValidator has a couple custom error messages you can set that correspond to different + * validation scenarios. For defining a custom message when the string is too short, + * you may use the {@link tooShort} property. Similarly with {@link tooLong}. The messages may contain + * placeholders that will be replaced with the actual content. In addition to the "{attribute}" + * placeholder, recognized by all validators (see {@link CValidator}), CStringValidator allows for the following + * placeholders to be specified: + * <ul> + * <li>{min}: when using {@link tooShort}, replaced with minimum length, {@link min}, if set.</li> + * <li>{max}: when using {@link tooLong}, replaced with the maximum length, {@link max}, if set.</li> + * <li>{length}: when using {@link message}, replaced with the exact required length, {@link is}, if set.</li> + * </ul> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CStringValidator.php 3491 2011-12-17 05:17:57Z jefftulsa $ + * @package system.validators + * @since 1.0 + */ +class CStringValidator extends CValidator +{ + /** + * @var integer maximum length. Defaults to null, meaning no maximum limit. + */ + public $max; + /** + * @var integer minimum length. Defaults to null, meaning no minimum limit. + */ + public $min; + /** + * @var integer exact length. Defaults to null, meaning no exact length limit. + */ + public $is; + /** + * @var string user-defined error message used when the value is too short. + */ + public $tooShort; + /** + * @var string user-defined error message used when the value is too long. + */ + public $tooLong; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + /** + * @var string the encoding of the string value to be validated (e.g. 'UTF-8'). + * This property is used only when mbstring PHP extension is enabled. + * The value of this property will be used as the 2nd parameter of the + * mb_strlen() function. If this property is not set, the application charset + * will be used. + * If this property is set false, then strlen() will be used even if mbstring is enabled. + * @since 1.1.1 + */ + public $encoding; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + + if(function_exists('mb_strlen') && $this->encoding!==false) + $length=mb_strlen($value, $this->encoding ? $this->encoding : Yii::app()->charset); + else + $length=strlen($value); + + if($this->min!==null && $length<$this->min) + { + $message=$this->tooShort!==null?$this->tooShort:Yii::t('yii','{attribute} is too short (minimum is {min} characters).'); + $this->addError($object,$attribute,$message,array('{min}'=>$this->min)); + } + if($this->max!==null && $length>$this->max) + { + $message=$this->tooLong!==null?$this->tooLong:Yii::t('yii','{attribute} is too long (maximum is {max} characters).'); + $this->addError($object,$attribute,$message,array('{max}'=>$this->max)); + } + if($this->is!==null && $length!==$this->is) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} is of the wrong length (should be {length} characters).'); + $this->addError($object,$attribute,$message,array('{length}'=>$this->is)); + } + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + $label=$object->getAttributeLabel($attribute); + + if(($message=$this->message)===null) + $message=Yii::t('yii','{attribute} is of the wrong length (should be {length} characters).'); + $message=strtr($message, array( + '{attribute}'=>$label, + '{length}'=>$this->is, + )); + + if(($tooShort=$this->tooShort)===null) + $tooShort=Yii::t('yii','{attribute} is too short (minimum is {min} characters).'); + $tooShort=strtr($tooShort, array( + '{attribute}'=>$label, + '{min}'=>$this->min, + )); + + if(($tooLong=$this->tooLong)===null) + $tooLong=Yii::t('yii','{attribute} is too long (maximum is {max} characters).'); + $tooLong=strtr($tooLong, array( + '{attribute}'=>$label, + '{max}'=>$this->max, + )); + + $js=''; + if($this->min!==null) + { + $js.=" +if(value.length<{$this->min}) { + messages.push(".CJSON::encode($tooShort)."); +} +"; + } + if($this->max!==null) + { + $js.=" +if(value.length>{$this->max}) { + messages.push(".CJSON::encode($tooLong)."); +} +"; + } + if($this->is!==null) + { + $js.=" +if(value.length!={$this->is}) { + messages.push(".CJSON::encode($message)."); +} +"; + } + + if($this->allowEmpty) + { + $js=" +if($.trim(value)!='') { + $js +} +"; + } + + return $js; + } +} + diff --git a/framework/validators/CTypeValidator.php b/framework/validators/CTypeValidator.php new file mode 100644 index 0000000..e82c1a5 --- /dev/null +++ b/framework/validators/CTypeValidator.php @@ -0,0 +1,110 @@ +<?php +/** + * CTypeValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CTypeValidator verifies if the attribute is of the type specified by {@link type}. + * + * The following data types are supported: + * <ul> + * <li><b>integer</b> A 32-bit signed integer data type.</li> + * <li><b>float</b> A double-precision floating point number data type.</li> + * <li><b>string</b> A string data type.</li> + * <li><b>array</b> An array value. </li> + * <li><b>date</b> A date data type.</li> + * <li><b>time</b> A time data type.</li> + * <li><b>datetime</b> A date and time data type.</li> + * </ul> + * + * For <b>date</b> type, the property {@link dateFormat} + * will be used to determine how to parse the date string. If the given date + * value doesn't follow the format, the attribute is considered as invalid. + * + * Starting from version 1.1.7, we have a dedicated date validator {@link CDateValidator}. + * Please consider using this validator to validate a date-typed value. + * + * When using the {@link message} property to define a custom error message, the message + * may contain additional placeholders that will be replaced with the actual content. In addition + * to the "{attribute}" placeholder, recognized by all validators (see {@link CValidator}), + * CTypeValidator allows for the following placeholders to be specified: + * <ul> + * <li>{type}: replaced with data type the attribute should be {@link type}.</li> + * </ul> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CTypeValidator.php 3515 2011-12-28 12:29:24Z mdomba $ + * @package system.validators + * @since 1.0 + */ +class CTypeValidator extends CValidator +{ + /** + * @var string the data type that the attribute should be. Defaults to 'string'. + * Valid values include 'string', 'integer', 'float', 'array', 'date', 'time' and 'datetime'. + */ + public $type='string'; + /** + * @var string the format pattern that the date value should follow. Defaults to 'MM/dd/yyyy'. + * Please see {@link CDateTimeParser} for details about how to specify a date format. + * This property is effective only when {@link type} is 'date'. + */ + public $dateFormat='MM/dd/yyyy'; + /** + * @var string the format pattern that the time value should follow. Defaults to 'hh:mm'. + * Please see {@link CDateTimeParser} for details about how to specify a time format. + * This property is effective only when {@link type} is 'time'. + */ + public $timeFormat='hh:mm'; + /** + * @var string the format pattern that the datetime value should follow. Defaults to 'MM/dd/yyyy hh:mm'. + * Please see {@link CDateTimeParser} for details about how to specify a datetime format. + * This property is effective only when {@link type} is 'datetime'. + */ + public $datetimeFormat='MM/dd/yyyy hh:mm'; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + + if($this->type==='integer') + $valid=preg_match('/^[-+]?[0-9]+$/',trim($value)); + else if($this->type==='float') + $valid=preg_match('/^[-+]?([0-9]*\.)?[0-9]+([eE][-+]?[0-9]+)?$/',trim($value)); + else if($this->type==='date') + $valid=CDateTimeParser::parse($value,$this->dateFormat,array('month'=>1,'day'=>1,'hour'=>0,'minute'=>0,'second'=>0))!==false; + else if($this->type==='time') + $valid=CDateTimeParser::parse($value,$this->timeFormat)!==false; + else if($this->type==='datetime') + $valid=CDateTimeParser::parse($value,$this->datetimeFormat, array('month'=>1,'day'=>1,'hour'=>0,'minute'=>0,'second'=>0))!==false; + else if($this->type==='array') + $valid=is_array($value); + else + return; + + if(!$valid) + { + $message=$this->message!==null?$this->message : Yii::t('yii','{attribute} must be {type}.'); + $this->addError($object,$attribute,$message,array('{type}'=>$this->type)); + } + } +} + diff --git a/framework/validators/CUniqueValidator.php b/framework/validators/CUniqueValidator.php new file mode 100644 index 0000000..d48b35f --- /dev/null +++ b/framework/validators/CUniqueValidator.php @@ -0,0 +1,129 @@ +<?php +/** + * CUniqueValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CUniqueValidator validates that the attribute value is unique in the corresponding database table. + * + * When using the {@link message} property to define a custom error message, the message + * may contain additional placeholders that will be replaced with the actual content. In addition + * to the "{attribute}" placeholder, recognized by all validators (see {@link CValidator}), + * CUniqueValidator allows for the following placeholders to be specified: + * <ul> + * <li>{value}: replaced with current value of the attribute.</li> + * </ul> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CUniqueValidator.php 3549 2012-01-27 15:36:43Z qiang.xue $ + * @package system.validators + * @since 1.0 + */ +class CUniqueValidator extends CValidator +{ + /** + * @var boolean whether the comparison is case sensitive. Defaults to true. + * Note, by setting it to false, you are assuming the attribute type is string. + */ + public $caseSensitive=true; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + /** + * @var string the ActiveRecord class name that should be used to + * look for the attribute value being validated. Defaults to null, meaning using + * the class of the object currently being validated. + * You may use path alias to reference a class name here. + * @see attributeName + */ + public $className; + /** + * @var string the ActiveRecord class attribute name that should be + * used to look for the attribute value being validated. Defaults to null, + * meaning using the name of the attribute being validated. + * @see className + */ + public $attributeName; + /** + * @var array additional query criteria. This will be combined with the condition + * that checks if the attribute value exists in the corresponding table column. + * This array will be used to instantiate a {@link CDbCriteria} object. + */ + public $criteria=array(); + /** + * @var string the user-defined error message. The placeholders "{attribute}" and "{value}" + * are recognized, which will be replaced with the actual attribute name and value, respectively. + */ + public $message; + /** + * @var boolean whether this validation rule should be skipped if when there is already a validation + * error for the current attribute. Defaults to true. + * @since 1.1.1 + */ + public $skipOnError=true; + + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + + $className=$this->className===null?get_class($object):Yii::import($this->className); + $attributeName=$this->attributeName===null?$attribute:$this->attributeName; + $finder=CActiveRecord::model($className); + $table=$finder->getTableSchema(); + if(($column=$table->getColumn($attributeName))===null) + throw new CException(Yii::t('yii','Table "{table}" does not have a column named "{column}".', + array('{column}'=>$attributeName,'{table}'=>$table->name))); + + $columnName=$column->rawName; + $criteria=new CDbCriteria(array( + 'condition'=>$this->caseSensitive ? "$columnName=:value" : "LOWER($columnName)=LOWER(:value)", + 'params'=>array(':value'=>$value), + )); + if($this->criteria!==array()) + $criteria->mergeWith($this->criteria); + + if(!$object instanceof CActiveRecord || $object->isNewRecord || $object->tableName()!==$finder->tableName()) + $exists=$finder->exists($criteria); + else + { + $criteria->limit=2; + $objects=$finder->findAll($criteria); + $n=count($objects); + if($n===1) + { + if($column->isPrimaryKey) // primary key is modified and not unique + $exists=$object->getOldPrimaryKey()!=$object->getPrimaryKey(); + else + { + // non-primary key, need to exclude the current record based on PK + $exists=array_shift($objects)->getPrimaryKey()!=$object->getOldPrimaryKey(); + } + } + else + $exists=$n>1; + } + + if($exists) + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} "{value}" has already been taken.'); + $this->addError($object,$attribute,$message,array('{value}'=>CHtml::encode($value))); + } + } +} + diff --git a/framework/validators/CUnsafeValidator.php b/framework/validators/CUnsafeValidator.php new file mode 100644 index 0000000..c92f26c --- /dev/null +++ b/framework/validators/CUnsafeValidator.php @@ -0,0 +1,37 @@ +<?php +/** + * CUnsafeValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CUnsafeValidator marks the associated attributes to be unsafe so that they cannot be massively assigned. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CUnsafeValidator.php 2799 2011-01-01 19:31:13Z qiang.xue $ + * @package system.validators + * @since 1.0 + */ +class CUnsafeValidator extends CValidator +{ + /** + * @var boolean whether attributes listed with this validator should be considered safe for massive assignment. + * Defaults to false. + * @since 1.1.4 + */ + public $safe=false; + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + } +} + diff --git a/framework/validators/CUrlValidator.php b/framework/validators/CUrlValidator.php new file mode 100644 index 0000000..0ee080e --- /dev/null +++ b/framework/validators/CUrlValidator.php @@ -0,0 +1,139 @@ +<?php +/** + * CUrlValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CUrlValidator validates that the attribute value is a valid http or https URL. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CUrlValidator.php 3242 2011-05-28 14:31:04Z qiang.xue $ + * @package system.validators + * @since 1.0 + */ +class CUrlValidator extends CValidator +{ + /** + * @var string the regular expression used to validate the attribute value. + * Since version 1.1.7 the pattern may contain a {schemes} token that will be replaced + * by a regular expression which represents the {@see validSchemes}. + */ + public $pattern='/^{schemes}:\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)/i'; + /** + * @var array list of URI schemes which should be considered valid. By default, http and https + * are considered to be valid schemes. + * @since 1.1.7 + **/ + public $validSchemes=array('http','https'); + /** + * @var string the default URI scheme. If the input doesn't contain the scheme part, the default + * scheme will be prepended to it (thus changing the input). Defaults to null, meaning a URL must + * contain the scheme part. + * @since 1.1.7 + **/ + public $defaultScheme; + /** + * @var boolean whether the attribute value can be null or empty. Defaults to true, + * meaning that if the attribute is empty, it is considered valid. + */ + public $allowEmpty=true; + + /** + * Validates the attribute of the object. + * If there is any error, the error message is added to the object. + * @param CModel $object the object being validated + * @param string $attribute the attribute being validated + */ + protected function validateAttribute($object,$attribute) + { + $value=$object->$attribute; + if($this->allowEmpty && $this->isEmpty($value)) + return; + if(($value=$this->validateValue($value))!==false) + $object->$attribute=$value; + else + { + $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} is not a valid URL.'); + $this->addError($object,$attribute,$message); + } + } + + /** + * Validates a static value to see if it is a valid URL. + * Note that this method does not respect {@link allowEmpty} property. + * This method is provided so that you can call it directly without going through the model validation rule mechanism. + * @param mixed $value the value to be validated + * @return mixed false if the the value is not a valid URL, otherwise the possibly modified value ({@see defaultScheme}) + * @since 1.1.1 + */ + public function validateValue($value) + { + if(is_string($value) && strlen($value)<2000) // make sure the length is limited to avoid DOS attacks + { + if($this->defaultScheme!==null && strpos($value,'://')===false) + $value=$this->defaultScheme.'://'.$value; + + if(strpos($this->pattern,'{schemes}')!==false) + $pattern=str_replace('{schemes}','('.implode('|',$this->validSchemes).')',$this->pattern); + else + $pattern=$this->pattern; + + if(preg_match($pattern,$value)) + return $value; + } + return false; + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + $message=$this->message!==null ? $this->message : Yii::t('yii','{attribute} is not a valid URL.'); + $message=strtr($message, array( + '{attribute}'=>$object->getAttributeLabel($attribute), + )); + + if(strpos($this->pattern,'{schemes}')!==false) + $pattern=str_replace('{schemes}','('.implode('|',$this->validSchemes).')',$this->pattern); + else + $pattern=$this->pattern; + + $js=" +if(!value.match($pattern)) { + messages.push(".CJSON::encode($message)."); +} +"; + if($this->defaultScheme!==null) + { + $js=" +if(!value.match(/:\\/\\//)) { + value=".CJSON::encode($this->defaultScheme)."+'://'+value; +} +$js +"; + } + + if($this->allowEmpty) + { + $js=" +if($.trim(value)!='') { + $js +} +"; + } + + return $js; + } +} + diff --git a/framework/validators/CValidator.php b/framework/validators/CValidator.php new file mode 100644 index 0000000..45e5bd1 --- /dev/null +++ b/framework/validators/CValidator.php @@ -0,0 +1,261 @@ +<?php +/** + * CValidator class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CValidator is the base class for all validators. + * + * Child classes must implement the {@link validateAttribute} method. + * + * The following properties are defined in CValidator: + * <ul> + * <li>{@link attributes}: array, list of attributes to be validated;</li> + * <li>{@link message}: string, the customized error message. The message + * may contain placeholders that will be replaced with the actual content. + * For example, the "{attribute}" placeholder will be replaced with the label + * of the problematic attribute. Different validators may define additional + * placeholders.</li> + * <li>{@link on}: string, in which scenario should the validator be in effect. + * This is used to match the 'on' parameter supplied when calling {@link CModel::validate}.</li> + * </ul> + * + * When using {@link createValidator} to create a validator, the following aliases + * are recognized as the corresponding built-in validator classes: + * <ul> + * <li>required: {@link CRequiredValidator}</li> + * <li>filter: {@link CFilterValidator}</li> + * <li>match: {@link CRegularExpressionValidator}</li> + * <li>email: {@link CEmailValidator}</li> + * <li>url: {@link CUrlValidator}</li> + * <li>unique: {@link CUniqueValidator}</li> + * <li>compare: {@link CCompareValidator}</li> + * <li>length: {@link CStringValidator}</li> + * <li>in: {@link CRangeValidator}</li> + * <li>numerical: {@link CNumberValidator}</li> + * <li>captcha: {@link CCaptchaValidator}</li> + * <li>type: {@link CTypeValidator}</li> + * <li>file: {@link CFileValidator}</li> + * <li>default: {@link CDefaultValueValidator}</li> + * <li>exist: {@link CExistValidator}</li> + * <li>boolean: {@link CBooleanValidator}</li> + * <li>date: {@link CDateValidator}</li> + * <li>safe: {@link CSafeValidator}</li> + * <li>unsafe: {@link CUnsafeValidator}</li> + * </ul> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CValidator.php 3515 2011-12-28 12:29:24Z mdomba $ + * @package system.validators + * @since 1.0 + */ +abstract class CValidator extends CComponent +{ + /** + * @var array list of built-in validators (name=>class) + */ + public static $builtInValidators=array( + 'required'=>'CRequiredValidator', + 'filter'=>'CFilterValidator', + 'match'=>'CRegularExpressionValidator', + 'email'=>'CEmailValidator', + 'url'=>'CUrlValidator', + 'unique'=>'CUniqueValidator', + 'compare'=>'CCompareValidator', + 'length'=>'CStringValidator', + 'in'=>'CRangeValidator', + 'numerical'=>'CNumberValidator', + 'captcha'=>'CCaptchaValidator', + 'type'=>'CTypeValidator', + 'file'=>'CFileValidator', + 'default'=>'CDefaultValueValidator', + 'exist'=>'CExistValidator', + 'boolean'=>'CBooleanValidator', + 'safe'=>'CSafeValidator', + 'unsafe'=>'CUnsafeValidator', + 'date'=>'CDateValidator', + ); + + /** + * @var array list of attributes to be validated. + */ + public $attributes; + /** + * @var string the user-defined error message. Different validators may define various + * placeholders in the message that are to be replaced with actual values. All validators + * recognize "{attribute}" placeholder, which will be replaced with the label of the attribute. + */ + public $message; + /** + * @var boolean whether this validation rule should be skipped when there is already a validation + * error for the current attribute. Defaults to false. + * @since 1.1.1 + */ + public $skipOnError=false; + /** + * @var array list of scenarios that the validator should be applied. + * Each array value refers to a scenario name with the same name as its array key. + */ + public $on; + /** + * @var boolean whether attributes listed with this validator should be considered safe for massive assignment. + * Defaults to true. + * @since 1.1.4 + */ + public $safe=true; + /** + * @var boolean whether to perform client-side validation. Defaults to true. + * Please refer to {@link CActiveForm::enableClientValidation} for more details about client-side validation. + * @since 1.1.7 + */ + public $enableClientValidation=true; + + /** + * Validates a single attribute. + * This method should be overridden by child classes. + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + */ + abstract protected function validateAttribute($object,$attribute); + + + /** + * Creates a validator object. + * @param string $name the name or class of the validator + * @param CModel $object the data object being validated that may contain the inline validation method + * @param mixed $attributes list of attributes to be validated. This can be either an array of + * the attribute names or a string of comma-separated attribute names. + * @param array $params initial values to be applied to the validator properties + * @return CValidator the validator + */ + public static function createValidator($name,$object,$attributes,$params=array()) + { + if(is_string($attributes)) + $attributes=preg_split('/[\s,]+/',$attributes,-1,PREG_SPLIT_NO_EMPTY); + + if(isset($params['on'])) + { + if(is_array($params['on'])) + $on=$params['on']; + else + $on=preg_split('/[\s,]+/',$params['on'],-1,PREG_SPLIT_NO_EMPTY); + } + else + $on=array(); + + if(method_exists($object,$name)) + { + $validator=new CInlineValidator; + $validator->attributes=$attributes; + $validator->method=$name; + if(isset($params['clientValidate'])) + { + $validator->clientValidate=$params['clientValidate']; + unset($params['clientValidate']); + } + $validator->params=$params; + if(isset($params['skipOnError'])) + $validator->skipOnError=$params['skipOnError']; + } + else + { + $params['attributes']=$attributes; + if(isset(self::$builtInValidators[$name])) + $className=Yii::import(self::$builtInValidators[$name],true); + else + $className=Yii::import($name,true); + $validator=new $className; + foreach($params as $name=>$value) + $validator->$name=$value; + } + + $validator->on=empty($on) ? array() : array_combine($on,$on); + + return $validator; + } + + /** + * Validates the specified object. + * @param CModel $object the data object being validated + * @param array $attributes the list of attributes to be validated. Defaults to null, + * meaning every attribute listed in {@link attributes} will be validated. + */ + public function validate($object,$attributes=null) + { + if(is_array($attributes)) + $attributes=array_intersect($this->attributes,$attributes); + else + $attributes=$this->attributes; + foreach($attributes as $attribute) + { + if(!$this->skipOnError || !$object->hasErrors($attribute)) + $this->validateAttribute($object,$attribute); + } + } + + /** + * Returns the JavaScript needed for performing client-side validation. + * Do not override this method if the validator does not support client-side validation. + * Two predefined JavaScript variables can be used: + * <ul> + * <li>value: the value to be validated</li> + * <li>messages: an array used to hold the validation error messages for the value</li> + * </ul> + * @param CModel $object the data object being validated + * @param string $attribute the name of the attribute to be validated. + * @return string the client-side validation script. Null if the validator does not support client-side validation. + * @see CActiveForm::enableClientValidation + * @since 1.1.7 + */ + public function clientValidateAttribute($object,$attribute) + { + } + + /** + * Returns a value indicating whether the validator applies to the specified scenario. + * A validator applies to a scenario as long as any of the following conditions is met: + * <ul> + * <li>the validator's "on" property is empty</li> + * <li>the validator's "on" property contains the specified scenario</li> + * </ul> + * @param string $scenario scenario name + * @return boolean whether the validator applies to the specified scenario. + */ + public function applyTo($scenario) + { + return empty($this->on) || isset($this->on[$scenario]); + } + + /** + * Adds an error about the specified attribute to the active record. + * This is a helper method that performs message selection and internationalization. + * @param CModel $object the data object being validated + * @param string $attribute the attribute being validated + * @param string $message the error message + * @param array $params values for the placeholders in the error message + */ + protected function addError($object,$attribute,$message,$params=array()) + { + $params['{attribute}']=$object->getAttributeLabel($attribute); + $object->addError($attribute,strtr($message,$params)); + } + + /** + * Checks if the given value is empty. + * A value is considered empty if it is null, an empty array, or the trimmed result is an empty string. + * Note that this method is different from PHP empty(). It will return false when the value is 0. + * @param mixed $value the value to be checked + * @param boolean $trim whether to perform trimming before checking if the string is empty. Defaults to false. + * @return boolean whether the value is empty + */ + protected function isEmpty($value,$trim=false) + { + return $value===null || $value===array() || $value==='' || $trim && is_scalar($value) && trim($value)===''; + } +} + |
