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
						
					
					
				
			
		
		
	
	
							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(); | 
						|
	} | 
						|
} |