mirror of
https://github.com/pacnpal/thrillwiki_laravel.git
synced 2025-12-20 08:11:10 -05:00
106 lines
2.6 KiB
PHP
106 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Traits;
|
|
|
|
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
|
use Illuminate\Support\Str;
|
|
use App\Models\SlugHistory;
|
|
|
|
trait HasSlugHistory
|
|
{
|
|
/**
|
|
* Boot the trait.
|
|
*/
|
|
protected static function bootHasSlugHistory(): void
|
|
{
|
|
static::saving(function ($model) {
|
|
if (!$model->slug) {
|
|
$model->slug = $model->generateSlug();
|
|
}
|
|
});
|
|
|
|
static::updating(function ($model) {
|
|
if ($model->isDirty('slug') && $model->getOriginal('slug')) {
|
|
static::addToSlugHistory($model->getOriginal('slug'));
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get all slug histories for this model.
|
|
*/
|
|
public function slugHistories(): MorphMany
|
|
{
|
|
return $this->morphMany(SlugHistory::class, 'sluggable');
|
|
}
|
|
|
|
/**
|
|
* Add a slug to the history.
|
|
*/
|
|
protected function addToSlugHistory(string $slug): void
|
|
{
|
|
$this->slugHistories()->create(['slug' => $slug]);
|
|
}
|
|
|
|
/**
|
|
* Generate a unique slug.
|
|
*/
|
|
protected function generateSlug(): string
|
|
{
|
|
$slug = Str::slug($this->name);
|
|
$count = 2;
|
|
|
|
while (
|
|
static::where('slug', $slug)
|
|
->where('id', '!=', $this->id)
|
|
->exists() ||
|
|
SlugHistory::where('slug', $slug)
|
|
->where('sluggable_type', get_class($this))
|
|
->where('sluggable_id', '!=', $this->id)
|
|
->exists()
|
|
) {
|
|
$slug = Str::slug($this->name) . '-' . $count++;
|
|
}
|
|
|
|
return $slug;
|
|
}
|
|
|
|
/**
|
|
* Find a model by its current or historical slug.
|
|
*
|
|
* @param string $slug
|
|
* @return static|null
|
|
*/
|
|
public static function findBySlug(string $slug)
|
|
{
|
|
// Try current slug
|
|
$model = static::where('slug', $slug)->first();
|
|
if ($model) {
|
|
return $model;
|
|
}
|
|
|
|
// Try historical slug
|
|
$slugHistory = SlugHistory::where('slug', $slug)
|
|
->where('sluggable_type', static::class)
|
|
->latest()
|
|
->first();
|
|
|
|
if ($slugHistory) {
|
|
return static::find($slugHistory->sluggable_id);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Find a model by its current or historical slug or fail.
|
|
*
|
|
* @param string $slug
|
|
* @return static
|
|
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
|
*/
|
|
public static function findBySlugOrFail(string $slug)
|
|
{
|
|
return static::findBySlug($slug) ?? throw new \Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
}
|
|
} |