81 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			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();
 | 
						|
    }
 | 
						|
}
 |