parfum/app/Traits/Utilities/WithSortOrder.php

80 lines
2.3 KiB
PHP

<?php
namespace App\Traits\Utilities;
trait WithSortOrder
{
/**
* Get the model class for this sortable entity
*/
abstract protected function getModelClass(): string;
/**
* Get the current model instance
*/
abstract protected function getModelInstance();
/**
* Adjust sort order after deletion
*/
protected function adjustSortOrderAfterDelete($deletedModel): void
{
$modelClass = $this->getModelClass();
$modelClass::where('sort_order', '>', $deletedModel->sort_order)
->orderBy('sort_order')
->get()
->each(function ($item) {
$item->update(['sort_order' => $item->sort_order - 1]);
});
}
/**
* Handle sort order changes (up, down, first, last)
*/
public function sortOrder(string $direction): void
{
$modelClass = $this->getModelClass();
$model = $this->getModelInstance();
if (in_array($direction, ['up', 'down'])) {
$swap = null;
if ($direction === 'up') {
$swap = $modelClass::where('sort_order', '<', $model->sort_order)
->orderByDesc('sort_order')
->first();
} else {
$swap = $modelClass::where('sort_order', '>', $model->sort_order)
->orderBy('sort_order')
->first();
}
if ($swap) {
$temp = $model->sort_order;
$model->update(['sort_order' => $swap->sort_order]);
$swap->update(['sort_order' => $temp]);
}
} elseif ($direction === 'first') {
$model->update(['sort_order' => $modelClass::min('sort_order') - 1]);
$this->normalizeSortOrder();
} elseif ($direction === 'last') {
$model->update(['sort_order' => $modelClass::max('sort_order') + 1]);
$this->normalizeSortOrder();
}
}
/**
* Normalize sort order to ensure consecutive numbering
*/
protected function normalizeSortOrder(): void
{
$modelClass = $this->getModelClass();
$items = $modelClass::orderBy('sort_order')->get();
foreach ($items as $index => $item) {
$item->update(['sort_order' => $index + 1]);
}
}
}