You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

137 lines
2.5 KiB

<?php
/**
* Created by Error202
* Date: 28.08.2018
*/
namespace core\behaviors;
use yii\base\Behavior;
use yii\db\ActiveRecord;
use yii\validators\UniqueValidator;
use yii\helpers\Inflector;
use Yii;
class SluggableRelationBehavior extends Behavior
{
/**
* Source attribute for generate slug
* @var string
*/
public $attribute;
/**
* Field name for slug
* @var string
*/
public $slugAttribute = 'slug';
/**
* Relation name, if attribute from relative table
* @var string
*/
public $relation;
/**
* Generate slug if slugAttribute is empty
* @var bool
*/
public $slugIfEmpty = true;
public function events()
{
return [
ActiveRecord::EVENT_AFTER_UPDATE => 'afterUpdate',
ActiveRecord::EVENT_AFTER_INSERT => 'afterInsert',
];
}
public function afterInsert()
{
$this->addSlug();
}
public function afterUpdate()
{
if (!$this->owner->{$this->slugAttribute}) {
$this->addSlug();
}
}
private function addSlug()
{
/** @var ActiveRecord $owner */
$owner = $this->owner;
if (!$this->isNewSlugNeeded()) {
$slug = $owner->{$this->slugAttribute};
}
else {
if ($this->relation) {
$attribute = $owner->{$this->relation}->{$this->attribute};
$slug = $this->generateSlug($attribute);
$slug = $this->makeUnique($slug);
}
else {
$attribute = $owner->{$this->attribute};
$slug = $this->generateSlug($attribute);
$slug = $this->makeUnique($slug);
}
}
$owner->{$this->slugAttribute} = $slug;
$owner->save();
}
protected function generateSlug($attribute)
{
return Inflector::slug($attribute);
}
protected function isNewSlugNeeded()
{
if (empty($this->owner->{$this->slugAttribute})) {
return true;
}
if (!empty($this->owner->{$this->slugAttribute}) && !$this->slugIfEmpty) {
return true;
}
return false;
}
protected function makeUnique($slug)
{
$uniqueSlug = $slug;
$iteration = 0;
while (!$this->validateSlug($uniqueSlug)) {
$iteration++;
$uniqueSlug = $this->generateUniqueSlug($slug, $iteration);
}
return $uniqueSlug;
}
protected function generateUniqueSlug($baseSlug, $iteration)
{
return $baseSlug . '-' . ($iteration + 1);
}
protected function validateSlug($slug)
{
/* @var $validator UniqueValidator */
/* @var $model ActiveRecord */
$validator = Yii::createObject(array_merge(
[
'class' => UniqueValidator::class,
]
));
$model = clone $this->owner;
$model->clearErrors();
$model->{$this->slugAttribute} = $slug;
$validator->validateAttribute($model, $this->slugAttribute);
return !$model->hasErrors();
}
}