From a34b436548e30538275d4502fe177d6b22fe2805 Mon Sep 17 00:00:00 2001 From: Alban Jubert Date: Thu, 2 Nov 2017 13:54:10 +0100 Subject: [PATCH] Fix for issue #22: when a has one relation is involved and the related models are linked using there primary key, the owner attribute should not be updated in order to pass the validation Added test cases for #22 issue --- src/SaveRelationsBehavior.php | 2 +- tests/SaveRelationsBehaviorTest.php | 39 +++++++++++++++++++++------ tests/models/BadConfigurationModel.php | 48 ++++++++++++++++++++++++++++++++++ tests/models/User.php | 23 ++++++++++++++++ tests/models/UserProfile.php | 25 ++++++++++++++++++ 5 files changed, 128 insertions(+), 9 deletions(-) create mode 100644 tests/models/BadConfigurationModel.php create mode 100644 tests/models/UserProfile.php diff --git a/src/SaveRelationsBehavior.php b/src/SaveRelationsBehavior.php index d04cf1f..903db16 100644 --- a/src/SaveRelationsBehavior.php +++ b/src/SaveRelationsBehavior.php @@ -238,7 +238,7 @@ class SaveRelationsBehavior extends Behavior if ($relation->multiple === false && !empty($model->{$relationName})) { Yii::trace("Setting foreign keys for {$relationName}", __METHOD__); foreach ($relation->link as $relatedAttribute => $modelAttribute) { - if ($model->{$modelAttribute} !== $model->{$relationName}->{$relatedAttribute}) { + if ($model->{$modelAttribute} !== $model->{$relationName}->{$relatedAttribute} && !in_array($modelAttribute, $model->primaryKey())) { $model->{$modelAttribute} = $model->{$relationName}->{$relatedAttribute}; } } diff --git a/tests/SaveRelationsBehaviorTest.php b/tests/SaveRelationsBehaviorTest.php index ee86de2..e890a23 100644 --- a/tests/SaveRelationsBehaviorTest.php +++ b/tests/SaveRelationsBehaviorTest.php @@ -4,7 +4,6 @@ namespace tests; use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior; -use RuntimeException; use tests\models\Company; use tests\models\DummyModel; use tests\models\DummyModelParent; @@ -32,6 +31,7 @@ class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase $db->createCommand()->dropTable('project_user')->execute(); $db->createCommand()->dropTable('project')->execute(); $db->createCommand()->dropTable('user')->execute(); + $db->createCommand()->dropTable('user_profile')->execute(); $db->createCommand()->dropTable('company')->execute(); $db->createCommand()->dropTable('link_type')->execute(); $db->createCommand()->dropTable('link')->execute(); @@ -62,6 +62,12 @@ class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase 'username' => $migration->string()->notNull()->unique() ])->execute(); + // User profile + $db->createCommand()->createTable('user_profile', [ + 'user_id' => $migration->primaryKey(), + 'bio' => $migration->text(), + ])->execute(); + // Project $db->createCommand()->createTable('project', [ 'id' => $migration->primaryKey(), @@ -148,20 +154,25 @@ class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase ])->execute(); } - /** - * @expectedException RuntimeException - */ public function testCannotAttachBehaviorToAnythingButActiveRecord() { + $this->setExpectedException('RuntimeException'); $model = new Model(); $model->attachBehavior('saveRelated', SaveRelationsBehavior::className()); } - /** - * @expectedException \yii\base\InvalidCallException - */ + public function testUnsupportedRelationProperty() + { + $this->setExpectedException('\yii\base\UnknownPropertyException'); + $model = new Project(); + $model->detachBehaviors(); + $model->attachBehavior('saveRelated', new SaveRelationsBehavior(['relations' => ['links' => ['fakeParam' => 'Some value']]])); + } + + public function testTryToSetUndeclaredRelationShouldFail() { + $this->setExpectedException('\yii\base\InvalidCallException'); $project = new Project(); $project->projectUsers = []; } @@ -582,7 +593,7 @@ class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase $project->loadRelations($data); $this->assertFalse($project->save(), 'Project could be saved'); $data = [ - 'Link' => [ + 'Link' => [ [ 'language' => 'en', 'name' => 'yii', @@ -594,4 +605,16 @@ class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase $this->assertTrue($project->save(), 'Project could not be saved'); } + public function testSaveHasOneWithPrimaryKeyAsForeignKey() + { + $user = new User(); + $user->username = 'Dummy More'; + $user->userProfile = [ + 'bio' => "Some great bio" + ]; + $this->assertTrue($user->save(), 'User could not be saved'); + $this->assertEquals($user->userProfile->bio, "Some great bio"); + $this->assertEquals($user->id, $user->userProfile->user_id); + } + } diff --git a/tests/models/BadConfigurationModel.php b/tests/models/BadConfigurationModel.php new file mode 100644 index 0000000..127b11b --- /dev/null +++ b/tests/models/BadConfigurationModel.php @@ -0,0 +1,48 @@ + [ + 'class' => SaveRelationsBehavior::className(), + 'relations' => ['children'] + ], + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getChildren() + { + return $this->hasOne(DummyModel::className(), ['id' => 'parent_id']); + } + +} \ No newline at end of file diff --git a/tests/models/User.php b/tests/models/User.php index fdff1a6..0f7c176 100644 --- a/tests/models/User.php +++ b/tests/models/User.php @@ -2,6 +2,8 @@ namespace tests\models; +use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior; + class User extends \yii\db\ActiveRecord { /** @@ -15,6 +17,19 @@ class User extends \yii\db\ActiveRecord /** * @inheritdoc */ + public function behaviors() + { + return [ + 'saveRelations' => [ + 'class' => SaveRelationsBehavior::className(), + 'relations' => ['userProfile'] + ], + ]; + } + + /** + * @inheritdoc + */ public function rules() { return [ @@ -23,4 +38,12 @@ class User extends \yii\db\ActiveRecord ]; } + /** + * @return \yii\db\ActiveQuery + */ + public function getUserProfile() + { + return $this->hasOne(UserProfile::className(), ['user_id' => 'id']); + } + } diff --git a/tests/models/UserProfile.php b/tests/models/UserProfile.php new file mode 100644 index 0000000..5d9c6d6 --- /dev/null +++ b/tests/models/UserProfile.php @@ -0,0 +1,25 @@ +