Commit d362af6e by Klimov Paul

`yii\behaviors\Sluggable` optimized

parent b062a660
...@@ -48,6 +48,7 @@ use yii\helpers\Inflector; ...@@ -48,6 +48,7 @@ use yii\helpers\Inflector;
* ]; * ];
* } * }
* ``` * ```
*
* @author Alexander Kochetov <creocoder@gmail.com> * @author Alexander Kochetov <creocoder@gmail.com>
* @author Paul Klimov <klimov.paul@gmail.com> * @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0 * @since 2.0
...@@ -63,7 +64,7 @@ class SluggableBehavior extends AttributeBehavior ...@@ -63,7 +64,7 @@ class SluggableBehavior extends AttributeBehavior
*/ */
public $attribute; public $attribute;
/** /**
* @var mixed the value that will be used as a slug. This can be an anonymous function * @var string|callable the value that will be used as a slug. This can be an anonymous function
* or an arbitrary value. If the former, the return value of the function will be used as a slug. * or an arbitrary value. If the former, the return value of the function will be used as a slug.
* The signature of the function should be as follows, * The signature of the function should be as follows,
* *
...@@ -80,7 +81,7 @@ class SluggableBehavior extends AttributeBehavior ...@@ -80,7 +81,7 @@ class SluggableBehavior extends AttributeBehavior
* If enabled behavior will validate slug uniqueness automatically. If validation fails it will attempt * If enabled behavior will validate slug uniqueness automatically. If validation fails it will attempt
* generating unique slug value from based one until success. * generating unique slug value from based one until success.
*/ */
public $unique = false; public $ensureUnique = false;
/** /**
* @var array configuration for slug uniqueness validator. This configuration should not contain validator name * @var array configuration for slug uniqueness validator. This configuration should not contain validator name
* and validated attributes - only options in format 'name => value' are allowed. * and validated attributes - only options in format 'name => value' are allowed.
...@@ -118,12 +119,8 @@ class SluggableBehavior extends AttributeBehavior ...@@ -118,12 +119,8 @@ class SluggableBehavior extends AttributeBehavior
parent::init(); parent::init();
if (empty($this->attributes)) { if (empty($this->attributes)) {
if ($this->unique) {
$this->attributes = [BaseActiveRecord::EVENT_BEFORE_INSERT => $this->slugAttribute];
} else {
$this->attributes = [BaseActiveRecord::EVENT_BEFORE_VALIDATE => $this->slugAttribute]; $this->attributes = [BaseActiveRecord::EVENT_BEFORE_VALIDATE => $this->slugAttribute];
} }
}
if ($this->attribute === null && $this->value === null) { if ($this->attribute === null && $this->value === null) {
throw new InvalidConfigException('Either "attribute" or "value" property must be specified.'); throw new InvalidConfigException('Either "attribute" or "value" property must be specified.');
...@@ -135,23 +132,43 @@ class SluggableBehavior extends AttributeBehavior ...@@ -135,23 +132,43 @@ class SluggableBehavior extends AttributeBehavior
*/ */
protected function getValue($event) protected function getValue($event)
{ {
$isNewSlug = true;
if ($this->attribute !== null) { if ($this->attribute !== null) {
if (is_array($this->attribute)) { if (is_array($this->attribute)) {
$attributes = $this->attribute;
} else {
$attributes = [$this->attribute];
}
/* @var $owner BaseActiveRecord */
$owner = $this->owner;
if (!$owner->getIsNewRecord() && !empty($owner->{$this->slugAttribute})) {
$isNewSlug = false;
foreach ($attributes as $attribute) {
if ($owner->isAttributeChanged($attribute)) {
$isNewSlug = true;
break;
}
}
}
if ($isNewSlug) {
$slugParts = []; $slugParts = [];
foreach ($this->attribute as $attribute) { foreach ($attributes as $attribute) {
$slugParts[] = $this->owner->{$attribute}; $slugParts[] = $owner->{$attribute};
} }
$this->value = Inflector::slug(implode('-', $slugParts)); $slug = Inflector::slug(implode('-', $slugParts));
} else { } else {
$this->value = Inflector::slug($this->owner->{$this->attribute}); $slug = $owner->{$this->slugAttribute};
}
} }
} else {
$slug = parent::getValue($event); $slug = parent::getValue($event);
}
if ($this->unique) { if ($this->ensureUnique && $isNewSlug) {
$baseSlug = $slug; $baseSlug = $slug;
$iteration = 0; $iteration = 0;
while (!$this->validateSlugUnique($slug)) { while (!$this->validateSlug($slug)) {
$iteration++; $iteration++;
$slug = $this->generateUniqueSlug($baseSlug, $iteration); $slug = $this->generateUniqueSlug($baseSlug, $iteration);
} }
...@@ -164,7 +181,7 @@ class SluggableBehavior extends AttributeBehavior ...@@ -164,7 +181,7 @@ class SluggableBehavior extends AttributeBehavior
* @param string $slug slug value * @param string $slug slug value
* @return boolean whether slug is unique. * @return boolean whether slug is unique.
*/ */
private function validateSlugUnique($slug) private function validateSlug($slug)
{ {
$validator = array_merge( $validator = array_merge(
[ [
......
...@@ -218,7 +218,7 @@ class ActiveRecordSluggableUnique extends ActiveRecordSluggable ...@@ -218,7 +218,7 @@ class ActiveRecordSluggableUnique extends ActiveRecordSluggable
'sluggable' => [ 'sluggable' => [
'class' => SluggableBehavior::className(), 'class' => SluggableBehavior::className(),
'attribute' => 'name', 'attribute' => 'name',
'unique' => true, 'ensureUnique' => true,
], ],
]; ];
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment