Files
animethemes-server/app/GraphQL/Schema/Queries/SearchQuery.php
T
2026-03-09 10:41:34 -03:00

141 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\GraphQL\Schema\Queries;
use App\Concerns\Actions\GraphQL\ConstrainsEagerLoads;
use App\GraphQL\Argument\Argument;
use App\GraphQL\Argument\FirstArgument;
use App\GraphQL\Argument\PageArgument;
use App\GraphQL\Schema\Types\EloquentType;
use App\GraphQL\Schema\Types\List\PlaylistType;
use App\GraphQL\Schema\Types\SearchType;
use App\GraphQL\Schema\Types\Wiki\Anime\AnimeThemeType;
use App\GraphQL\Schema\Types\Wiki\AnimeType;
use App\GraphQL\Schema\Types\Wiki\ArtistType;
use App\GraphQL\Schema\Types\Wiki\SeriesType;
use App\GraphQL\Schema\Types\Wiki\SongType;
use App\GraphQL\Schema\Types\Wiki\StudioType;
use App\GraphQL\Schema\Types\Wiki\VideoType;
use App\Models\List\Playlist;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Anime\AnimeTheme;
use App\Models\Wiki\Artist;
use App\Models\Wiki\Series;
use App\Models\Wiki\Song;
use App\Models\Wiki\Studio;
use App\Models\Wiki\Video;
use App\Search\Criteria;
use App\Search\Search;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Number;
class SearchQuery extends BaseQuery
{
use ConstrainsEagerLoads;
public function __construct()
{
parent::__construct(false);
}
public function name(): string
{
return 'search';
}
public function description(): string
{
return 'Returns a listing of resources that match a given search term.';
}
/**
* The arguments of the type.
*
* @return Argument[]
*/
public function arguments(): array
{
return [
new Argument('search', Type::string())
->required(),
new FirstArgument(),
new PageArgument(),
];
}
/**
* The base return type of the query.
*/
public function baseType(): SearchType
{
return new SearchType();
}
/**
* @return array<string, array>
*/
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): array
{
$result = [];
$fields = $resolveInfo->getFieldSelection();
if (Arr::get($fields, 'anime')) {
$result['anime'] = $this->search(Anime::class, $args, $resolveInfo, new AnimeType, 'anime');
}
if (Arr::get($fields, 'artists')) {
$result['artists'] = $this->search(Artist::class, $args, $resolveInfo, new ArtistType, 'artists');
}
if (Arr::get($fields, 'animethemes')) {
$result['animethemes'] = $this->search(AnimeTheme::class, $args, $resolveInfo, new AnimeThemeType, 'animethemes');
}
if (Arr::get($fields, 'playlists')) {
$result['playlists'] = $this->search(Playlist::class, $args, $resolveInfo, new PlaylistType, 'playlists');
}
if (Arr::get($fields, 'series')) {
$result['series'] = $this->search(Series::class, $args, $resolveInfo, new SeriesType, 'series');
}
if (Arr::get($fields, 'songs')) {
$result['songs'] = $this->search(Song::class, $args, $resolveInfo, new SongType, 'songs');
}
if (Arr::get($fields, 'studios')) {
$result['studios'] = $this->search(Studio::class, $args, $resolveInfo, new StudioType, 'studios');
}
if (Arr::get($fields, 'videos')) {
$result['videos'] = $this->search(Video::class, $args, $resolveInfo, new VideoType, 'videos');
}
return $result;
}
/**
* @param class-string<Model> $modelClass
*/
protected function search(string $modelClass, array $args, ResolveInfo $resolveInfo, EloquentType $type, string $fieldName): Collection
{
$term = Arr::get($args, 'search');
$page = Arr::get($args, 'page', 1);
$first = Number::clamp(Arr::get($args, 'first'), 1, 15);
$searchBuilder = Search::search($modelClass, new Criteria($term))
->passToEloquentBuilder(fn (Builder $builder) => $this->constrainEagerLoads($builder, $resolveInfo, $type, $fieldName))
->withPagination($first, $page);
return collect($searchBuilder->execute()->items());
}
}