diff --git a/src/SaveRelationsBehavior.php b/src/SaveRelationsBehavior.php index 4377be3..7eb0286 100644 --- a/src/SaveRelationsBehavior.php +++ b/src/SaveRelationsBehavior.php @@ -7,6 +7,7 @@ use Yii; use yii\base\Behavior; use yii\base\Component; use yii\base\Exception; +use yii\base\InvalidArgumentException; use yii\base\ModelEvent; use yii\base\UnknownPropertyException; use yii\db\ActiveQuery; @@ -63,8 +64,6 @@ class SaveRelationsBehavior extends Behavior } } - //private $_relationsCascadeDelete = []; //TODO - /** * @inheritdoc */ @@ -169,7 +168,7 @@ class SaveRelationsBehavior extends Behavior $newRelations[] = $entry; } else { // TODO handle this with one DB request to retrieve all models - $newRelations[] = $this->processModelAsArray($entry, $relation); + $newRelations[] = $this->processModelAsArray($entry, $relation, $name); } } $this->_newRelationValue[$name] = $newRelations; @@ -183,12 +182,12 @@ class SaveRelationsBehavior extends Behavior * @param \yii\db\ActiveQuery $relation * @return BaseActiveRecord */ - protected function processModelAsArray($data, $relation) + protected function processModelAsArray($data, $relation, $name) { /** @var BaseActiveRecord $modelClass */ $modelClass = $relation->modelClass; $fks = $this->_getRelatedFks($data, $relation, $modelClass); - return $this->_loadOrCreateRelationModel($data, $fks, $modelClass); + return $this->_loadOrCreateRelationModel($data, $fks, $modelClass, $name); } /** @@ -238,9 +237,10 @@ class SaveRelationsBehavior extends Behavior * @param $data * @param $fks * @param $modelClass + * @param $relationName * @return BaseActiveRecord */ - private function _loadOrCreateRelationModel($data, $fks, $modelClass) + private function _loadOrCreateRelationModel($data, $fks, $modelClass, $relationName) { /** @var BaseActiveRecord $relationModel */ @@ -250,6 +250,9 @@ class SaveRelationsBehavior extends Behavior } if (!($relationModel instanceof BaseActiveRecord) && !empty($data)) { $relationModel = new $modelClass; + if (array_key_exists($relationName, $this->_relationsScenario)) { + $relationModel->setScenario($this->_relationsScenario[$relationName]); + } } if (($relationModel instanceof BaseActiveRecord) && is_array($data)) { $relationModel->setAttributes($data); @@ -270,7 +273,7 @@ class SaveRelationsBehavior extends Behavior /** @var ActiveQuery $relation */ $relation = $owner->getRelation($name); if (!($value instanceof $relation->modelClass)) { - $value = $this->processModelAsArray($value, $relation); + $value = $this->processModelAsArray($value, $relation, $name); } $this->_newRelationValue[$name] = $value; $owner->populateRelation($name, $value); @@ -402,9 +405,6 @@ class SaveRelationsBehavior extends Behavior /** @var BaseActiveRecord $model */ $model = $this->owner; if (!is_null($relationModel) && ($relationModel->isNewRecord || count($relationModel->getDirtyAttributes()))) { - if (array_key_exists($relationName, $this->_relationsScenario)) { - $relationModel->setScenario($this->_relationsScenario[$relationName]); - } Yii::debug("Validating {$prettyRelationName} relation model using " . $relationModel->scenario . ' scenario', __METHOD__); if (!$relationModel->validate()) { $this->_addError($relationModel, $model, $relationName, $prettyRelationName); @@ -718,4 +718,23 @@ class SaveRelationsBehavior extends Behavior } } } + + /** + * Set the scenario for a given relation + * @param $relationName + * @param $scenario + * @throws InvalidArgumentException + */ + public function setRelationScenario($relationName, $scenario) + { + /** @var BaseActiveRecord $owner */ + $owner = $this->owner; + $relation = $owner->getRelation($relationName, false); + if (in_array($relationName, $this->_relations) && !is_null($relation)) { + $this->_relationsScenario[$relationName] = $scenario; + } else { + throw new InvalidArgumentException('Unknown ' . $relationName . ' relation'); + } + + } } diff --git a/tests/SaveRelationsBehaviorTest.php b/tests/SaveRelationsBehaviorTest.php index 7b886c5..42719d3 100644 --- a/tests/SaveRelationsBehaviorTest.php +++ b/tests/SaveRelationsBehaviorTest.php @@ -650,6 +650,14 @@ class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase $this->assertTrue($project->save(), 'Project could not be saved'); } + public function testFailToSetScenarioForUnkownRelation() + { + $this->setExpectedException('\yii\base\InvalidArgumentException'); + $user = new User(); + $user->setRelationScenario('wrongNameRelation', 'insert'); + } + + public function testSaveHasOneWithPrimaryKeyAsForeignKey() { $user = new User(); @@ -657,11 +665,14 @@ class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase $user->company = [ 'name' => 'ACME' ]; + $user->setRelationScenario('userProfile', 'insert'); $user->userProfile = [ - 'bio' => "Some great bio" + 'bio' => "Some great bio", + 'agree' => 1 ]; - $this->assertTrue($user->save(), 'User could not be saved'); - $this->assertEquals($user->userProfile->bio, "Some great bio"); + $this->assertEquals(1, $user->userProfile->agree, 'User could not be saved' . VarDumper::dumpAsString($user->errors)); + $this->assertTrue($user->save(), 'User could not be saved' . VarDumper::dumpAsString($user->errors)); + $this->assertEquals("Some great bio", $user->userProfile->bio); $this->assertEquals($user->id, $user->userProfile->user_id); } diff --git a/tests/models/UserProfile.php b/tests/models/UserProfile.php index ec08463..d817149 100644 --- a/tests/models/UserProfile.php +++ b/tests/models/UserProfile.php @@ -7,6 +7,8 @@ use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior; class UserProfile extends \yii\db\ActiveRecord { + public $agree; + /** * @inheritdoc */ @@ -37,7 +39,8 @@ class UserProfile extends \yii\db\ActiveRecord [['user_id'], 'integer'], ['bio', 'required'], [['user_id'], 'unique'], - [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']] + [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']], + [['agree'], 'required', 'on' => 'insert'], ]; }