From 9f657bdb50d8d1e8cc3c0d2afb977ccc72835362 Mon Sep 17 00:00:00 2001 From: Alban Jubert Date: Fri, 10 Aug 2018 16:46:14 +0200 Subject: [PATCH] Fix a regression in Has One saving introduced by #33 fix. --- CHANGELOG.md | 4 ++++ src/SaveRelationsBehavior.php | 41 ++++++++++++++++++++++++++----------- tests/SaveRelationsBehaviorTest.php | 2 +- tests/models/User.php | 3 +++ 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7957a6d..3c6927c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Yii2 Active Record Save Relations Behavior Change Log +## [1.5.2] +### Fixed +- Fix a regression in Has One saving introduced by #33 fix. + ## [1.5.1] ### Fixed - Bug #33: Custom relation scenario was set too late and was preventing attributes from being correctly set (thx @phrakon) diff --git a/src/SaveRelationsBehavior.php b/src/SaveRelationsBehavior.php index 9063e66..75bebd9 100644 --- a/src/SaveRelationsBehavior.php +++ b/src/SaveRelationsBehavior.php @@ -296,16 +296,7 @@ class SaveRelationsBehavior extends Behavior // If relation is has_one, try to set related model attributes foreach ($this->_relations as $relationName) { if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing... - /** @var ActiveQuery $relation */ - $relation = $model->getRelation($relationName); - if ($relation->multiple === false && !empty($model->{$relationName})) { - Yii::debug("Setting foreign keys for {$relationName}", __METHOD__); - foreach ($relation->link as $relatedAttribute => $modelAttribute) { - if ($model->{$modelAttribute} !== $model->{$relationName}->{$relatedAttribute}) { - $model->{$modelAttribute} = $model->{$relationName}->{$relatedAttribute}; - } - } - } + $this->_setRelationForeignKeys($relationName); } } } @@ -384,9 +375,13 @@ class SaveRelationsBehavior extends Behavior */ private function _prepareHasOneRelation(BaseActiveRecord $model, $relationName, ModelEvent $event) { + Yii::debug("_prepareHasOneRelation for {$relationName}", __METHOD__); $relationModel = $model->{$relationName}; $this->validateRelationModel(self::prettyRelationName($relationName), $relationName, $model->{$relationName}); - if ($relationModel->getIsNewRecord()) { + $relation = $model->getRelation($relationName); + $p1 = $model->isPrimaryKey(array_keys($relation->link)); + $p2 = $relationModel::isPrimaryKey(array_values($relation->link)); + if ($relationModel->getIsNewRecord() && $p1 && !$p2) { // Save Has one relation new record if ($event->isValid && (count($model->dirtyAttributes) || $model->{$relationName}->isNewRecord)) { Yii::debug('Saving ' . self::prettyRelationName($relationName) . ' relation model', __METHOD__); @@ -465,6 +460,29 @@ class SaveRelationsBehavior extends Behavior } /** + * Set relation foreign keys that point to owner primary key + * @param $relationName + */ + protected function _setRelationForeignKeys($relationName) + { + /** @var BaseActiveRecord $owner */ + $owner = $this->owner; + /** @var ActiveQuery $relation */ + $relation = $owner->getRelation($relationName); + if ($relation->multiple === false && !empty($owner->{$relationName})) { + Yii::debug("Setting foreign keys for {$relationName}", __METHOD__); + foreach ($relation->link as $relatedAttribute => $modelAttribute) { + if ($owner->{$modelAttribute} !== $owner->{$relationName}->{$relatedAttribute}) { + if ($owner->{$relationName}->isNewRecord) { + $owner->{$relationName}->save(); + } + $owner->{$modelAttribute} = $owner->{$relationName}->{$relatedAttribute}; + } + } + } + } + + /** * Link the related models. * If the models have not been changed, nothing will be done. * Related records will be linked to the owner model using the BaseActiveRecord `link()` method. @@ -642,7 +660,6 @@ class SaveRelationsBehavior extends Behavior { /** @var BaseActiveRecord $owner */ $owner = $this->owner; - if ($this->_oldRelationValue[$relationName] !== $owner->{$relationName}) { if ($owner->{$relationName} instanceof BaseActiveRecord) { $owner->link($relationName, $owner->{$relationName}); diff --git a/tests/SaveRelationsBehaviorTest.php b/tests/SaveRelationsBehaviorTest.php index 42719d3..c2260b6 100644 --- a/tests/SaveRelationsBehaviorTest.php +++ b/tests/SaveRelationsBehaviorTest.php @@ -689,7 +689,7 @@ class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase $profile->loadRelations($data); $this->assertEquals('Someone Else', $profile->user->username, "User name should be 'Someone Else'"); $this->assertTrue($profile->user->isNewRecord, "User should be a new record"); - $profile->save(); + $this->assertEquals(1, $profile->user_id); $this->assertTrue($profile->save(), 'Profile could not be saved'); $this->assertEquals('Someone Else', $profile->user->username, "User name should be 'Someone Else'"); } diff --git a/tests/models/User.php b/tests/models/User.php index e69912b..9372b12 100644 --- a/tests/models/User.php +++ b/tests/models/User.php @@ -3,9 +3,12 @@ namespace tests\models; use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior; +use lhs\Yii2SaveRelationsBehavior\SaveRelationsTrait; class User extends \yii\db\ActiveRecord { + use SaveRelationsTrait; + /** * @inheritdoc */