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