78 lines
2 KiB
PHP
78 lines
2 KiB
PHP
<?php
|
|
|
|
namespace App\Traits\Models;
|
|
|
|
use App\Interfaces\OrderableInterface;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
trait Orderable
|
|
{
|
|
/**
|
|
* @property int $priority_order
|
|
*/
|
|
|
|
/**
|
|
* Returns the grouping field used for ordering.
|
|
* Returns null if the order is global
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function getOrderGroupField(): ?string
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns the priority order value of the model.
|
|
*
|
|
* @return integer
|
|
*/
|
|
public function getPriorityOrder(): int
|
|
{
|
|
return $this->priority_order ?? 0;
|
|
}
|
|
|
|
/**
|
|
* shifts down by 1 all elements positioned after the delete.
|
|
*
|
|
* @param Model&OrderableInterface $model
|
|
* @return void
|
|
*/
|
|
public static function setOrder(OrderableInterface $model): void
|
|
{
|
|
$groupField = $model->getOrderGroupField();
|
|
$query = $model::query()->where('priority_order', '>', $model->getPriorityOrder());
|
|
|
|
if ($groupField) {
|
|
$query->where($groupField, $model->{$groupField});
|
|
}
|
|
|
|
$query->each(function (Model $item): void {
|
|
/** @var Model&OrderableInterface $item */
|
|
$item->setAttribute('priority_order', $item->getPriorityOrder() - 1);
|
|
$item->saveOrFail();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Assigns the next order value on creation.
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function bootOrderable(): void
|
|
{
|
|
static::creating(function (Model $model): void {
|
|
/** @var Model&OrderableInterface $model */
|
|
if (!$model->getPriorityOrder()) {
|
|
$groupField = $model->getOrderGroupField();
|
|
$query = static::query();
|
|
|
|
if ($groupField) {
|
|
$query->where($groupField, $model->{$groupField});
|
|
}
|
|
|
|
$model->setAttribute('priority_order', ($query->max('priority_order') ?? 0) + 1);
|
|
}
|
|
});
|
|
}
|
|
}
|