Commit 3bd186de by Qiang Xue

refactored validators.

parent b5b1d91e
......@@ -580,8 +580,9 @@ abstract class Module extends Component
* instance of it.
*
* @param string $route the route consisting of module, controller and action IDs.
* @return array|boolean if the controller is created successfully, it will be returned together
* with the remainder of the route which represents the action ID. Otherwise false will be returned.
* @return array|boolean If the controller is created successfully, it will be returned together
* with the requested action ID. Otherwise false will be returned.
* @throws InvalidConfigException if the controller class and its file do not match.
*/
public function createController($route)
{
......
......@@ -7,6 +7,8 @@
namespace yii\validators;
use Yii;
/**
* BooleanValidator checks if the attribute value is a boolean value.
*
......@@ -32,11 +34,6 @@ class BooleanValidator extends Validator
* 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.
......@@ -47,12 +44,8 @@ class BooleanValidator extends Validator
public 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}.');
if (!$this->validateValue($value)) {
$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,
......@@ -60,13 +53,15 @@ class BooleanValidator extends Validator
}
}
/**
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
*/
public function validateValue($value)
{
if ($this->allowEmpty && $this->isEmpty($value)) {
return;
}
return ($this->strict || $value == $this->trueValue || $value == $this->falseValue)
&& (!$this->strict || $value === $this->trueValue || $value === $this->falseValue);
return $this->strict && ($value == $this->trueValue || $value == $this->falseValue)
|| !$this->strict && ($value === $this->trueValue || $value === $this->falseValue);
}
/**
......@@ -77,7 +72,7 @@ class BooleanValidator extends Validator
*/
public function clientValidateAttribute($object, $attribute)
{
$message = ($this->message !== null) ? $this->message : \Yii::t('yii|{attribute} must be either {true} or {false}.');
$message = ($this->message !== null) ? $this->message : Yii::t('yii|{attribute} must be either "{true}" or "{false}".');
$message = strtr($message, array(
'{attribute}' => $object->getAttributeLabel($attribute),
'{value}' => $object->$attribute,
......
......@@ -7,6 +7,9 @@
namespace yii\validators;
use Yii;
use yii\base\InvalidConfigException;
/**
* CaptchaValidator validates that the attribute value is the same as the verification code displayed in the CAPTCHA.
*
......@@ -22,16 +25,10 @@ class CaptchaValidator extends Validator
*/
public $caseSensitive = false;
/**
* @var string the 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 (e.g. 'site/captcha').
*/
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.
* @var string the route of the controller action that renders the CAPTCHA image.
*/
public $allowEmpty = false;
public $captchaAction = 'site/captcha';
/**
* Validates the attribute of the object.
......@@ -42,36 +39,39 @@ class CaptchaValidator extends Validator
public 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.');
if (!$this->validateValue($value)) {
$message = $this->message !== null ? $this->message : Yii::t('yii|The verification code is incorrect.');
$this->addError($object, $attribute, $message);
}
}
/**
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
*/
public function validateValue($value)
{
$captcha = $this->getCaptchaAction();
return $captcha->validate($value, $this->caseSensitive);
}
/**
* Returns the CAPTCHA action object.
* @return CCaptchaAction the action object
* @return CaptchaAction the action object
*/
public function getCaptchaAction()
{
if (strpos($this->captchaAction, '/') !== false) { // contains controller or module
$ca = \Yii::$app->createController($this->captchaAction);
if ($ca !== null) {
$ca = Yii::$app->createController($this->captchaAction);
if ($ca !== false) {
/** @var \yii\base\Controller $controller */
list($controller, $actionID) = $ca;
$action = $controller->createAction($actionID);
if ($action !== null) {
return $action;
}
} else {
$action = \Yii::$app->getController()->createAction($this->captchaAction);
}
if ($action === null) {
throw new \yii\base\Exception('Invalid captcha action ID: ' . $this->captchaAction);
}
return $action;
throw new InvalidConfigException('Invalid CAPTCHA action ID: ' . $this->captchaAction);
}
/**
......
......@@ -6,6 +6,7 @@
*/
namespace yii\validators;
use Yii;
use yii\base\InvalidConfigException;
......@@ -45,23 +46,12 @@ class CompareValidator extends Validator
*/
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:
* @var string the operator for comparison. The following operators are supported:
*
* - `=` or `==`: validates to see if the two values are equal. If [[strict]] is true, the comparison
* will be done in strict mode (i.e. checking value type as well).
* - `!=`: validates to see if the two values are NOT equal. If [[strict]] is true, the comparison
* will be done in strict mode (i.e. checking value type as well).
* - '==': validates to see if the two values are equal. The comparison is done is non-strict mode.
* - '===': validates to see if the two values are equal. The comparison is done is strict mode.
* - '!=': validates to see if the two values are NOT equal. The comparison is done is non-strict mode.
* - '!==': validates to see if the two values are NOT equal. The comparison is done is strict mode.
* - `>`: validates to see if the value being validated is greater than the value being compared with.
* - `>=`: validates to see if the value being validated is greater than or equal to the value being compared with.
* - `<`: validates to see if the value being validated is less than the value being compared with.
......@@ -79,9 +69,6 @@ class CompareValidator extends Validator
public function validateAttribute($object, $attribute)
{
$value = $object->$attribute;
if ($this->allowEmpty && $this->isEmpty($value)) {
return;
}
if ($this->compareValue !== null) {
$compareLabel = $compareValue = $this->compareValue;
} else {
......@@ -91,15 +78,26 @@ class CompareValidator extends Validator
}
switch ($this->operator) {
case '=':
case '==':
if (($this->strict && $value !== $compareValue) || (!$this->strict && $value != $compareValue)) {
if ($value != $compareValue) {
$message = ($this->message !== null) ? $this->message : Yii::t('yii|{attribute} must be repeated exactly.');
$this->addError($object, $attribute, $message, array('{compareAttribute}' => $compareLabel));
}
break;
case '===':
if ($value !== $compareValue) {
$message = ($this->message !== null) ? $this->message : Yii::t('yii|{attribute} must be repeated exactly.');
$this->addError($object, $attribute, $message, array('{compareAttribute}' => $compareLabel));
}
break;
case '!=':
if (($this->strict && $value === $compareValue) || (!$this->strict && $value == $compareValue)) {
if ($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}' => $compareLabel, '{compareValue}' => $compareValue));
}
break;
case '!==':
if ($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}' => $compareLabel, '{compareValue}' => $compareValue));
}
......@@ -134,6 +132,31 @@ class CompareValidator extends Validator
}
/**
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
*/
public function validateValue($value)
{
if ($this->compareValue === null) {
throw new InvalidConfigException('CompareValidator::compareValue must be set.');
}
switch ($this->operator) {
case '==': return $value == $this->compareValue;
case '===': return $value === $this->compareValue;
case '!=': return $value != $this->compareValue;
case '!==': return $value !== $this->compareValue;
case '>': return $value > $this->compareValue;
case '>=': return $value >= $this->compareValue;
case '<': return $value < $this->compareValue;
case '<=': return $value <= $this->compareValue;
default:
throw new InvalidConfigException("Unknown operator \"{$this->operator}\"");
}
}
/**
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated
......
......@@ -10,12 +10,8 @@ namespace yii\validators;
/**
* DefaultValueValidator sets the attribute to be the specified default value.
*
* By default, when the attribute being validated is [[isEmpty|empty]], the validator
* will assign a default [[value]] to it. However, if [[setOnEmpty]] is false, the validator
* will always assign the default [[value]] to the attribute, no matter it is empty or not.
*
* DefaultValueValidator is not really a validator. It is provided mainly to allow
* specifying attribute default values in a dynamic way.
* specifying attribute default values when they are empty.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
......@@ -27,11 +23,10 @@ class DefaultValueValidator extends Validator
*/
public $value;
/**
* @var boolean whether to set the default [[value]] only when the attribute is [[isEmpty|empty]].
* Defaults to true. If false, the attribute will always be assigned with the default [[value]],
* no matter it is empty or not.
* @var boolean this property is overwritten to be false so that this validator will
* be applied when the value being validated is empty.
*/
public $setOnEmpty = true;
public $skipOnEmpty = false;
/**
* Validates the attribute of the object.
......@@ -40,7 +35,7 @@ class DefaultValueValidator extends Validator
*/
public function validateAttribute($object, $attribute)
{
if (!$this->setOnEmpty || $this->isEmpty($object->$attribute)) {
if ($this->isEmpty($object->$attribute)) {
$object->$attribute = $this->value;
}
}
......
......@@ -42,11 +42,6 @@ class EmailValidator extends Validator
* 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.
......@@ -57,9 +52,6 @@ class EmailValidator extends Validator
public 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);
......@@ -67,11 +59,9 @@ class EmailValidator extends Validator
}
/**
* Validates a static value to see if it is a valid email.
* Note that this method does not respect [[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
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
*/
public function validateValue($value)
{
......
......@@ -6,6 +6,8 @@
*/
namespace yii\validators;
use Yii;
use yii\base\InvalidConfigException;
/**
......@@ -34,11 +36,6 @@ class ExistValidator extends Validator
* @see className
*/
public $attributeName;
/**
* @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.
......@@ -46,29 +43,41 @@ class ExistValidator extends Validator
*
* @param \yii\db\ActiveRecord $object the object being validated
* @param string $attribute the attribute being validated
* @throws InvalidConfigException if table doesn't have column specified
*/
public function validateAttribute($object, $attribute)
{
$value = $object->$attribute;
if ($this->allowEmpty && $this->isEmpty($value)) {
return;
}
/** @var $className \yii\db\ActiveRecord */
$className = ($this->className === null) ? get_class($object) : \Yii::import($this->className);
$attributeName = ($this->attributeName === null) ? $attribute : $this->attributeName;
$table = $className::getTableSchema();
if (($column = $table->getColumn($attributeName)) === null) {
throw new InvalidConfigException('Table "' . $table->name . '" does not have a column named "' . $attributeName . '"');
}
$className = $this->className === null ? get_class($object) : Yii::import($this->className);
$attributeName = $this->attributeName === null ? $attribute : $this->attributeName;
$query = $className::find();
$query->where(array($column->name => $value));
$query->where(array($attributeName => $value));
if (!$query->exists()) {
$message = ($this->message !== null) ? $this->message : \Yii::t('yii|{attribute} "{value}" is invalid.');
$message = $this->message !== null ? $this->message : Yii::t('yii|{attribute} "{value}" is invalid.');
$this->addError($object, $attribute, $message);
}
}
/**
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
* @throws InvalidConfigException if either [[className]] or [[attributeName]] is not set.
*/
public function validateValue($value)
{
if ($this->className === null) {
throw new InvalidConfigException('The "className" property must be set.');
}
if ($this->attributeName === null) {
throw new InvalidConfigException('The "attributeName" property must be set.');
}
/** @var $className \yii\db\ActiveRecord */
$className = $this->className;
$query = $className::find();
$query->where(array($this->attributeName => $value));
return $query->exists();
}
}
......@@ -38,6 +38,23 @@ class FilterValidator extends Validator
* ~~~
*/
public $filter;
/**
* @var boolean this property is overwritten to be false so that this validator will
* be applied when the value being validated is empty.
*/
public $skipOnEmpty = false;
/**
* Initializes the validator.
* @throws InvalidConfigException if [[filter]] is not set.
*/
public function init()
{
parent::init();
if ($this->filter === null) {
throw new InvalidConfigException('The "filter" property must be set.');
}
}
/**
* Validates the attribute of the object.
......@@ -48,9 +65,6 @@ class FilterValidator extends Validator
*/
public function validateAttribute($object, $attribute)
{
if ($this->filter === null) {
throw new InvalidConfigException('The "filter" property must be specified with a valid callback.');
}
$object->$attribute = call_user_func($this->filter, $object->$attribute);
}
}
......@@ -25,8 +25,9 @@ namespace yii\validators;
class InlineValidator extends Validator
{
/**
* @var string the name of the validation method defined in the
* \yii\base\Model class
* @var string|\Closure an anonymous function or the name of a model class method that will be
* called to perform the actual validation. Note that if you use anonymous function, you cannot
* use `$this` in it unless you are using PHP 5.4 or above.
*/
public $method;
/**
......@@ -34,8 +35,8 @@ class InlineValidator extends Validator
*/
public $params;
/**
* @var string the name of the method that returns the client validation code (see [[clientValidateAttribute()]]
* for details on how to return client validation code). The signature of the method should be like the following:
* @var string|\Closure an anonymous function or the name of a model class method that returns the client validation code.
* The signature of the method should be like the following:
*
* ~~~
* function foo($attribute)
......@@ -45,6 +46,8 @@ class InlineValidator extends Validator
* ~~~
*
* where `$attribute` refers to the attribute name to be validated.
*
* Please refer to [[clientValidateAttribute()]] for details on how to return client validation code.
*/
public $clientValidate;
......@@ -56,7 +59,10 @@ class InlineValidator extends Validator
public function validateAttribute($object, $attribute)
{
$method = $this->method;
$object->$method($attribute, $this->params);
if (is_string($method)) {
$method = array($object, $method);
}
call_user_func($method, $attribute, $this->params);
}
/**
......@@ -82,7 +88,10 @@ class InlineValidator extends Validator
{
if ($this->clientValidate !== null) {
$method = $this->clientValidate;
return $object->$method($attribute);
if (is_string($method)) {
$method = array($object, $method);
}
return call_user_func($method, $attribute);
} else {
return null;
}
......
......@@ -26,11 +26,6 @@ class NumberValidator extends Validator
*/
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;
......@@ -66,9 +61,6 @@ class NumberValidator extends Validator
public 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.');
......@@ -81,16 +73,28 @@ class NumberValidator extends Validator
}
}
if ($this->min !== null && $value < $this->min) {
$message = $this->tooSmall !== null ? $this->tooSmall : Yii::t('yii|{attribute} is too small (minimum is {min}).');
$message = $this->tooSmall !== null ? $this->tooSmall : Yii::t('yii|{attribute} must be no less than {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}).');
$message = $this->tooBig !== null ? $this->tooBig : Yii::t('yii|{attribute} must be no greater than {max}.');
$this->addError($object, $attribute, $message, array('{max}' => $this->max));
}
}
/**
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
*/
public function validateValue($value)
{
return preg_match($this->integerOnly ? $this->integerPattern : $this->numberPattern, "$value")
&& ($this->min === null || $value >= $this->min)
&& ($this->max === null || $value <= $this->max);
}
/**
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
......@@ -116,7 +120,7 @@ if(!value.match($pattern)) {
";
if ($this->min !== null) {
if (($tooSmall = $this->tooSmall) === null) {
$tooSmall = Yii::t('yii|{attribute} is too small (minimum is {min}).');
$tooSmall = Yii::t('yii|{attribute} must be no less than {min}.');
}
$tooSmall = strtr($tooSmall, array(
'{attribute}' => $label,
......@@ -131,7 +135,7 @@ if(value<{$this->min}) {
}
if ($this->max !== null) {
if (($tooBig = $this->tooBig) === null) {
$tooBig = Yii::t('yii|{attribute} is too big (maximum is {max}).');
$tooBig = Yii::t('yii|{attribute} must be no greater than {max}.');
}
$tooBig = strtr($tooBig, array(
'{attribute}' => $label,
......
......@@ -29,56 +29,61 @@ class RangeValidator extends Validator
*/
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 [[range]].
**/
public $not = false;
/**
* Initializes the validator.
* @throws InvalidConfigException if [[range]] is not set.
*/
public function init()
{
parent::init();
if (!is_array($this->range)) {
throw new InvalidConfigException('The "range" property must be set.');
}
}
/**
* Validates the attribute of the object.
* If there is any error, the error message is added to the object.
* @param \yii\base\Model $object the object being validated
* @param string $attribute the attribute being validated
* @throws InvalidConfigException if the "range" property is not an array
*/
public function validateAttribute($object, $attribute)
{
$value = $object->$attribute;
if ($this->allowEmpty && $this->isEmpty($value)) {
return;
}
if (!is_array($this->range)) {
throw new InvalidConfigException('The "range" property must be specified as an array.');
}
$message = $this->message !== null ? $this->message : \Yii::t('yii|{attribute} is invalid.');
if (!$this->not && !in_array($value, $this->range, $this->strict)) {
$message = ($this->message !== null) ? $this->message : \Yii::t('yii|{attribute} should be in the list.');
$this->addError($object, $attribute, $message);
} elseif ($this->not && in_array($value, $this->range, $this->strict)) {
$message = ($this->message !== null) ? $this->message : \Yii::t('yii|{attribute} should NOT be in the list.');
$this->addError($object, $attribute, $message);
}
}
/**
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
*/
public function validateValue($value)
{
return !$this->not && in_array($value, $this->range, $this->strict)
|| $this->not && !in_array($value, $this->range, $this->strict);
}
/**
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @return string the client-side validation script.
* @throws InvalidConfigException if the "range" property is not an array
*/
public function clientValidateAttribute($object, $attribute)
{
if (!is_array($this->range)) {
throw new InvalidConfigException('The "range" property must be specified as an array.');
}
if (($message = $this->message) === null) {
$message = $this->not ? \Yii::t('yii|{attribute} should NOT be in the list.') : \Yii::t('yii|{attribute} should be in the list.');
$message = \Yii::t('yii|{attribute} is invalid.');
}
$message = strtr($message, array(
'{attribute}' => $object->getAttributeLabel($attribute),
......
......@@ -7,6 +7,8 @@
namespace yii\validators;
use yii\base\InvalidConfigException;
/**
* RegularExpressionValidator validates that the attribute value matches the specified [[pattern]].
*
......@@ -22,32 +24,33 @@ class RegularExpressionValidator extends Validator
*/
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 [[pattern]] should NOT match the attribute value.
* @throws InvalidConfigException if the "pattern" is not a valid regular expression
**/
public $not = false;
/**
* Initializes the validator.
* @throws InvalidConfigException if [[pattern]] is not set.
*/
public function init()
{
parent::init();
if ($this->pattern === null) {
throw new InvalidConfigException('The "pattern" property must be set.');
}
}
/**
* Validates the attribute of the object.
* If there is any error, the error message is added to the object.
* @param \yii\base\Model $object the object being validated
* @param string $attribute the attribute being validated
* @throws \yii\base\Exception if the "pattern" is not a valid regular expression
*/
public function validateAttribute($object, $attribute)
{
$value = $object->$attribute;
if ($this->allowEmpty && $this->isEmpty($value)) {
return;
}
if ($this->pattern === null) {
throw new \yii\base\Exception('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);
......@@ -55,18 +58,25 @@ class RegularExpressionValidator extends Validator
}
/**
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
*/
public function validateValue($value)
{
return !$this->not && preg_match($this->pattern, $value)
|| $this->not && !preg_match($this->pattern, $value);
}
/**
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @return string the client-side validation script.
* @throws \yii\base\Exception if the "pattern" is not a valid regular expression
* @throws InvalidConfigException if the "pattern" is not a valid regular expression
*/
public function clientValidateAttribute($object, $attribute)
{
if ($this->pattern === null) {
throw new \yii\base\Exception('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),
......
......@@ -16,6 +16,10 @@ namespace yii\validators;
class RequiredValidator extends Validator
{
/**
* @var boolean whether to skip this validator if the value being validated is empty.
*/
public $skipOnEmpty = false;
/**
* @var mixed the desired value that the attribute must have.
* If this is null, the validator will validate that the specified attribute is not empty.
* If this is set as a value that is not null, the validator will validate that
......@@ -59,6 +63,23 @@ class RequiredValidator extends Validator
}
/**
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
*/
public function validateValue($value)
{
if ($this->requiredValue === null) {
if ($this->strict && $value !== null || !$this->strict && !$this->isEmpty($value, true)) {
return true;
}
} elseif (!$this->strict && $value == $this->requiredValue || $this->strict && $value === $this->requiredValue) {
return true;
}
return false;
}
/**
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
......
......@@ -7,6 +7,8 @@
namespace yii\validators;
use Yii;
/**
* StringValidator validates that the attribute value is of certain length.
*
......@@ -46,19 +48,22 @@ class StringValidator extends Validator
*/
public $notEqual;
/**
* @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.
* @var string the encoding of the string value to be validated (e.g. 'UTF-8').
* If this property is not set, [[\yii\base\Application::charset]] will be used.
*/
public $allowEmpty = true;
public $encoding;
/**
* @var mixed 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.
* Initializes the validator.
*/
public $encoding;
public function init()
{
parent::init();
if ($this->encoding === null) {
$this->encoding = Yii::$app->charset;
}
}
/**
* Validates the attribute of the object.
......@@ -69,37 +74,46 @@ class StringValidator extends Validator
public function validateAttribute($object, $attribute)
{
$value = $object->$attribute;
if ($this->allowEmpty && $this->isEmpty($value)) {
return;
}
if (!is_string($value)) {
$message = ($this->message !== null) ? $this->message : \Yii::t('yii|{attribute} must be a string.');
$message = ($this->message !== null) ? $this->message : Yii::t('yii|{attribute} must be a string.');
$this->addError($object, $attribute, $message);
return;
}
if (function_exists('mb_strlen') && $this->encoding !== false) {
$length = mb_strlen($value, $this->encoding ? $this->encoding : \Yii::$app->charset);
} else {
$length = strlen($value);
}
$length = mb_strlen($value, $this->encoding);
if ($this->min !== null && $length < $this->min) {
$message = ($this->tooShort !== null) ? $this->tooShort : \Yii::t('yii|{attribute} is too short (minimum is {min} characters).');
$message = ($this->tooShort !== null) ? $this->tooShort : Yii::t('yii|{attribute} should contain at least {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).');
$message = ($this->tooLong !== null) ? $this->tooLong : Yii::t('yii|{attribute} should contain at most {max} characters.');
$this->addError($object, $attribute, $message, array('{max}' => $this->max));
}
if ($this->is !== null && $length !== $this->is) {
$message = ($this->notEqual !== null) ? $this->notEqual : \Yii::t('yii|{attribute} is of the wrong length (should be {length} characters).');
$message = ($this->notEqual !== null) ? $this->notEqual : Yii::t('yii|{attribute} should contain {length} characters.');
$this->addError($object, $attribute, $message, array('{length}' => $this->is));
}
}
/**
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
*/
public function validateValue($value)
{
if (!is_string($value)) {
return false;
}
$length = mb_strlen($value, $this->encoding);
return ($this->min === null || $length >= $this->min)
&& ($this->max === null || $length <= $this->max)
&& ($this->is === null || $length === $this->is);
}
/**
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
......@@ -111,7 +125,7 @@ class StringValidator extends Validator
$value = $object->$attribute;
if (($notEqual = $this->notEqual) === null) {
$notEqual = \Yii::t('yii|{attribute} is of the wrong length (should be {length} characters).');
$notEqual = Yii::t('yii|{attribute} should contain {length} characters.');
}
$notEqual = strtr($notEqual, array(
'{attribute}' => $label,
......@@ -120,7 +134,7 @@ class StringValidator extends Validator
));
if (($tooShort = $this->tooShort) === null) {
$tooShort = \Yii::t('yii|{attribute} is too short (minimum is {min} characters).');
$tooShort = Yii::t('yii|{attribute} should contain at least {min} characters.');
}
$tooShort = strtr($tooShort, array(
'{attribute}' => $label,
......@@ -129,7 +143,7 @@ class StringValidator extends Validator
));
if (($tooLong = $this->tooLong) === null) {
$tooLong = \Yii::t('yii|{attribute} is too long (maximum is {max} characters).');
$tooLong = Yii::t('yii|{attribute} should contain at most {max} characters.');
}
$tooLong = strtr($tooLong, array(
'{attribute}' => $label,
......
......@@ -17,11 +17,6 @@ use yii\base\InvalidConfigException;
class UniqueValidator extends Validator
{
/**
* @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 or alias of the class
* 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.
......@@ -45,10 +40,6 @@ class UniqueValidator extends Validator
public function validateAttribute($object, $attribute)
{
$value = $object->$attribute;
if ($this->allowEmpty && $this->isEmpty($value)) {
return;
}
/** @var $className \yii\db\ActiveRecord */
$className = $this->className === null ? get_class($object) : \Yii::import($this->className);
$attributeName = $this->attributeName === null ? $attribute : $this->attributeName;
......
......@@ -32,11 +32,6 @@ class UrlValidator extends Validator
* contain the scheme part.
**/
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.
......@@ -47,11 +42,10 @@ class UrlValidator extends Validator
public function validateAttribute($object, $attribute)
{
$value = $object->$attribute;
if ($this->allowEmpty && $this->isEmpty($value)) {
return;
if ($this->validateValue($value)) {
if ($this->defaultScheme !== null && strpos($value, '://') === false) {
$object->$attribute = $this->defaultScheme . '://' . $value;
}
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);
......@@ -59,11 +53,9 @@ class UrlValidator extends Validator
}
/**
* Validates a static value to see if it is a valid URL.
* Note that this method does not respect [[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})
* Validates the given value.
* @param mixed $value the value to be validated.
* @return boolean whether the value is valid.
*/
public function validateValue($value)
{
......@@ -80,7 +72,7 @@ class UrlValidator extends Validator
}
if (preg_match($pattern, $value)) {
return $value;
return true;
}
}
return false;
......
......@@ -7,6 +7,7 @@
namespace yii\validators;
use Yii;
use yii\base\Component;
use yii\base\NotSupportedException;
......@@ -95,6 +96,12 @@ abstract class Validator extends Component
*/
public $skipOnError = true;
/**
* @var boolean whether this validation rule should be skipped if the attribute value
* is null or an empty string.
*/
public $skipOnEmpty = true;
/**
* @var boolean whether to enable client-side validation. Defaults to null, meaning
* its actual value inherits from that of [[\yii\web\ActiveForm::enableClientValidation]].
*/
......@@ -150,7 +157,7 @@ abstract class Validator extends Component
}
}
return \Yii::createObject($params);
return Yii::createObject($params);
}
/**
......@@ -169,12 +176,20 @@ abstract class Validator extends Component
$attributes = $this->attributes;
}
foreach ($attributes as $attribute) {
if (!($this->skipOnError && $object->hasErrors($attribute))) {
$skip = $this->skipOnError && $object->hasErrors($attribute)
|| $this->skipOnEmpty && $this->isEmpty($object->$attribute);
if (!$skip) {
$this->validateAttribute($object, $attribute);
}
}
}
/**
* Validates a value.
* A validator class can implement this method to support data validation out of the context of a data model.
* @param mixed $value the data value to be validated.
* @throws NotSupportedException if data validation without a model is not supported
*/
public function validateValue($value)
{
throw new NotSupportedException(__CLASS__ . ' does not support validateValue().');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment