Commit 15904951 by Carsten Brandt

Merge PR #3406 branch 'exist-validator-enhancement' of https://github.com/creocoder/yii2

* 'exist-validator-enhancement' of https://github.com/creocoder/yii2: ExistValidator final refactoring. `allowArray` checking also added to `validateValue` method. New tests added New tests added ExistValidator::validateValue() fixed Tests excess dump removed ExistValidator bugfix Tests updated ExistValidator refactoring CHANGELOG updated `allowArray` introduced. CHANGELOG ExistValidator count logic fix Tests updated Tests updated Tests updated Refactoring Refactoring Improve `exist` validator to support array attributes Conflicts: framework/CHANGELOG.md
parents 95cf5f39 49f8d45d
...@@ -53,6 +53,7 @@ Yii Framework 2 Change Log ...@@ -53,6 +53,7 @@ Yii Framework 2 Change Log
- Enh: `yii\console\MigrateController` now returns `yii\console\Controller::EXIT_CODE_ERROR` in case of failed migration (samdark) - Enh: `yii\console\MigrateController` now returns `yii\console\Controller::EXIT_CODE_ERROR` in case of failed migration (samdark)
- Enh: Added method ErrorHandler::unregister() for unregistering the ErrorHandler (cebe) - Enh: Added method ErrorHandler::unregister() for unregistering the ErrorHandler (cebe)
- Enh: Added `all` option to `MigrateController::actionDown()` action (creocoder, umneeq) - Enh: Added `all` option to `MigrateController::actionDown()` action (creocoder, umneeq)
- Enh: Added support for array attributes in `exist` validator (creocoder)
- Chg #2913: RBAC `DbManager` is now initialized via migration (samdark) - Chg #2913: RBAC `DbManager` is now initialized via migration (samdark)
- Chg #3036: Upgraded Twitter Bootstrap to 3.1.x (qiangxue) - Chg #3036: Upgraded Twitter Bootstrap to 3.1.x (qiangxue)
- Chg #3175: InvalidCallException, InvalidParamException, UnknownMethodException are now extended from SPL BadMethodCallException (samdark) - Chg #3175: InvalidCallException, InvalidParamException, UnknownMethodException are now extended from SPL BadMethodCallException (samdark)
......
...@@ -63,6 +63,11 @@ class ExistValidator extends Validator ...@@ -63,6 +63,11 @@ class ExistValidator extends Validator
public $filter; public $filter;
/** /**
* @var boolean whether to allow array type attribute.
*/
public $allowArray = false;
/**
* @inheritdoc * @inheritdoc
*/ */
public function init() public function init()
...@@ -81,6 +86,9 @@ class ExistValidator extends Validator ...@@ -81,6 +86,9 @@ class ExistValidator extends Validator
$targetAttribute = $this->targetAttribute === null ? $attribute : $this->targetAttribute; $targetAttribute = $this->targetAttribute === null ? $attribute : $this->targetAttribute;
if (is_array($targetAttribute)) { if (is_array($targetAttribute)) {
if ($this->allowArray) {
throw new InvalidConfigException('The "targetAttribute" property must be configured as a string.');
}
$params = []; $params = [];
foreach ($targetAttribute as $k => $v) { foreach ($targetAttribute as $k => $v) {
$params[$v] = is_integer($k) ? $object->$v : $object->$k; $params[$v] = is_integer($k) ? $object->$v : $object->$k;
...@@ -89,6 +97,7 @@ class ExistValidator extends Validator ...@@ -89,6 +97,7 @@ class ExistValidator extends Validator
$params = [$targetAttribute => $object->$attribute]; $params = [$targetAttribute => $object->$attribute];
} }
if (!$this->allowArray) {
foreach ($params as $value) { foreach ($params as $value) {
if (is_array($value)) { if (is_array($value)) {
$this->addError($object, $attribute, Yii::t('yii', '{attribute} is invalid.')); $this->addError($object, $attribute, Yii::t('yii', '{attribute} is invalid.'));
...@@ -96,11 +105,16 @@ class ExistValidator extends Validator ...@@ -96,11 +105,16 @@ class ExistValidator extends Validator
return; return;
} }
} }
}
$targetClass = $this->targetClass === null ? get_class($object) : $this->targetClass; $targetClass = $this->targetClass === null ? get_class($object) : $this->targetClass;
$query = $this->createQuery($targetClass, $params); $query = $this->createQuery($targetClass, $params);
if (!$query->exists()) { if (is_array($object->$attribute)) {
if ($query->count("DISTINCT [[$targetAttribute]]") != count($object->$attribute)) {
$this->addError($object, $attribute, $this->message);
}
} elseif (!$query->exists()) {
$this->addError($object, $attribute, $this->message); $this->addError($object, $attribute, $this->message);
} }
} }
...@@ -110,9 +124,6 @@ class ExistValidator extends Validator ...@@ -110,9 +124,6 @@ class ExistValidator extends Validator
*/ */
protected function validateValue($value) protected function validateValue($value)
{ {
if (is_array($value)) {
return [$this->message, []];
}
if ($this->targetClass === null) { if ($this->targetClass === null) {
throw new InvalidConfigException('The "targetClass" property must be set.'); throw new InvalidConfigException('The "targetClass" property must be set.');
} }
...@@ -122,8 +133,15 @@ class ExistValidator extends Validator ...@@ -122,8 +133,15 @@ class ExistValidator extends Validator
$query = $this->createQuery($this->targetClass, [$this->targetAttribute => $value]); $query = $this->createQuery($this->targetClass, [$this->targetAttribute => $value]);
if (is_array($value)) {
if (!$this->allowArray) {
return [$this->message, []];
}
return $query->count("DISTINCT [[$this->targetAttribute]]") == count($value) ? null : [$this->message, []];
} else {
return $query->exists() ? null : [$this->message, []]; return $query->exists() ? null : [$this->message, []];
} }
}
/** /**
* Creates a query instance with the given condition. * Creates a query instance with the given condition.
......
...@@ -89,10 +89,39 @@ class ExistValidatorTest extends DatabaseTestCase ...@@ -89,10 +89,39 @@ class ExistValidatorTest extends DatabaseTestCase
$m->a_field = 'some new value'; $m->a_field = 'some new value';
$val->validateAttribute($m, 'a_field'); $val->validateAttribute($m, 'a_field');
$this->assertTrue($m->hasErrors('a_field')); $this->assertTrue($m->hasErrors('a_field'));
// check array // existing array
$val = new ExistValidator(['targetAttribute' => 'ref']); $val = new ExistValidator(['targetAttribute' => 'ref']);
$m = ValidatorTestRefModel::findOne(['id' => 2]); $val->allowArray = true;
$m->test_val = [1,2,3]; $m = new ValidatorTestRefModel();
$m->test_val = [2, 3, 4, 5];
$val->validateAttribute($m, 'test_val');
$this->assertFalse($m->hasErrors('test_val'));
// non-existing array
$val = new ExistValidator(['targetAttribute' => 'ref']);
$val->allowArray = true;
$m = new ValidatorTestRefModel();
$m->test_val = [95, 96, 97, 98];
$val->validateAttribute($m, 'test_val');
$this->assertTrue($m->hasErrors('test_val'));
// partial-existing array
$val = new ExistValidator(['targetAttribute' => 'ref']);
$val->allowArray = true;
$m = new ValidatorTestRefModel();
$m->test_val = [2, 97, 3, 98];
$val->validateAttribute($m, 'test_val');
$this->assertTrue($m->hasErrors('test_val'));
// existing array (allowArray = false)
$val = new ExistValidator(['targetAttribute' => 'ref']);
$val->allowArray = false;
$m = new ValidatorTestRefModel();
$m->test_val = [2, 3, 4, 5];
$val->validateAttribute($m, 'test_val');
$this->assertTrue($m->hasErrors('test_val'));
// non-existing array (allowArray = false)
$val = new ExistValidator(['targetAttribute' => 'ref']);
$val->allowArray = false;
$m = new ValidatorTestRefModel();
$m->test_val = [95, 96, 97, 98];
$val->validateAttribute($m, 'test_val'); $val->validateAttribute($m, 'test_val');
$this->assertTrue($m->hasErrors('test_val')); $this->assertTrue($m->hasErrors('test_val'));
} }
......
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