PIMS/app/Modules/Movies/Services/Browse/Entities/GetGenreWithMoviesService.php

63 lines
2 KiB
PHP

<?php
namespace App\Modules\Movies\Services\Browse\Entities;
use App\Modules\Movies\Models\{Genre, Movie};
use App\Modules\Movies\Services\Contracts\GetGenreWithMoviesServiceInterface;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\ModelNotFoundException;
class GetGenreWithMoviesService implements GetGenreWithMoviesServiceInterface
{
/**
* @param int $id
* @param array{q?: string|null, per_page?: int|null} $params
* @return array{entity: Genre, movies: LengthAwarePaginator}
*/
public function handle(int $id, array $params = []): array
{
$genre = Genre::query()->find($id);
if (!$genre) {
throw (new ModelNotFoundException())->setModel(Genre::class, [$id]);
}
$perPage = max(1, min((int)($params['per_page'] ?? 20), 50));
$q = isset($params['q']) ? trim((string)$params['q']) : '';
$sort = isset($params['sort']) ? trim((string)$params['sort']) : 'title_asc';
$moviesQuery = Movie::query()
->whereHas('genres', fn($q2) => $q2->whereKey($genre->id))
->with(['genres'])
->when($q !== '', fn($query) => $query->where('title', 'like', "%{$q}%"));
switch ($sort) {
case 'title_desc':
$moviesQuery->orderBy('title', 'desc');
break;
case 'newest':
$moviesQuery->orderBy('created_at', 'desc');
break;
case 'oldest':
$moviesQuery->orderBy('created_at', 'asc');
break;
case 'year_asc':
$moviesQuery->orderBy('year', 'asc');
break;
case 'year_desc':
$moviesQuery->orderBy('year', 'desc');
break;
case 'title_asc':
default:
$moviesQuery->orderBy('title', 'asc');
break;
}
$movies = $moviesQuery->paginate($perPage);
return [
'entity' => $genre,
'movies' => $movies,
];
}
}