jikan-rest/app/Services/DefaultQueryBuilderService.php
pushrbx 1d3aa7b794 various hot fixes and improvements
- improved searching with low letter count
- removed the ability to order anime by type and rating
- fixed schedules endpoint's filter parameter yet again
- improved configuration
- fixed filtering anime by producers
- fixed filtering manga by magazines
- fixed search analytics in case of short search terms
2023-07-15 14:44:42 +01:00

80 lines
2.8 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
final class DefaultQueryBuilderService implements QueryBuilderService
{
/**
* @throws \Exception
*/
public function __construct(
private readonly SearchService $searchService,
private readonly QueryBuilderPaginatorService $paginatorService
)
{
}
public function query(Collection $requestParameters): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
{
if ($requestParameters->get("q", "") !== "" && !$requestParameters->has("letter")) {
$searchEngineOptions = $this->getSearchEngineOptions($requestParameters);
$builder = $this->searchService->setFilterParameters($requestParameters)
->search($requestParameters->get("q"), $searchEngineOptions["order_by"], $searchEngineOptions["sort_direction_descending"]);
} else {
$builder = $this->searchService->setFilterParameters($requestParameters)->query();
if (!$requestParameters->has("order_by")) {
$builder = $builder->orderBy("mal_id");
}
}
return $builder;
}
public function paginate(\Illuminate\Database\Eloquent\Builder|\Laravel\Scout\Builder $builder, ?int $page = null, ?int $limit = null): array
{
$paginated = $this->paginateBuilder($builder, $page, $limit);
$items = $paginated->items();
foreach ($items as &$item) {
unset($item['_id']);
}
return [
'per_page' => $paginated->perPage(),
'total' => $paginated->total(),
'current_page' => $paginated->currentPage(),
'last_page' => $paginated->lastPage(),
'data' => $items
];
}
public function paginateBuilder(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $builder, ?int $page = null, ?int $limit = null): \Illuminate\Contracts\Pagination\LengthAwarePaginator
{
return $this->paginatorService->paginate($builder, $limit, $page);
}
private function getSearchEngineOptions(Collection $requestParameters): array
{
$orderBy = $requestParameters->get("order_by");
$sort = $requestParameters->get("sort");
$searchOptions = [];
// todo: validate whether the specified field exists on the model
if (!empty($orderBy)) {
$searchOptions["order_by"] = $orderBy;
} else {
$searchOptions["order_by"] = null;
}
if (!empty($sort) && in_array($sort, ["asc", "desc"])) {
$searchOptions["sort_direction_descending"] = $sort == "desc";
} else {
$searchOptions["sort_direction_descending"] = false;
}
return $searchOptions;
}
}