Fixes #14304: Fixed yii\validators\UniqueValidator and yii\validators\ExistValidator to skip prefixes in case expressions are used

This commit is contained in:
Alexander Makarov
2017-06-27 00:02:47 +03:00
committed by GitHub
parent 606b6d44f4
commit d4c15c36d0
5 changed files with 54 additions and 2 deletions

View File

@ -17,6 +17,7 @@ Yii Framework 2 Change Log
- Enh #14081: Added `yii\caching\CacheInterface` to make custom cache extensions adoption easier (silverfire) - Enh #14081: Added `yii\caching\CacheInterface` to make custom cache extensions adoption easier (silverfire)
- Chg #14286: Used primary inputmask package name instead of an alias (samdark) - Chg #14286: Used primary inputmask package name instead of an alias (samdark)
- Enh #14298: The default response formatter configs defined by `yii\web\Response::defaultFormatters()` now use the array syntax (brandonkelly) - Enh #14298: The default response formatter configs defined by `yii\web\Response::defaultFormatters()` now use the array syntax (brandonkelly)
- Bug #14304: Fixed `yii\validators\UniqueValidator` and `yii\validators\ExistValidator` to skip prefixes in case expressions are used (samdark)
- Bug #14341: Fixed regression in error handling introduced by fixing #14264 (samdark) - Bug #14341: Fixed regression in error handling introduced by fixing #14264 (samdark)
2.0.12 June 05, 2017 2.0.12 June 05, 2017

View File

@ -221,10 +221,16 @@ class ExistValidator extends Validator
} }
$prefixedConditions = []; $prefixedConditions = [];
foreach ($conditions as $columnName => $columnValue) { foreach ($conditions as $columnName => $columnValue) {
$prefixedColumn = "{$alias}.[[" . preg_replace( if (strpos($columnName, '(') === false) {
$prefixedColumn = "{$alias}.[[" . preg_replace(
'/^' . preg_quote($alias) . '\.(.*)$/', '/^' . preg_quote($alias) . '\.(.*)$/',
'$1', '$1',
$columnName) . ']]'; $columnName) . ']]';
} else {
// there is an expression, can't prefix it reliably
$prefixedColumn = $columnName;
}
$prefixedConditions[$prefixedColumn] = $columnValue; $prefixedConditions[$prefixedColumn] = $columnValue;
} }
return $prefixedConditions; return $prefixedConditions;

View File

@ -288,10 +288,16 @@ class UniqueValidator extends Validator
} }
$prefixedConditions = []; $prefixedConditions = [];
foreach ($conditions as $columnName => $columnValue) { foreach ($conditions as $columnName => $columnValue) {
$prefixedColumn = "{$alias}.[[" . preg_replace( if (strpos($columnName, '(') === false) {
$prefixedColumn = "{$alias}.[[" . preg_replace(
'/^' . preg_quote($alias) . '\.(.*)$/', '/^' . preg_quote($alias) . '\.(.*)$/',
'$1', '$1',
$columnName) . ']]'; $columnName) . ']]';
} else {
// there is an expression, can't prefix it reliably
$prefixedColumn = $columnName;
}
$prefixedConditions[$prefixedColumn] = $columnValue; $prefixedConditions[$prefixedColumn] = $columnValue;
} }
return $prefixedConditions; return $prefixedConditions;

View File

@ -11,6 +11,7 @@ use Yii;
use yii\base\Exception; use yii\base\Exception;
use yii\validators\ExistValidator; use yii\validators\ExistValidator;
use yiiunit\data\ar\ActiveRecord; use yiiunit\data\ar\ActiveRecord;
use yiiunit\data\ar\Document;
use yiiunit\data\ar\Order; use yiiunit\data\ar\Order;
use yiiunit\data\ar\OrderItem; use yiiunit\data\ar\OrderItem;
use yiiunit\data\validators\models\ValidatorTestMainModel; use yiiunit\data\validators\models\ValidatorTestMainModel;
@ -190,4 +191,20 @@ abstract class ExistValidatorTest extends DatabaseTestCase
OrderItem::$tableName = $oldTableName; OrderItem::$tableName = $oldTableName;
} }
/**
* Test expresssion in targetAttribute
* @see https://github.com/yiisoft/yii2/issues/14304
*/
public function testExpresionInAttributeColumnName()
{
$val = new ExistValidator([
'targetClass' => OrderItem::className(),
'targetAttribute' => ['id' => 'COALESCE(order_id, 0)'],
]);
$m = new Order(['id' => 1]);
$val->validateAttribute($m, 'id');
$this->assertFalse($m->hasErrors('id'));
}
} }

View File

@ -11,6 +11,7 @@ use Yii;
use yii\validators\UniqueValidator; use yii\validators\UniqueValidator;
use yiiunit\data\ar\ActiveRecord; use yiiunit\data\ar\ActiveRecord;
use yiiunit\data\ar\Customer; use yiiunit\data\ar\Customer;
use yiiunit\data\ar\Document;
use yiiunit\data\ar\Order; use yiiunit\data\ar\Order;
use yiiunit\data\ar\OrderItem; use yiiunit\data\ar\OrderItem;
use yiiunit\data\ar\Profile; use yiiunit\data\ar\Profile;
@ -412,4 +413,25 @@ abstract class UniqueValidatorTest extends DatabaseTestCase
$validator->validateAttribute($model, 'id'); $validator->validateAttribute($model, 'id');
$this->assertFalse($model->hasErrors()); $this->assertFalse($model->hasErrors());
} }
/**
* Test expresssion in targetAttribute
* @see https://github.com/yiisoft/yii2/issues/14304
*/
public function testExpresionInAttributeColumnName()
{
$validator = new UniqueValidator([
'targetAttribute' => [
'title' => 'LOWER(title)',
],
]);
$model = new Document();
$model->id = 42;
$model->title = 'Test';
$model->content = 'test';
$model->version = 1;
$model->save(false);
$validator->validateAttribute($model, 'title');
$this->assertFalse($model->hasErrors(), 'There were errors: ' . json_encode($model->getErrors()));
}
} }