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
- 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 `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 #3036: Upgraded Twitter Bootstrap to 3.1.x (qiangxue)
- Chg #3175: InvalidCallException, InvalidParamException, UnknownMethodException are now extended from SPL BadMethodCallException (samdark)
......
......@@ -63,6 +63,11 @@ class ExistValidator extends Validator
public $filter;
/**
* @var boolean whether to allow array type attribute.
*/
public $allowArray = false;
/**
* @inheritdoc
*/
public function init()
......@@ -81,6 +86,9 @@ class ExistValidator extends Validator
$targetAttribute = $this->targetAttribute === null ? $attribute : $this->targetAttribute;
if (is_array($targetAttribute)) {
if ($this->allowArray) {
throw new InvalidConfigException('The "targetAttribute" property must be configured as a string.');
}
$params = [];
foreach ($targetAttribute as $k => $v) {
$params[$v] = is_integer($k) ? $object->$v : $object->$k;
......@@ -89,18 +97,24 @@ class ExistValidator extends Validator
$params = [$targetAttribute => $object->$attribute];
}
foreach ($params as $value) {
if (is_array($value)) {
$this->addError($object, $attribute, Yii::t('yii', '{attribute} is invalid.'));
if (!$this->allowArray) {
foreach ($params as $value) {
if (is_array($value)) {
$this->addError($object, $attribute, Yii::t('yii', '{attribute} is invalid.'));
return;
return;
}
}
}
$targetClass = $this->targetClass === null ? get_class($object) : $this->targetClass;
$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);
}
}
......@@ -110,9 +124,6 @@ class ExistValidator extends Validator
*/
protected function validateValue($value)
{
if (is_array($value)) {
return [$this->message, []];
}
if ($this->targetClass === null) {
throw new InvalidConfigException('The "targetClass" property must be set.');
}
......@@ -122,7 +133,14 @@ class ExistValidator extends Validator
$query = $this->createQuery($this->targetClass, [$this->targetAttribute => $value]);
return $query->exists() ? null : [$this->message, []];
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, []];
}
}
/**
......
......@@ -89,10 +89,39 @@ class ExistValidatorTest extends DatabaseTestCase
$m->a_field = 'some new value';
$val->validateAttribute($m, 'a_field');
$this->assertTrue($m->hasErrors('a_field'));
// check array
// existing array
$val = new ExistValidator(['targetAttribute' => 'ref']);
$m = ValidatorTestRefModel::findOne(['id' => 2]);
$m->test_val = [1,2,3];
$val->allowArray = true;
$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');
$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