Merge branch 'mdmunir-8139-unsafe-validator'

This commit is contained in:
SilverFire - Dmitry Naumenko
2016-03-22 23:33:17 +02:00
4 changed files with 81 additions and 11 deletions

View File

@@ -392,6 +392,19 @@ have to do it explicitly as follows,
$model->secret = $secret; $model->secret = $secret;
``` ```
The same can be done in `rules()` method:
```php
public function rules()
{
return [
[['username', 'password', '!secret'], 'required', 'on' => 'login']
];
}
```
In this case attributes `username` and `password` are required, but `secret` must be assigned explicitly.
## Data Exporting <span id="data-exporting"></span> ## Data Exporting <span id="data-exporting"></span>

View File

@@ -754,7 +754,7 @@ class Model extends Component implements IteratorAggregate, ArrayAccess, Arrayab
} }
$attributes = []; $attributes = [];
foreach ($scenarios[$scenario] as $attribute) { foreach ($scenarios[$scenario] as $attribute) {
if ($attribute[0] !== '!') { if ($attribute[0] !== '!' && !in_array('!' . $attribute, $scenarios[$scenario])) {
$attributes[] = $attribute; $attributes[] = $attribute;
} }
} }

View File

@@ -224,17 +224,26 @@ class Validator extends Component
* Validates the specified object. * Validates the specified object.
* @param \yii\base\Model $model the data model being validated * @param \yii\base\Model $model the data model being validated
* @param array|null $attributes the list of attributes to be validated. * @param array|null $attributes the list of attributes to be validated.
* Note that if an attribute is not associated with the validator, * Note that if an attribute is not associated with the validator, or is is prefixed with `!` char - it will be
* it will be ignored. * ignored. If this parameter is null, every attribute listed in [[attributes]] will be validated.
* If this parameter is null, every attribute listed in [[attributes]] will be validated.
*/ */
public function validateAttributes($model, $attributes = null) public function validateAttributes($model, $attributes = null)
{ {
if (is_array($attributes)) { if (is_array($attributes)) {
$attributes = array_intersect($this->attributes, $attributes); $newAttributes = [];
foreach ($attributes as $attribute) {
if (in_array($attribute, $this->attributes) || in_array('!' . $attribute, $this->attributes)) {
$newAttributes[] = $attribute;
}
}
$attributes = $newAttributes;
} else { } else {
$attributes = $this->attributes; $attributes = [];
foreach ($this->attributes as $attribute) {
$attributes[] = $attribute[0] === '!' ? substr($attribute, 1) : $attribute;
}
} }
foreach ($attributes as $attribute) { foreach ($attributes as $attribute) {
$skip = $this->skipOnError && $model->hasErrors($attribute) $skip = $this->skipOnError && $model->hasErrors($attribute)
|| $this->skipOnEmpty && $this->isEmpty($model->$attribute); || $this->skipOnEmpty && $this->isEmpty($model->$attribute);

View File

@@ -3,11 +3,11 @@
namespace yiiunit\framework\base; namespace yiiunit\framework\base;
use yii\base\Model; use yii\base\Model;
use yiiunit\data\base\RulesModel;
use yiiunit\TestCase;
use yiiunit\data\base\Speaker;
use yiiunit\data\base\Singer;
use yiiunit\data\base\InvalidRulesModel; use yiiunit\data\base\InvalidRulesModel;
use yiiunit\data\base\RulesModel;
use yiiunit\data\base\Singer;
use yiiunit\data\base\Speaker;
use yiiunit\TestCase;
/** /**
* @group base * @group base
@@ -177,6 +177,53 @@ class ModelTest extends TestCase
$this->assertEquals(['account_id', 'user_id', 'email', 'name'], $model->activeAttributes()); $this->assertEquals(['account_id', 'user_id', 'email', 'name'], $model->activeAttributes());
} }
public function testUnsafeAttributes()
{
$model = new RulesModel();
$model->rules = [
[['name', '!email'], 'required'], // Name is safe to set, but email is not. Both are required
];
$this->assertEquals(['name'], $model->safeAttributes());
$this->assertEquals(['name', 'email'], $model->activeAttributes());
$model->attributes = ['name' => 'mdmunir', 'email' => 'mdm@mun.com'];
$this->assertNull($model->email);
$this->assertFalse($model->validate());
$model = new RulesModel();
$model->rules = [
[['name'], 'required'],
[['!user_id'], 'default', 'value' => '3426'],
];
$model->attributes = ['name' => 'mdmunir', 'user_id' => '62792684'];
$this->assertTrue($model->validate());
$this->assertEquals('3426', $model->user_id);
$model = new RulesModel();
$model->rules = [
[['name', 'email'], 'required'],
[['!email'], 'safe']
];
$this->assertEquals(['name'], $model->safeAttributes());
$model->attributes = ['name' => 'mdmunir', 'email' => 'm2792684@mdm.com'];
$this->assertFalse($model->validate());
$model = new RulesModel();
$model->rules = [
[['name', 'email'], 'required'],
[['email'], 'email'],
[['!email'], 'safe', 'on' => 'update']
];
$model->setScenario(RulesModel::SCENARIO_DEFAULT);
$this->assertEquals(['name', 'email'], $model->safeAttributes());
$model->attributes = ['name' => 'mdmunir', 'email' => 'm2792684@mdm.com'];
$this->assertTrue($model->validate());
$model->setScenario('update');
$this->assertEquals(['name'], $model->safeAttributes());
$model->attributes = ['name' => 'D426', 'email' => 'd426@mdm.com'];
$this->assertNotEquals('d426@mdm.com', $model->email);
}
public function testErrors() public function testErrors()
{ {
$speaker = new Speaker(); $speaker = new Speaker();
@@ -344,7 +391,8 @@ class ModelTest extends TestCase
public function testCreateValidators() public function testCreateValidators()
{ {
$this->setExpectedException('yii\base\InvalidConfigException', 'Invalid validation rule: a rule must specify both attribute names and validator type.'); $this->setExpectedException('yii\base\InvalidConfigException',
'Invalid validation rule: a rule must specify both attribute names and validator type.');
$invalid = new InvalidRulesModel(); $invalid = new InvalidRulesModel();
$invalid->createValidators(); $invalid->createValidators();