ldc-le-gaulois-pro/app/Traits/Models/Orderable.php
2026-05-11 14:21:12 +02:00

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