From d0ce165ba61720b297a3acc09386eeeece4f3fd8 Mon Sep 17 00:00:00 2001 From: Nikolay Oleynikov Date: Thu, 20 Apr 2017 21:30:04 +0300 Subject: [PATCH] Fixes #13728: Fixed the bug when `yii\behaviors\SluggableBehavior` wasn't preserving immutable slug values --- framework/CHANGELOG.md | 1 + framework/behaviors/SluggableBehavior.php | 22 ++++++++----- .../framework/behaviors/SluggableBehaviorTest.php | 38 ++++++++++++++++++++++ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 2830882..feb0cce 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -46,6 +46,7 @@ Yii Framework 2 Change Log - Bug #13670: Fixed alias option from console when it includes `-` or `_` in option name (pana1990) - Enh: Added `yii\di\Instance::__set_state()` method to restore object after serialization using `var_export()` function (silvefire) - Enh #13695: `\yii\web\Response::setStatusCode()` method now returns the Response object itself (kyle-mccarthy) +- Bug #13728: Fixed the bug when `yii\behaviors\SluggableBehavior` wasn't preserving immutable slug values (Kolyunya) - Bug #13707: Fixed `\yii\web\ErrorHandler` and `\yii\web\ErrorAction` not setting correct response code to response object before rendering error view (samdark) - Enh #13698: `yii\grid\DataColumn` filter is automatically generated as dropdown list in case of `format` set to `boolean` (bizley) - Enh #13254: Core validators no longer require Yii::$app to be set (sammousa) diff --git a/framework/behaviors/SluggableBehavior.php b/framework/behaviors/SluggableBehavior.php index 350be44..d1c2e04 100644 --- a/framework/behaviors/SluggableBehavior.php +++ b/framework/behaviors/SluggableBehavior.php @@ -138,17 +138,17 @@ class SluggableBehavior extends AttributeBehavior */ protected function getValue($event) { - if ($this->attribute !== null) { - if ($this->isNewSlugNeeded()) { - $slugParts = []; - foreach ((array) $this->attribute as $attribute) { - $slugParts[] = ArrayHelper::getValue($this->owner, $attribute); - } + if (!$this->isNewSlugNeeded()) { + return $this->owner->{$this->slugAttribute}; + } - $slug = $this->generateSlug($slugParts); - } else { - return $this->owner->{$this->slugAttribute}; + if ($this->attribute !== null) { + $slugParts = []; + foreach ((array) $this->attribute as $attribute) { + $slugParts[] = ArrayHelper::getValue($this->owner, $attribute); } + + $slug = $this->generateSlug($slugParts); } else { $slug = parent::getValue($event); } @@ -173,6 +173,10 @@ class SluggableBehavior extends AttributeBehavior return false; } + if ($this->attribute === null) { + return true; + } + foreach ((array)$this->attribute as $attribute) { if ($this->owner->isAttributeChanged($attribute)) { return true; diff --git a/tests/framework/behaviors/SluggableBehaviorTest.php b/tests/framework/behaviors/SluggableBehaviorTest.php index 571e67c..b119e37 100644 --- a/tests/framework/behaviors/SluggableBehaviorTest.php +++ b/tests/framework/behaviors/SluggableBehaviorTest.php @@ -168,6 +168,44 @@ class SluggableBehaviorTest extends TestCase $model->save(); $this->assertEquals('test-name', $model->slug); } + + /** + * @depends testSlug + */ + public function testImmutableByAttribute() + { + $model = new ActiveRecordSluggable(); + $model->getSluggable()->immutable = true; + + $model->name = 'test name'; + $model->validate(); + $this->assertEquals('test-name', $model->slug); + + $model->name = 'another name'; + $model->validate(); + $this->assertEquals('test-name', $model->slug); + } + + /** + * @depends testSlug + */ + public function testImmutableByCallback() + { + $model = new ActiveRecordSluggable(); + $model->getSluggable()->immutable = true; + $model->getSluggable()->attribute = null; + $model->getSluggable()->value = function () use ($model) { + return $model->name; + }; + + $model->name = 'test name'; + $model->validate(); + $this->assertEquals('test name', $model->slug); + + $model->name = 'another name'; + $model->validate(); + $this->assertEquals('test name', $model->slug); + } } /**