76 lines
1.8 KiB
PHP
76 lines
1.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\QueryRequestModifiers;
|
|
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Foundation\Http\FormRequest;
|
|
use Illuminate\Support\Facades\Validator;
|
|
|
|
/**
|
|
* @template C of Model
|
|
* @template D of OrderableDTO
|
|
*/
|
|
trait Orderable
|
|
{
|
|
/**
|
|
* @param Builder<C> $query
|
|
* @param ?OrderableDTO<D> $orderDef
|
|
* @return Builder<C>
|
|
*/
|
|
protected function applyOrderable(Builder $query, ?OrderableDTO $orderDef): Builder
|
|
{
|
|
if ($orderDef !== null) {
|
|
$query->orderBy($orderDef->getColumn(), $orderDef->getDirection()->value);
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* @param class-string<D> $className
|
|
* @return D|null
|
|
*/
|
|
protected function makeOrderableFromRequest(FormRequest $request, string $className): ?object
|
|
{
|
|
$keys = $request->all(self::keys());
|
|
|
|
if (!isset($keys['order']) || !isset($keys['direction'])) {
|
|
return null;
|
|
}
|
|
|
|
$validator = Validator::make($keys, $this->validateRules());
|
|
|
|
if ($validator->fails()) {
|
|
// this should never happen... Invalid request
|
|
throw new \InvalidArgumentException($validator->errors()->first());
|
|
}
|
|
|
|
$column = $keys['order'];
|
|
$direction = $keys['direction'];
|
|
|
|
return call_user_func([$className, 'createFromValues'], $column, SortDirection::from($direction));
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
public function validateRules(): array
|
|
{
|
|
return [
|
|
'order' => 'sometimes|string|in:title',
|
|
'direction' => 'sometimes|string|in:asc,desc',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return array<int, string>
|
|
*/
|
|
protected static function keys(): array
|
|
{
|
|
return ['order', 'direction'];
|
|
}
|
|
}
|