service-captcha/app/Services/Search/Search.php

81 lines
2.3 KiB
PHP

<?php declare(strict_types=1);
namespace App\Services\Search;
use App\Models\Role;
use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Pagination\CursorPaginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
use App\Contracts\Search as SearchContract;
final readonly class Search implements SearchContract
{
public function __construct(
private Relation|Builder $query
) { }
public function all(): Collection
{
return $this->query->get();
}
public function get(int $limit): Collection
{
return $this->query->limit($limit)->get();
}
public function pagination(int $limit, int $page = 1): LengthAwarePaginator
{
if ($page > 100) {
return $this->paginationPerfomance($limit, $page);
}
return $this->query->paginate($limit, page: $page)->withQueryString();
}
public function cursorPaginate(int $limit): CursorPaginator
{
return $this->query->cursorPaginate($limit);
}
private function paginationPerfomance(int $limit, int $page = 1): LengthAwarePaginator
{
$total = $this->query->clone()->count();
$options = [
'path' => Paginator::resolveCurrentPath(),
'pageName' => 'page',
];
$result = collect();
if ($total > 0) {
$result = $this->subQuery($limit, $page);
}
$pagination = Container::getInstance()->makeWith(LengthAwarePaginator::class, [
'items' => $result,
'total' => $total,
'perPage' => $limit,
'currentPage' => $page,
'options' => $options
]);
return $pagination->withQueryString();
}
private function subQuery(int $limit, int $page): Collection
{
$table = $this->query->getModel()->getTable();
return $this->query->getModel()::query()
->select($table.'.*')
->with($this->query->getEagerLoads())
->from(
clone $this->query->select('id')->forPage($page, $limit),
'q'
)->join($table.' as '.$table, $table.'.id', '=', 'q.id')
->get();
}
}