Skip to content

Commit

Permalink
Fixes #16280: Fixed yii\base\Model::getActiveValidators() to return…
Browse files Browse the repository at this point in the history
… correct validators for attribute on scenario
  • Loading branch information
paweljankowiak06 authored and samdark committed May 20, 2018
1 parent 3278b0a commit 33fe347
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 15 deletions.
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Yii Framework 2 Change Log
- Bug #16245: Fixed `__isset()` in `BaseActiveRecord` not catching errors (sammousa)
- Bug #16266: Fixed `yii\helpers\BaseStringHelper` where explode would not allow 0 as trim string (Thoulah)
- Bug #16277: Fixed `yii\db\Query::from()` to respect `yii\db\ExpressionInterface` (noname007)
- Bug #16280: Fixed `yii\base\Model::getActiveValidators()` to return correct validators for attribute on scenario (paweljankowiak06)
- Enh #16191: Enhanced `yii\helpers\Inflector` to work correctly with UTF-8 (silverfire)
- Bug: Fixed bad instnaceof check in `yii\db\Schema::getTableMetadata()` (samdark)
- Bug #16292: Fixed misconfigured CORS filter exception throwing. Now it throws `InvalidConfigException` in Debug mode (khvalov)
Expand Down
14 changes: 12 additions & 2 deletions framework/base/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -431,10 +431,20 @@ public function getValidators()
*/
public function getActiveValidators($attribute = null)
{
$validators = [];
$activeAttributes = $this->activeAttributes();
if ($attribute !== null && !in_array($attribute, $activeAttributes, true)) {
return [];
}
$scenario = $this->getScenario();
$validators = [];
foreach ($this->getValidators() as $validator) {
if ($validator->isActive($scenario) && ($attribute === null || in_array($attribute, $validator->getAttributeNames(), true))) {
if ($attribute === null) {
$validatorAttributes = $validator->getValidationAttributes($activeAttributes);
$attributeValid = !empty($validatorAttributes);
} else {
$attributeValid = in_array($attribute, $validator->getValidationAttributes($attribute), true);
}
if ($attributeValid && $validator->isActive($scenario)) {
$validators[] = $validator;
}
}
Expand Down
35 changes: 22 additions & 13 deletions framework/validators/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -240,24 +240,13 @@ public function init()
/**
* Validates the specified object.
* @param \yii\base\Model $model the data model being validated
* @param array|null $attributes the list of attributes to be validated.
* @param array|string|null $attributes the list of attributes to be validated.
* Note that if an attribute is not associated with the validator - it will be
* ignored. If this parameter is null, every attribute listed in [[attributes]] will be validated.
*/
public function validateAttributes($model, $attributes = null)
{
if (is_array($attributes)) {
$newAttributes = [];
$attributeNames = $this->getAttributeNames();
foreach ($attributes as $attribute) {
if (in_array($attribute, $attributeNames, true)) {
$newAttributes[] = $attribute;
}
}
$attributes = $newAttributes;
} else {
$attributes = $this->getAttributeNames();
}
$attributes = $this->getValidationAttributes($attributes);

foreach ($attributes as $attribute) {
$skip = $this->skipOnError && $model->hasErrors($attribute)
Expand All @@ -270,6 +259,26 @@ public function validateAttributes($model, $attributes = null)
}
}

public function getValidationAttributes($attributes = null)
{
if ($attributes === null) {
return $this->getAttributeNames();
}

if (is_string($attributes)) {
$attributes = [$attributes];
}

$newAttributes = [];
$attributeNames = $this->getAttributeNames();
foreach ($attributes as $attribute) {
if (in_array($attribute, $attributeNames, true)) {
$newAttributes[] = $attribute;
}
}
return $newAttributes;
}

/**
* Validates a single attribute.
* Child classes must implement this method to provide the actual validation logic.
Expand Down
35 changes: 35 additions & 0 deletions tests/framework/base/ModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,18 @@ public function testDefaultScenarios()
$this->assertEquals($scenarios, $model->scenarios());
}

public function testValidatorsWithDifferentScenarios()
{
$model = new CustomScenariosModel();
self::assertCount(3, $model->getActiveValidators());
self::assertCount(2, $model->getActiveValidators('name'));

$model->setScenario('secondScenario');
self::assertCount(2, $model->getActiveValidators());
self::assertCount(2, $model->getActiveValidators('id'));
self::assertCount(0, $model->getActiveValidators('name'), 'This attribute has no validators in current scenario.');
}

public function testIsAttributeRequired()
{
$singer = new Singer();
Expand Down Expand Up @@ -536,3 +548,26 @@ public function setPassword($pw)
$this->passwordHash = $pw;
}
}

class CustomScenariosModel extends Model
{
public $id;
public $name;

public function rules()
{
return [
[['id', 'name'], 'required'],
['id', 'integer'],
['name', 'string'],
];
}

public function scenarios()
{
return [
self::SCENARIO_DEFAULT => ['id', 'name'],
'secondScenario' => ['id'],
];
}
}

0 comments on commit 33fe347

Please sign in to comment.