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

55 lines
2 KiB
PHP

<?php
namespace App\Traits\Controllers;
use App\Http\Requests\Bo\UpdateOrderRequest;
use App\Interfaces\OrderableInterface;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
trait ManagesOrder
{
/**
* Updates the order of a model and reorders all impacted elements.
*
* Shifts by +1 or -1 all elements located between the old
* and new position of the model, then assigns the new position
* to the target model. The whole operation runs inside a
* database transaction to ensure data consistency.
*
* @param UpdateOrderRequest $request The validated request containing the 'priority' field.
* @param Model&OrderableInterface $model The model to reorder (must use the Orderable trait).
* @return RedirectResponse
*
* @throws \Throwable Returns if save fail.
*/
public function changeOrderPriority(UpdateOrderRequest $request, Model&OrderableInterface $model): RedirectResponse
{
$newPriority = (int) $request->validated('priority_order');
return DB::transaction(function () use ($model, $newPriority): RedirectResponse {
$query = $model::query()
->whereKeyNot($model)
->whereBetween('priority_order', [
min($model->getPriorityOrder(), $newPriority),
max($model->getPriorityOrder(), $newPriority),
]);
$groupField = $model->getOrderGroupField();
if ($groupField) {
$query->where($groupField, $model->{$groupField});
}
$model->getPriorityOrder() < $newPriority
? $query->decrement('priority_order', 1)
: $query->increment('priority_order', 1);
$model->setAttribute('priority_order', $newPriority);
$model->saveOrFail();
return redirect()->back()->with('success', trans('crud.messages.order_changed'));
});
}
}