mirror of
https://github.com/AnimeThemes/animethemes-server.git
synced 2026-07-11 01:24:46 +02:00
chore(graphql): migrate to rebing/graphql (#921)
This commit is contained in:
+5
-8
@@ -179,6 +179,11 @@ FORTIFY_HOME=http://localhost
|
||||
FORTIFY_PATH=
|
||||
FORTIFY_URL=http://localhost
|
||||
|
||||
# graphql
|
||||
GRAPHQL_DOMAIN_NAME=
|
||||
GRAPHQL_PATH=/graphql
|
||||
GRAPHIQL_ENABLED=true
|
||||
|
||||
# hashids
|
||||
HASHIDS_SALT_MAIN=
|
||||
HASHIDS_SALT_PLAYLISTS=
|
||||
@@ -198,14 +203,6 @@ IMAGE_DISK_ROOT=
|
||||
JETSTREAM_PATH=
|
||||
JETSTREAM_URL=http://localhost
|
||||
|
||||
# lighthouse
|
||||
GRAPHQL_DOMAIN_NAME=
|
||||
GRAPHQL_PATH=/graphql
|
||||
GRAPHIQL_ENABLED=true
|
||||
LIGHTHOUSE_DEBUG=true
|
||||
LIGHTHOUSE_MAX_QUERY_COMPLEXITY=100
|
||||
LIGHTHOUSE_MAX_QUERY_DEPTH=10
|
||||
|
||||
# logging
|
||||
LOG_CHANNEL=daily
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
|
||||
+5
-8
@@ -177,6 +177,11 @@ FORTIFY_HOME=http://localhost:3000
|
||||
FORTIFY_PATH=
|
||||
FORTIFY_URL=http://localhost
|
||||
|
||||
# graphql
|
||||
GRAPHQL_DOMAIN_NAME=
|
||||
GRAPHQL_PATH=/graphql
|
||||
GRAPHIQL_ENABLED=true
|
||||
|
||||
# hashids
|
||||
HASHIDS_SALT_MAIN=
|
||||
HASHIDS_SALT_PLAYLISTS=
|
||||
@@ -196,14 +201,6 @@ IMAGE_DISK_ROOT=
|
||||
JETSTREAM_PATH=
|
||||
JETSTREAM_URL=http://localhost
|
||||
|
||||
# lighthouse
|
||||
GRAPHQL_DOMAIN_NAME=
|
||||
GRAPHQL_PATH=/graphql
|
||||
GRAPHIQL_ENABLED=true
|
||||
LIGHTHOUSE_DEBUG=true
|
||||
LIGHTHOUSE_MAX_QUERY_COMPLEXITY=100
|
||||
LIGHTHOUSE_MAX_QUERY_DEPTH=10
|
||||
|
||||
# logging
|
||||
LOG_CHANNEL=daily
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Concerns\Actions\GraphQL;
|
||||
|
||||
use App\GraphQL\Definition\Types\BaseType;
|
||||
use App\GraphQL\Definition\Unions\BaseUnion;
|
||||
use App\GraphQL\Support\Relations\Relation;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation as RelationLaravel;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait ConstrainsEagerLoads
|
||||
{
|
||||
use FiltersModels;
|
||||
use SortsModels;
|
||||
|
||||
/**
|
||||
* Apply eager loads with filters and sorting.
|
||||
*/
|
||||
protected function constrainEagerLoads(Builder $query, ResolveInfo|array $resolveInfo, BaseType $type): void
|
||||
{
|
||||
$fields = $resolveInfo instanceof ResolveInfo
|
||||
? Arr::get($resolveInfo->getFieldSelectionWithAliases(100), 'data.data.selectionSet')
|
||||
: $resolveInfo;
|
||||
|
||||
$this->processEagerLoadForType($query, $fields, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process recursively the relations available for the given type.
|
||||
*/
|
||||
private function processEagerLoadForType(Builder $builder, array $fields, BaseType|BaseUnion $type): void
|
||||
{
|
||||
$eagerLoadRelations = [];
|
||||
|
||||
/** @var array<int, Relation> $relations */
|
||||
$relations = collect($type->relations())
|
||||
->filter(fn (Relation $relation) => Arr::has($fields, $relation->getName()))
|
||||
->toArray();
|
||||
|
||||
foreach ($relations as $relation) {
|
||||
$name = $relation->getName();
|
||||
$path = $relation->getRelationName();
|
||||
|
||||
$relationSelection = Arr::get($fields, "{$name}.{$name}");
|
||||
|
||||
$relationArgs = Arr::get($relationSelection, 'args');
|
||||
|
||||
$relationType = $relation->getBaseType();
|
||||
|
||||
$eagerLoadRelations[$path] = function (RelationLaravel $relationLaravel) use ($relationSelection, $relationArgs, $relationType) {
|
||||
$relationQuery = $relationLaravel->getQuery();
|
||||
|
||||
if ($relationLaravel instanceof MorphTo) {
|
||||
$unions = Arr::get($relationSelection, 'unions');
|
||||
$subTypes = collect($relationType->baseTypes())
|
||||
->filter(fn (BaseType $type) => Arr::has($unions, $type->getName()))
|
||||
->toArray();
|
||||
|
||||
$morphConstrains = [];
|
||||
foreach ($subTypes as $subType) {
|
||||
$subTypeSelection = Arr::get($unions, "{$subType->getName()}.selectionSet");
|
||||
|
||||
$morphConstrains[$subType->model()] = function (Builder $subMorphQuery) use ($subTypeSelection, $subType) {
|
||||
$this->processEagerLoadForType($subMorphQuery, $subTypeSelection, $subType);
|
||||
};
|
||||
}
|
||||
|
||||
$relationLaravel->constrain($morphConstrains);
|
||||
} else {
|
||||
$this->filter($relationQuery, $relationArgs, $relationType);
|
||||
|
||||
$this->sort($relationQuery, $relationArgs, $relationType);
|
||||
|
||||
$child = Arr::get($relationSelection, 'selectionSet.data.data.selectionSet')
|
||||
?? Arr::get($relationSelection, 'selectionSet', []);
|
||||
|
||||
$this->processEagerLoadForType($relationQuery, $child, $relationType);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$builder->with($eagerLoadRelations);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Concerns\Actions\GraphQL;
|
||||
|
||||
use App\GraphQL\Definition\Types\BaseType;
|
||||
use App\GraphQL\Definition\Unions\BaseUnion;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait FiltersModels
|
||||
{
|
||||
public function filter(Builder $builder, array $args, BaseType|BaseUnion $type): Builder
|
||||
{
|
||||
// union not supported yet
|
||||
if ($type instanceof BaseUnion) {
|
||||
return $builder;
|
||||
}
|
||||
|
||||
$resolvers = Filter::getValueWithResolvers($type);
|
||||
|
||||
foreach ($args as $arg => $value) {
|
||||
$valueResolver = Arr::get($resolvers, $arg);
|
||||
|
||||
if ($valueResolver === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var Filter $filter */
|
||||
$filter = Arr::get($valueResolver, 'filter');
|
||||
|
||||
$filter->apply($builder, $value);
|
||||
}
|
||||
|
||||
return $builder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Concerns\Actions\GraphQL;
|
||||
|
||||
use App\Exceptions\GraphQL\ClientValidationException;
|
||||
use Illuminate\Contracts\Pagination\Paginator;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
trait PaginatesModels
|
||||
{
|
||||
public function paginate(Builder $builder, array $args): Paginator
|
||||
{
|
||||
$first = Arr::get($args, 'first');
|
||||
$page = Arr::get($args, 'page');
|
||||
|
||||
$maxCount = Config::get('graphql.pagination_values.max_count');
|
||||
if ($maxCount !== null && $first > $maxCount) {
|
||||
throw new ClientValidationException("Maximum first value is {$maxCount}. Got {$first}. Fetch in smaller chuncks.");
|
||||
}
|
||||
|
||||
return $builder->paginate($first, page: $page);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Concerns\Actions\GraphQL;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait SearchModels
|
||||
{
|
||||
/**
|
||||
* Search models.
|
||||
*
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function search(Builder $builder, array $args): Builder
|
||||
{
|
||||
$search = Arr::get($args, 'search');
|
||||
|
||||
if ($search !== null) {
|
||||
$model = $builder->getModel();
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$keys = $model::search($search)->keys();
|
||||
|
||||
$builder->whereIn($model->getKeyName(), $keys);
|
||||
}
|
||||
|
||||
return $builder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Concerns\Actions\GraphQL;
|
||||
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Definition\Types\BaseType;
|
||||
use App\GraphQL\Definition\Unions\BaseUnion;
|
||||
use App\GraphQL\Support\Argument\SortArgument;
|
||||
use App\GraphQL\Support\Sort\RandomSort;
|
||||
use App\GraphQL\Support\Sort\Sort;
|
||||
use App\GraphQL\Support\SortableColumns;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
|
||||
trait SortsModels
|
||||
{
|
||||
/**
|
||||
* Apply sorts to the query builder.
|
||||
*/
|
||||
public function sort(Builder $builder, array $args, BaseType|BaseUnion $type): Builder
|
||||
{
|
||||
$sorts = Arr::get($args, SortArgument::ARGUMENT);
|
||||
|
||||
if (blank($sorts)) {
|
||||
return $builder;
|
||||
}
|
||||
|
||||
$resolvers = new SortableColumns($type)->getValuesWithResolver();
|
||||
|
||||
$this->applySort($builder, $sorts, $resolvers);
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $sorts
|
||||
* @param array<string, array<string, mixed>> $resolvers
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function applySort(Builder $builder, array $sorts, array $resolvers): Builder
|
||||
{
|
||||
foreach ($sorts as $sort) {
|
||||
if ($sort === RandomSort::CASE) {
|
||||
$builder->inRandomOrder();
|
||||
continue;
|
||||
}
|
||||
|
||||
$resolver = Arr::get($resolvers, Str::remove('_DESC', $sort));
|
||||
|
||||
$direction = Sort::resolveFromEnumCase($sort);
|
||||
|
||||
$column = Arr::get($resolver, SortableColumns::RESOLVER_COLUMN);
|
||||
$sortType = Arr::get($resolver, SortableColumns::RESOLVER_SORT_TYPE);
|
||||
|
||||
if ($sortType === SortType::ROOT) {
|
||||
$builder->orderBy($column, $direction);
|
||||
}
|
||||
|
||||
if ($sortType === SortType::AGGREGATE) {
|
||||
$relation = Arr::get($resolver, SortableColumns::RESOLVER_RELATION);
|
||||
if ($relation === null) {
|
||||
throw new InvalidArgumentException("The 'relation' argument is required for the {$column} column with aggregate sort type.");
|
||||
}
|
||||
|
||||
$builder->withAggregate([
|
||||
"$relation as {$relation}_value" => function ($query) use ($direction) {
|
||||
$query->orderBy('value', $direction);
|
||||
},
|
||||
], 'value');
|
||||
|
||||
$builder->orderBy("{$relation}_value", $direction);
|
||||
}
|
||||
}
|
||||
|
||||
return $builder;
|
||||
}
|
||||
}
|
||||
@@ -15,30 +15,28 @@ use App\GraphQL\Definition\Types\BaseType;
|
||||
use App\GraphQL\Support\Argument\Argument;
|
||||
use App\GraphQL\Support\Argument\BindableArgument;
|
||||
use App\GraphQL\Support\Argument\SortArgument;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait ResolvesArguments
|
||||
{
|
||||
use ResolvesDirectives;
|
||||
|
||||
/**
|
||||
* Build the arguments array into string.
|
||||
* Resolve the args.
|
||||
*
|
||||
* @param Argument[] $arguments
|
||||
* @return array<string, array<string, mixed>>
|
||||
*/
|
||||
protected function buildArguments(array $arguments): string
|
||||
public function args(): array
|
||||
{
|
||||
if (blank($arguments)) {
|
||||
return '';
|
||||
}
|
||||
return collect($this->arguments())
|
||||
->mapWithKeys(fn (Argument $argument) => [
|
||||
$argument->name => [
|
||||
'name' => $argument->name,
|
||||
'type' => $argument->getType(),
|
||||
|
||||
$arguments = collect($arguments)
|
||||
->flatten()
|
||||
->map(fn (Argument $argument) => $argument->__toString())
|
||||
->implode(', ');
|
||||
|
||||
return sprintf('(%s)', $arguments);
|
||||
...(! is_null($argument->getDefaultValue()) ? ['defaultValue' => $argument->getDefaultValue()] : []),
|
||||
],
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,8 +50,8 @@ trait ResolvesArguments
|
||||
return collect($fields)
|
||||
->filter(fn (Field $field) => $field instanceof FilterableField)
|
||||
->map(
|
||||
fn (FilterableField $field) => collect($field->filterDirectives())
|
||||
->map(fn (FilterDirective $directive) => $directive->argument())
|
||||
fn (FilterableField $field) => collect($field->getFilters())
|
||||
->map(fn (Filter $filter) => $filter->argument())
|
||||
->toArray()
|
||||
)
|
||||
->flatten()
|
||||
@@ -81,7 +79,7 @@ trait ResolvesArguments
|
||||
return collect($fields)
|
||||
->filter(fn (Field $field) => $field instanceof CreatableField)
|
||||
->map(
|
||||
fn (Field $field) => new Argument($field->getColumn(), $field->type())
|
||||
fn (Field $field) => new Argument($field->getColumn(), $field->baseType())
|
||||
->required($field instanceof RequiredOnCreation)
|
||||
)
|
||||
->flatten()
|
||||
@@ -99,7 +97,7 @@ trait ResolvesArguments
|
||||
return collect($fields)
|
||||
->filter(fn (Field $field) => $field instanceof UpdatableField)
|
||||
->map(
|
||||
fn (Field $field) => new Argument($field->getColumn(), $field->type())
|
||||
fn (Field $field) => new Argument($field->getColumn(), $field->baseType())
|
||||
->required($field instanceof RequiredOnUpdate)
|
||||
)
|
||||
->flatten()
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Concerns\GraphQL;
|
||||
|
||||
use App\GraphQL\Attributes\Deprecated;
|
||||
use App\GraphQL\Attributes\Resolvers\UseAllDirective;
|
||||
use App\GraphQL\Attributes\Resolvers\UseAuthDirective;
|
||||
use App\GraphQL\Attributes\Resolvers\UseBuilderDirective;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFindDirective;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFirstDirective;
|
||||
use App\GraphQL\Attributes\Resolvers\UsePaginateDirective;
|
||||
use App\GraphQL\Attributes\UseSearchDirective;
|
||||
use Illuminate\Support\Arr;
|
||||
use ReflectionClass;
|
||||
|
||||
trait ResolvesAttributes
|
||||
{
|
||||
/**
|
||||
* Resolve the all directive as an attribute.
|
||||
*/
|
||||
protected function resolveAllAttribute(): bool
|
||||
{
|
||||
$reflection = new ReflectionClass($this);
|
||||
|
||||
$attributes = $reflection->getAttributes(UseAllDirective::class);
|
||||
|
||||
if (filled($attributes)) {
|
||||
$instance = Arr::first($attributes)->newInstance();
|
||||
|
||||
return $instance->shouldUse;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the auth directive as an attribute.
|
||||
*/
|
||||
protected function resolveAuthAttribute(): bool
|
||||
{
|
||||
$reflection = new ReflectionClass($this);
|
||||
|
||||
$attributes = $reflection->getAttributes(UseAuthDirective::class);
|
||||
|
||||
if (filled($attributes)) {
|
||||
$instance = Arr::first($attributes)->newInstance();
|
||||
|
||||
return $instance->shouldUse;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the builder directive as an attribute.
|
||||
*/
|
||||
protected function resolveBuilderAttribute(): ?string
|
||||
{
|
||||
$reflection = new ReflectionClass($this);
|
||||
|
||||
$attributes = [];
|
||||
|
||||
while ($reflection) {
|
||||
$attributes = array_merge($attributes, $reflection->getAttributes(UseBuilderDirective::class));
|
||||
$reflection = $reflection->getParentClass();
|
||||
}
|
||||
|
||||
if (filled($attributes)) {
|
||||
$instance = Arr::first($attributes)->newInstance();
|
||||
|
||||
return sprintf('%s@%s', $instance->controllerClass, $instance->method);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the deprecated directive as an attribute.
|
||||
*/
|
||||
protected function resolveDeprecatedAttribute(): ?string
|
||||
{
|
||||
$reflection = new ReflectionClass($this);
|
||||
|
||||
$attributes = $reflection->getAttributes(Deprecated::class);
|
||||
|
||||
if (filled($attributes)) {
|
||||
$instance = Arr::first($attributes)->newInstance();
|
||||
|
||||
return $instance->reason;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the field directive as an attribute.
|
||||
*/
|
||||
protected function resolveFieldAttribute(): ?string
|
||||
{
|
||||
$reflection = new ReflectionClass($this);
|
||||
|
||||
$attributes = [];
|
||||
|
||||
while ($reflection) {
|
||||
$attributes = array_merge($attributes, $reflection->getAttributes(UseFieldDirective::class));
|
||||
$reflection = $reflection->getParentClass();
|
||||
}
|
||||
|
||||
if (filled($attributes)) {
|
||||
$instance = Arr::first($attributes)->newInstance();
|
||||
|
||||
return sprintf('%s@%s', $instance->fieldClass, $instance->method);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the first directive as an attribute.
|
||||
*/
|
||||
protected function resolveFirstAttribute(): bool
|
||||
{
|
||||
$reflection = new ReflectionClass($this);
|
||||
|
||||
$attributes = [];
|
||||
|
||||
while ($reflection) {
|
||||
$attributes = array_merge($attributes, $reflection->getAttributes(UseFirstDirective::class));
|
||||
$reflection = $reflection->getParentClass();
|
||||
|
||||
if (filled($attributes)) {
|
||||
$instance = Arr::first($attributes)->newInstance();
|
||||
|
||||
return $instance->shouldUse;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the find directive as an attribute.
|
||||
*/
|
||||
protected function resolveFindAttribute(): bool
|
||||
{
|
||||
$reflection = new ReflectionClass($this);
|
||||
|
||||
$attributes = $reflection->getAttributes(UseFindDirective::class);
|
||||
|
||||
if (filled($attributes)) {
|
||||
$instance = Arr::first($attributes)->newInstance();
|
||||
|
||||
return $instance->shouldUse;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the paginate directive as an attribute.
|
||||
*/
|
||||
protected function resolvePaginateAttribute(): array|bool
|
||||
{
|
||||
$reflection = new ReflectionClass($this);
|
||||
|
||||
$attributes = $reflection->getAttributes(UsePaginateDirective::class);
|
||||
|
||||
if (filled($attributes)) {
|
||||
$instance = Arr::first($attributes)->newInstance();
|
||||
|
||||
if ($instance->shouldUse && is_string($instance->builder)) {
|
||||
return [
|
||||
'builder' => $instance->builder,
|
||||
];
|
||||
}
|
||||
|
||||
return $instance->shouldUse;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the search directive as an attribute.
|
||||
*/
|
||||
protected function resolveSearchAttribute(): bool
|
||||
{
|
||||
$reflection = new ReflectionClass($this);
|
||||
|
||||
$attributes = [];
|
||||
|
||||
while ($reflection) {
|
||||
$attributes = array_merge($attributes, $reflection->getAttributes(UseSearchDirective::class));
|
||||
$reflection = $reflection->getParentClass();
|
||||
}
|
||||
|
||||
return filled($attributes);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Concerns\GraphQL;
|
||||
|
||||
trait ResolvesDirectives
|
||||
{
|
||||
/**
|
||||
* Convert the array of directives into a string format for GraphQL.
|
||||
*
|
||||
* @param array<string, array<string, mixed>> $directives
|
||||
*/
|
||||
protected static function resolveDirectives(array $directives): string
|
||||
{
|
||||
return collect($directives)
|
||||
->map(function ($args, $directive) {
|
||||
if (blank($args)) {
|
||||
return sprintf('@%s', $directive);
|
||||
}
|
||||
|
||||
$argsString = collect($args)
|
||||
->map(fn ($value, $key) => sprintf('%s: %s', $key, json_encode($value)))
|
||||
->implode(', ');
|
||||
|
||||
return sprintf('@%s(%s)', $directive, $argsString);
|
||||
})
|
||||
->implode(' ');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Console\Commands\GraphQL;
|
||||
|
||||
use App\Console\Commands\BaseCommand;
|
||||
use GraphQL\Utils\SchemaPrinter;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Support\Facades\Validator as ValidatorFacade;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class GraphQLPrintSchemaCommand extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*/
|
||||
protected $signature = 'graphql:print-schema {schema=default}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*/
|
||||
protected $description = 'Print the GraphQL schema into SDL';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$schemaName = $this->argument('schema');
|
||||
|
||||
$schema = GraphQL::schema($schemaName);
|
||||
|
||||
$sdl = SchemaPrinter::doPrint($schema);
|
||||
|
||||
$this->line($sdl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validator for options.
|
||||
*/
|
||||
protected function validator(): Validator
|
||||
{
|
||||
return ValidatorFacade::make($this->options(), []);
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
interface BindableField
|
||||
{
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<Model>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string;
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string;
|
||||
public function bindResolver(array $args): ?Model;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Contracts\GraphQL\Fields;
|
||||
|
||||
interface DeprecatedField
|
||||
{
|
||||
/**
|
||||
* The reason which the field is deprecated.
|
||||
*/
|
||||
public function deprecationReason(): string;
|
||||
}
|
||||
@@ -4,14 +4,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Contracts\GraphQL\Fields;
|
||||
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
|
||||
interface FilterableField
|
||||
{
|
||||
/**
|
||||
* The directives available for this field.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array;
|
||||
public function getFilters(): array;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enums\GraphQL;
|
||||
|
||||
enum PaginationType
|
||||
{
|
||||
case NONE;
|
||||
case SIMPLE;
|
||||
case PAGINATOR;
|
||||
case CONNECTION;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Exceptions\GraphQL;
|
||||
|
||||
use Exception;
|
||||
use GraphQL\Error\ClientAware;
|
||||
|
||||
/**
|
||||
* Thrown when query is not allowed.
|
||||
*/
|
||||
class ClientForbiddenException extends Exception implements ClientAware
|
||||
{
|
||||
public function isClientSafe(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Attributes;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_ALL)]
|
||||
class Deprecated
|
||||
{
|
||||
public function __construct(
|
||||
public string $reason,
|
||||
) {}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Attributes;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_ALL)]
|
||||
class Hidden
|
||||
{
|
||||
public function __construct(
|
||||
public bool $hidden = true,
|
||||
) {}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Attributes\Resolvers;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
class UseAllDirective
|
||||
{
|
||||
public function __construct(
|
||||
public bool $shouldUse = true,
|
||||
) {}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Attributes\Resolvers;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
class UseAuthDirective
|
||||
{
|
||||
public function __construct(
|
||||
public bool $shouldUse = true,
|
||||
) {}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Attributes\Resolvers;
|
||||
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
class UseBuilderDirective
|
||||
{
|
||||
/**
|
||||
* @param class-string<BaseController> $controllerClass
|
||||
*/
|
||||
public function __construct(
|
||||
public string $controllerClass,
|
||||
public string $method = 'index',
|
||||
) {}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Attributes\Resolvers;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
class UseFieldDirective
|
||||
{
|
||||
/**
|
||||
* @param class-string $fieldClass
|
||||
*/
|
||||
public function __construct(
|
||||
public string $fieldClass,
|
||||
public string $method = '__invoke',
|
||||
) {}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Attributes\Resolvers;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
class UseFindDirective
|
||||
{
|
||||
public function __construct(
|
||||
public bool $shouldUse = true,
|
||||
) {}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Attributes\Resolvers;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
class UseFirstDirective
|
||||
{
|
||||
public function __construct(
|
||||
public bool $shouldUse = true,
|
||||
) {}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Attributes\Resolvers;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
class UsePaginateDirective
|
||||
{
|
||||
public function __construct(
|
||||
public bool $shouldUse = true,
|
||||
public ?string $builder = null,
|
||||
) {}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Attributes;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
class UseSearchDirective {}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Admin;
|
||||
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\Admin\Announcement;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Announcement>
|
||||
*/
|
||||
class AnnouncementController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'id';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the index query.
|
||||
*
|
||||
* @param Builder<Announcement> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Announcement>
|
||||
*/
|
||||
public function index(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
return $builder->public();
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Admin;
|
||||
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\Admin\FeaturedTheme;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<FeaturedTheme>
|
||||
*/
|
||||
class CurrentFeaturedThemeController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'id';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the show query.
|
||||
*
|
||||
* @param Builder<FeaturedTheme> $builder
|
||||
* @param array $args
|
||||
* @return Builder<FeaturedTheme>
|
||||
*/
|
||||
public function show(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
return $builder
|
||||
->whereValueBetween(Date::now(), [
|
||||
FeaturedTheme::ATTRIBUTE_START_AT,
|
||||
FeaturedTheme::ATTRIBUTE_END_AT,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Admin;
|
||||
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\Admin\Dump;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Dump>
|
||||
*/
|
||||
class DumpController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'id';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the index query.
|
||||
*
|
||||
* @param Builder<Dump> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Dump>
|
||||
*/
|
||||
public function index(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
return $builder->onlySafeDumps();
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Admin;
|
||||
|
||||
use App\Constants\FeatureConstants;
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\Admin\Feature;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Feature>
|
||||
*/
|
||||
class FeatureController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'id';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the index query.
|
||||
*
|
||||
* @param Builder<Feature> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Feature>
|
||||
*/
|
||||
public function index(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
return $builder->where(Feature::ATTRIBUTE_SCOPE, FeatureConstants::NULL_SCOPE);
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Admin;
|
||||
|
||||
use App\Enums\Http\Api\Filter\ComparisonOperator;
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\Admin\FeaturedTheme;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<FeaturedTheme>
|
||||
*/
|
||||
class FeaturedThemeController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'id';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the index query.
|
||||
*
|
||||
* @param Builder<FeaturedTheme> $builder
|
||||
* @param array $args
|
||||
* @return Builder<FeaturedTheme>
|
||||
*/
|
||||
public function index(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
return $builder->whereNotNull(FeaturedTheme::ATTRIBUTE_START_AT)
|
||||
->whereDate(FeaturedTheme::ATTRIBUTE_START_AT, ComparisonOperator::LTE->value, Date::now());
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ use App\Actions\Http\Api\StoreAction;
|
||||
use App\Actions\Http\Api\UpdateAction;
|
||||
use App\GraphQL\Definition\Mutations\BaseMutation;
|
||||
use Dotenv\Exception\ValidationException;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
@@ -19,6 +20,8 @@ use Illuminate\Support\Facades\Validator;
|
||||
*/
|
||||
abstract class BaseController
|
||||
{
|
||||
final public const MODEL = 'model';
|
||||
|
||||
/**
|
||||
* @param StoreAction<TModel> $storeAction
|
||||
* @param UpdateAction<TModel> $updateAction
|
||||
@@ -43,6 +46,12 @@ abstract class BaseController
|
||||
{
|
||||
$mutationInstance = App::make($mutation);
|
||||
|
||||
return Validator::make($args, $mutationInstance->rules($args))->validated();
|
||||
$validated = Validator::make($args, $mutationInstance->rulesForValidation($args))->validated();
|
||||
|
||||
return [
|
||||
...$validated,
|
||||
|
||||
'model' => Arr::get($args, self::MODEL),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Document;
|
||||
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\Document\Page;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Page>
|
||||
*/
|
||||
class PageController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'slug';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the show query.
|
||||
*
|
||||
* @param Builder<Page> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Page>
|
||||
*/
|
||||
public function show(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
return $builder
|
||||
->where(self::ROUTE_SLUG, Arr::get($args, self::ROUTE_SLUG));
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\List\External;
|
||||
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\List\External\ExternalEntry;
|
||||
use App\Models\List\ExternalProfile;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<ExternalEntry>
|
||||
*/
|
||||
class ExternalEntryController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'id';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the index query.
|
||||
*
|
||||
* @param Builder<ExternalEntry> $builder
|
||||
* @param array $args
|
||||
* @return Builder<ExternalEntry>
|
||||
*/
|
||||
public function index(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
/** @var ExternalProfile $profile */
|
||||
$profile = Arr::get($args, 'profile');
|
||||
|
||||
$builder->where(ExternalEntry::ATTRIBUTE_PROFILE, $profile->getKey());
|
||||
|
||||
return $builder;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\List;
|
||||
|
||||
use App\Enums\Models\List\ExternalProfileVisibility;
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\List\ExternalProfile;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<ExternalProfile>
|
||||
*/
|
||||
class ExternalProfileController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'id';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the index query.
|
||||
*
|
||||
* @param Builder<ExternalProfile> $builder
|
||||
* @param array $args
|
||||
* @return Builder<ExternalProfile>
|
||||
*/
|
||||
public function index(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
$builder->where(ExternalProfile::ATTRIBUTE_VISIBILITY, ExternalProfileVisibility::PUBLIC->value);
|
||||
|
||||
if ($user = Auth::user()) {
|
||||
return $builder->orWhereBelongsTo($user, ExternalProfile::RELATION_USER);
|
||||
}
|
||||
|
||||
return $builder;
|
||||
}
|
||||
}
|
||||
@@ -12,56 +12,18 @@ use App\GraphQL\Definition\Mutations\Models\List\Playlist\Track\CreatePlaylistTr
|
||||
use App\GraphQL\Definition\Mutations\Models\List\Playlist\Track\UpdatePlaylistTrackMutation;
|
||||
use App\Models\List\Playlist;
|
||||
use App\Models\List\Playlist\PlaylistTrack;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Arr;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<PlaylistTrack>
|
||||
*/
|
||||
class PlaylistTrackController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'id';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the index query.
|
||||
*
|
||||
* @param Builder<PlaylistTrack> $builder
|
||||
* @param array<string, mixed> $args
|
||||
* @return Builder<PlaylistTrack>
|
||||
*/
|
||||
public function index(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
/** @var Playlist $playlist */
|
||||
$playlist = Arr::get($args, 'playlist');
|
||||
|
||||
$builder->where(PlaylistTrack::ATTRIBUTE_PLAYLIST, $playlist->getKey());
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the query builder to the show query.
|
||||
*
|
||||
* @param Builder<PlaylistTrack> $builder
|
||||
* @param array<string, mixed> $args
|
||||
* @return Builder<PlaylistTrack>
|
||||
*/
|
||||
public function show(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
$builder->whereRelation(PlaylistTrack::RELATION_PLAYLIST, Playlist::ATTRIBUTE_HASHID, Arr::get($args, 'playlist'));
|
||||
$builder->where(PlaylistTrack::ATTRIBUTE_HASHID, Arr::get($args, self::ROUTE_SLUG));
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource.
|
||||
*
|
||||
* @param null $root
|
||||
* @param array $args
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function store($root, array $args): PlaylistTrack
|
||||
{
|
||||
@@ -81,14 +43,14 @@ class PlaylistTrackController extends BaseController
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param null $root
|
||||
* @param array $args
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function update($root, array $args): PlaylistTrack
|
||||
{
|
||||
$validated = $this->validated($args, UpdatePlaylistTrackMutation::class);
|
||||
|
||||
/** @var PlaylistTrack $track */
|
||||
$track = Arr::pull($validated, self::ROUTE_SLUG);
|
||||
$track = Arr::pull($validated, self::MODEL);
|
||||
|
||||
$action = new UpdateTrackAction();
|
||||
|
||||
@@ -101,19 +63,19 @@ class PlaylistTrackController extends BaseController
|
||||
* Remove the specified resource.
|
||||
*
|
||||
* @param null $root
|
||||
* @param array $args
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function destroy($root, array $args): JsonResponse
|
||||
public function destroy($root, array $args): array
|
||||
{
|
||||
/** @var PlaylistTrack $track */
|
||||
$track = Arr::get($args, self::ROUTE_SLUG);
|
||||
$track = Arr::get($args, self::MODEL);
|
||||
|
||||
$action = new DestroyTrackAction();
|
||||
|
||||
$message = $action->destroy($track->playlist, $track);
|
||||
|
||||
return new JsonResponse([
|
||||
return [
|
||||
'message' => $message,
|
||||
]);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,61 +4,23 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\List;
|
||||
|
||||
use App\Enums\Models\List\PlaylistVisibility;
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\GraphQL\Definition\Mutations\Models\List\Playlist\CreatePlaylistMutation;
|
||||
use App\GraphQL\Definition\Mutations\Models\List\Playlist\UpdatePlaylistMutation;
|
||||
use App\Models\List\Playlist;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Playlist>
|
||||
*/
|
||||
class PlaylistController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'id';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the index query.
|
||||
*
|
||||
* @param Builder<Playlist> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Playlist>
|
||||
*/
|
||||
public function index(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
$builder->where(Playlist::ATTRIBUTE_VISIBILITY, PlaylistVisibility::PUBLIC->value);
|
||||
|
||||
if ($user = Auth::user()) {
|
||||
return $builder->orWhereBelongsTo($user, Playlist::RELATION_USER);
|
||||
}
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the query builder to the show query.
|
||||
*
|
||||
* @param Builder<Playlist> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Playlist>
|
||||
*/
|
||||
public function show(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
return $builder
|
||||
->whereKey(Arr::get($args, self::ROUTE_SLUG)->getKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource.
|
||||
*
|
||||
* @param null $root
|
||||
* @param array $args
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function store($root, array $args): Playlist
|
||||
{
|
||||
@@ -78,12 +40,12 @@ class PlaylistController extends BaseController
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param null $root
|
||||
* @param array $args
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function update($root, array $args): Playlist
|
||||
{
|
||||
/** @var Playlist $playlist */
|
||||
$playlist = Arr::pull($args, self::ROUTE_SLUG);
|
||||
$playlist = Arr::pull($args, self::MODEL);
|
||||
|
||||
$validated = $this->validated($args, UpdatePlaylistMutation::class);
|
||||
|
||||
@@ -96,17 +58,17 @@ class PlaylistController extends BaseController
|
||||
* Remove the specified resource.
|
||||
*
|
||||
* @param null $root
|
||||
* @param array $args
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function destroy($root, array $args): JsonResponse
|
||||
public function destroy($root, array $args): array
|
||||
{
|
||||
/** @var Playlist $playlist */
|
||||
$playlist = Arr::get($args, self::ROUTE_SLUG);
|
||||
$playlist = Arr::get($args, self::MODEL);
|
||||
|
||||
$message = $this->destroyAction->forceDelete($playlist);
|
||||
|
||||
return new JsonResponse([
|
||||
return [
|
||||
'message' => $message,
|
||||
]);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,36 +4,32 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\List;
|
||||
|
||||
use App\Exceptions\GraphQL\ClientForbiddenException;
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\List\ExternalProfile;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class SyncExternalProfileController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'id';
|
||||
|
||||
/**
|
||||
* Start a new sync job.
|
||||
*
|
||||
* @param null $root
|
||||
* @param array $args
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function store($root, array $args): JsonResponse
|
||||
public function store($root, array $args): array
|
||||
{
|
||||
/** @var ExternalProfile $profile */
|
||||
$profile = Arr::pull($args, self::ROUTE_SLUG);
|
||||
$profile = Arr::pull($args, self::MODEL);
|
||||
|
||||
if (! $profile->canBeSynced()) {
|
||||
return new JsonResponse([
|
||||
'error' => 'This external profile cannot be synced at the moment.',
|
||||
], 403);
|
||||
throw new ClientForbiddenException('This external profile cannot be synced at the moment.');
|
||||
}
|
||||
|
||||
$profile->dispatchSyncJob();
|
||||
|
||||
return new JsonResponse([
|
||||
return [
|
||||
'message' => 'Job dispatched.',
|
||||
], 201);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class LikeController extends BaseController
|
||||
* Store a newly created resource.
|
||||
*
|
||||
* @param null $root
|
||||
* @param array $args
|
||||
* @param array<string, mixed> $args
|
||||
*
|
||||
* @throws ClientValidationException
|
||||
*/
|
||||
@@ -58,7 +58,7 @@ class LikeController extends BaseController
|
||||
* Remove the specified resource.
|
||||
*
|
||||
* @param null $root
|
||||
* @param array $args
|
||||
* @param array<string, mixed> $args
|
||||
*
|
||||
* @throws ClientValidationException
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Wiki\Anime;
|
||||
|
||||
use App\Enums\Models\Wiki\AnimeSeason;
|
||||
use App\Concerns\Actions\GraphQL\FiltersModels;
|
||||
use App\Concerns\Actions\GraphQL\PaginatesModels;
|
||||
use App\Concerns\Actions\GraphQL\SortsModels;
|
||||
use App\Exceptions\GraphQL\ClientValidationException;
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\GraphQL\Definition\Fields\Wiki\Anime\AnimeYear\AnimeYearSeason\AnimeYearSeasonSeasonField;
|
||||
@@ -12,24 +14,29 @@ use App\GraphQL\Definition\Fields\Wiki\Anime\AnimeYear\AnimeYearSeasonField;
|
||||
use App\GraphQL\Definition\Fields\Wiki\Anime\AnimeYear\AnimeYearSeasonsField;
|
||||
use App\GraphQL\Definition\Fields\Wiki\Anime\AnimeYear\AnimeYearYearField;
|
||||
use App\GraphQL\Definition\Queries\Wiki\AnimeYearsQuery;
|
||||
use App\GraphQL\Definition\Types\Wiki\AnimeType;
|
||||
use App\Models\Wiki\Anime;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Contracts\Pagination\Paginator;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Arr;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Anime>
|
||||
*/
|
||||
class AnimeYearsController extends BaseController
|
||||
{
|
||||
use FiltersModels;
|
||||
use PaginatesModels;
|
||||
use SortsModels;
|
||||
|
||||
/**
|
||||
* Apply the builder to the animeyears query.
|
||||
*
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function index(null $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): mixed
|
||||
public function index(null $root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
$year = Arr::get($args, AnimeYearsQuery::ARGUMENT_YEAR);
|
||||
|
||||
@@ -38,7 +45,7 @@ class AnimeYearsController extends BaseController
|
||||
// Restrict 'animes' field to a unique year.
|
||||
if (
|
||||
($year === null || count($year) > 1)
|
||||
&& (Arr::get($fieldSelection, 'season.animes') || Arr::get($fieldSelection, 'seasons.animes'))
|
||||
&& (Arr::get($fieldSelection, 'season.anime') || Arr::get($fieldSelection, 'seasons.anime'))
|
||||
) {
|
||||
throw new ClientValidationException("Please provide a unique 'year' argument to query the animes field.");
|
||||
}
|
||||
@@ -69,13 +76,13 @@ class AnimeYearsController extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the resolver to the AnimeYearSeasonField.
|
||||
* Resolve the AnimeYearSeasonField.
|
||||
*
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function applyFieldToSeasonField(array $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): mixed
|
||||
public function resolveSeasonField(array $root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
$season = AnimeSeason::from(Arr::get($args, AnimeYearSeasonField::ARGUMENT_SEASON));
|
||||
$season = Arr::get($args, AnimeYearSeasonField::ARGUMENT_SEASON);
|
||||
$year = Arr::get($root, AnimeYearsQuery::ARGUMENT_YEAR);
|
||||
|
||||
$seasons = collect(Arr::get($root, 'seasons'));
|
||||
@@ -92,16 +99,22 @@ class AnimeYearsController extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the builder for the AnimeYearSeasonAnimeField.
|
||||
* Resolve the AnimeYearSeasonAnimeField.
|
||||
*/
|
||||
public function applyBuilderToAnimeField(array $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
public function resolveAnimeField(array $root, array $args, $context, ResolveInfo $resolveInfo): Paginator
|
||||
{
|
||||
$season = Arr::get($root, AnimeYearSeasonSeasonField::FIELD);
|
||||
$year = Arr::get($root, 'year');
|
||||
|
||||
return Anime::query()
|
||||
$builder = Anime::query()
|
||||
// season filter applies only on the 'season' field.
|
||||
->when($season !== null, fn (Builder $query) => $query->where(Anime::ATTRIBUTE_SEASON, $season->value))
|
||||
->where(Anime::ATTRIBUTE_YEAR, $year);
|
||||
|
||||
$this->filter($builder, $args, new AnimeType());
|
||||
|
||||
$this->sort($builder, $args, new AnimeType());
|
||||
|
||||
return $this->paginate($builder, $args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ use App\Models\Wiki\Anime;
|
||||
use App\Models\Wiki\ExternalResource;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Anime>
|
||||
@@ -20,14 +18,15 @@ use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
class FindAnimeByExternalSiteController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Apply the query builder to the show query.
|
||||
* Apply the query builder to the index query.
|
||||
*
|
||||
* @param Builder<Anime> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Anime>
|
||||
*/
|
||||
public function show(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
public function index(mixed $root, array $args, $context, $resolveInfo): Builder
|
||||
{
|
||||
$builder = Anime::query();
|
||||
|
||||
$site = Arr::get($args, FindAnimeByExternalSiteQuery::ATTRIBUTE_SITE);
|
||||
$externalId = Arr::get($args, FindAnimeByExternalSiteQuery::ATTRIBUTE_ID);
|
||||
$link = Arr::get($args, FindAnimeByExternalSiteQuery::ATTRIBUTE_LINK);
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Wiki;
|
||||
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\Wiki\Anime;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Anime>
|
||||
*/
|
||||
class AnimeController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'slug';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the show query.
|
||||
*
|
||||
* @param Builder<Anime> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Anime>
|
||||
*/
|
||||
public function show(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
return $builder
|
||||
->whereKey(Arr::get($args, self::ROUTE_SLUG)->getKey());
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Wiki;
|
||||
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\Wiki\Artist;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Artist>
|
||||
*/
|
||||
class ArtistController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'slug';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the show query.
|
||||
*
|
||||
* @param Builder<Artist> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Artist>
|
||||
*/
|
||||
public function show(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
return $builder
|
||||
->whereKey(Arr::get($args, self::ROUTE_SLUG)->getKey());
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Wiki;
|
||||
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\Wiki\Series;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Series>
|
||||
*/
|
||||
class SeriesController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'slug';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the show query.
|
||||
*
|
||||
* @param Builder<Series> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Series>
|
||||
*/
|
||||
public function show(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
return $builder
|
||||
->whereKey(Arr::get($args, self::ROUTE_SLUG)->getKey());
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Controllers\Wiki;
|
||||
|
||||
use App\GraphQL\Controllers\BaseController;
|
||||
use App\Models\Wiki\Studio;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Nuwave\Lighthouse\Execution\ResolveInfo;
|
||||
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
|
||||
|
||||
/**
|
||||
* @extends BaseController<Studio>
|
||||
*/
|
||||
class StudioController extends BaseController
|
||||
{
|
||||
final public const ROUTE_SLUG = 'slug';
|
||||
|
||||
/**
|
||||
* Apply the query builder to the show query.
|
||||
*
|
||||
* @param Builder<Studio> $builder
|
||||
* @param array $args
|
||||
* @return Builder<Studio>
|
||||
*/
|
||||
public function show(Builder $builder, mixed $value, mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder
|
||||
{
|
||||
return $builder
|
||||
->whereKey(Arr::get($args, self::ROUTE_SLUG)->getKey());
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace App\GraphQL\Definition\Fields\Auth\User\Me;
|
||||
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Definition\Fields\StringField;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use App\Models\Auth\User;
|
||||
|
||||
class MeEmailField extends StringField
|
||||
@@ -25,11 +25,11 @@ class MeEmailField extends StringField
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace App\GraphQL\Definition\Fields\Auth\User\Me;
|
||||
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Definition\Fields\DateTimeTzField;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use App\Models\Auth\User;
|
||||
|
||||
class MeEmailVerifiedAtField extends DateTimeTzField
|
||||
@@ -25,11 +25,11 @@ class MeEmailVerifiedAtField extends DateTimeTzField
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace App\GraphQL\Definition\Fields\Auth\User\Me;
|
||||
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Definition\Fields\StringField;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use App\Models\Auth\User;
|
||||
|
||||
class MeNameField extends StringField
|
||||
@@ -25,11 +25,11 @@ class MeNameField extends StringField
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace App\GraphQL\Definition\Fields\Auth\User\Me;
|
||||
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Definition\Fields\DateTimeTzField;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use App\Models\Auth\User;
|
||||
|
||||
class MeTwoFactorConfirmedAtField extends DateTimeTzField
|
||||
@@ -25,11 +25,11 @@ class MeTwoFactorConfirmedAtField extends DateTimeTzField
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -7,12 +7,11 @@ namespace App\GraphQL\Definition\Fields\Base;
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Resolvers\CountAggregateResolver;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
#[UseFieldDirective(CountAggregateResolver::class)]
|
||||
class CountAggregateField extends Field implements DisplayableField, SortableField
|
||||
{
|
||||
public function __construct(
|
||||
@@ -24,25 +23,10 @@ class CountAggregateField extends Field implements DisplayableField, SortableFie
|
||||
parent::__construct($column, $name, $nullable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the directives of the field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function directives(): array
|
||||
{
|
||||
return [
|
||||
'with' => [
|
||||
'relation' => $this->aggregateRelation,
|
||||
],
|
||||
...parent::directives(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
@@ -70,4 +54,14 @@ class CountAggregateField extends Field implements DisplayableField, SortableFie
|
||||
{
|
||||
return $this->aggregateRelation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the field.
|
||||
*
|
||||
* @param Model $root
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return (int) $root->{$this->aggregateRelation}?->value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace App\GraphQL\Definition\Fields\Base;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
class CountField extends Field implements DisplayableField
|
||||
@@ -19,25 +20,10 @@ class CountField extends Field implements DisplayableField
|
||||
parent::__construct($column, $name, $nullable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the directives of the field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function directives(): array
|
||||
{
|
||||
return [
|
||||
'count' => [
|
||||
'relation' => $this->relation,
|
||||
],
|
||||
...parent::directives(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
@@ -49,4 +35,12 @@ class CountField extends Field implements DisplayableField
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the field.
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return $root->{$this->relation}->count();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Definition\Fields\Base;
|
||||
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Definition\Fields\DateTimeTzField;
|
||||
use App\GraphQL\Resolvers\PivotResolver;
|
||||
use App\Models\BaseModel;
|
||||
|
||||
#[UseFieldDirective(PivotResolver::class)]
|
||||
class CreatedAtField extends DateTimeTzField
|
||||
{
|
||||
public function __construct()
|
||||
|
||||
@@ -5,12 +5,11 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Definition\Fields\Base;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Resolvers\ExistsResolver;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
#[UseFieldDirective(ExistsResolver::class)]
|
||||
class ExistsField extends Field implements DisplayableField
|
||||
{
|
||||
public function __construct(
|
||||
@@ -21,25 +20,10 @@ class ExistsField extends Field implements DisplayableField
|
||||
parent::__construct($relation.'Exists', $name, $nullable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the directives of the field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function directives(): array
|
||||
{
|
||||
return [
|
||||
'with' => [
|
||||
'relation' => $this->relation,
|
||||
],
|
||||
...parent::directives(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::boolean();
|
||||
}
|
||||
@@ -51,4 +35,14 @@ class ExistsField extends Field implements DisplayableField
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the field.
|
||||
*
|
||||
* @param Model $root
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return $root->{$this->relation}->isNotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,20 +27,10 @@ class IdField extends IntField implements BindableField
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<Model>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string
|
||||
public function bindResolver(array $args): null
|
||||
{
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string
|
||||
{
|
||||
return $this->column;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Definition\Fields\Base;
|
||||
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Definition\Fields\DateTimeTzField;
|
||||
use App\GraphQL\Resolvers\PivotResolver;
|
||||
use App\Models\BaseModel;
|
||||
|
||||
#[UseFieldDirective(PivotResolver::class)]
|
||||
class UpdatedAtField extends DateTimeTzField
|
||||
{
|
||||
public function __construct()
|
||||
|
||||
@@ -8,8 +8,8 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Support\Directives\Filters\EqFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Filter\EqFilter;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
abstract class BooleanField extends Field implements DisplayableField, FilterableField, SortableField
|
||||
@@ -17,7 +17,7 @@ abstract class BooleanField extends Field implements DisplayableField, Filterabl
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::boolean();
|
||||
}
|
||||
@@ -31,14 +31,14 @@ abstract class BooleanField extends Field implements DisplayableField, Filterabl
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new EqFilterDirective($this),
|
||||
new EqFilter($this),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,54 +4,24 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Definition\Fields;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Support\Directives\Filters\EqFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\GreaterFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\LesserFilterDirective;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Nuwave\Lighthouse\Schema\TypeRegistry;
|
||||
use App\GraphQL\Support\Filter\EqFilter;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use App\GraphQL\Support\Filter\GreaterFilter;
|
||||
use App\GraphQL\Support\Filter\LesserFilter;
|
||||
|
||||
abstract class DateTimeTzField extends Field implements DisplayableField, FilterableField, SortableField
|
||||
abstract class DateTimeTzField extends StringField
|
||||
{
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
{
|
||||
return app(TypeRegistry::class)->get('DateTimeTz');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the field should be displayed to the user.
|
||||
*/
|
||||
public function canBeDisplayed(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new EqFilterDirective($this),
|
||||
new LesserFilterDirective($this),
|
||||
new GreaterFilterDirective($this),
|
||||
new EqFilter($this),
|
||||
new LesserFilter($this),
|
||||
new GreaterFilter($this),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The sort type of the field.
|
||||
*/
|
||||
public function sortType(): SortType
|
||||
{
|
||||
return SortType::ROOT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Definition\Fields\Document\Page;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\BindableField;
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\Contracts\GraphQL\Fields\RequiredOnCreation;
|
||||
use App\Contracts\GraphQL\Fields\UpdatableField;
|
||||
@@ -12,7 +13,7 @@ use App\Models\Document\Page;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class PageSlugField extends StringField implements CreatableField, RequiredOnCreation, UpdatableField
|
||||
class PageSlugField extends StringField implements BindableField, CreatableField, RequiredOnCreation, UpdatableField
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
@@ -27,6 +28,14 @@ class PageSlugField extends StringField implements CreatableField, RequiredOnCre
|
||||
return 'The URL slug & route key of the resource';
|
||||
}
|
||||
|
||||
/**
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindResolver(array $args): null
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the creation validation rules for the field.
|
||||
*
|
||||
|
||||
@@ -8,13 +8,14 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Support\Directives\Filters\EqFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\InFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\NotInFilterDirective;
|
||||
use App\GraphQL\Support\Filter\EqFilter;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use App\GraphQL\Support\Filter\InFilter;
|
||||
use App\GraphQL\Support\Filter\NotInFilter;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Arr;
|
||||
use Nuwave\Lighthouse\Schema\TypeRegistry;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
abstract class EnumField extends Field implements DisplayableField, FilterableField, SortableField
|
||||
{
|
||||
@@ -38,42 +39,30 @@ abstract class EnumField extends Field implements DisplayableField, FilterableFi
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return app(TypeRegistry::class)->get(class_basename($this->enum));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the directives of the field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function directives(): array
|
||||
{
|
||||
return [
|
||||
'enumField' => [],
|
||||
];
|
||||
return GraphQL::type(class_basename($this->enum));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the field.
|
||||
*/
|
||||
public function resolve(mixed $root): mixed
|
||||
public function resolve(mixed $root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return Arr::get($root, $this->column)?->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new EqFilterDirective($this),
|
||||
new InFilterDirective($this),
|
||||
new NotInFilterDirective($this),
|
||||
new EqFilter($this),
|
||||
new InFilter($this),
|
||||
new NotInFilter($this),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -5,19 +5,17 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Definition\Fields;
|
||||
|
||||
use App\Concerns\GraphQL\ResolvesArguments;
|
||||
use App\Concerns\GraphQL\ResolvesAttributes;
|
||||
use App\Concerns\GraphQL\ResolvesDirectives;
|
||||
use App\Contracts\GraphQL\Fields\HasArgumentsField;
|
||||
use App\GraphQL\Definition\Types\BaseType;
|
||||
use App\GraphQL\Support\Argument\Argument;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Stringable;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
abstract class Field implements Stringable
|
||||
abstract class Field
|
||||
{
|
||||
use ResolvesArguments;
|
||||
use ResolvesAttributes;
|
||||
use ResolvesDirectives;
|
||||
|
||||
public function __construct(
|
||||
protected string $column,
|
||||
@@ -53,82 +51,60 @@ abstract class Field implements Stringable
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function getType(): Type
|
||||
public function type(): Type
|
||||
{
|
||||
$baseType = $this->baseType();
|
||||
|
||||
$type = $baseType instanceof BaseType
|
||||
? GraphQL::type($baseType->getName())
|
||||
: $baseType;
|
||||
|
||||
if (! $this->nullable) {
|
||||
return Type::nonNull($this->type());
|
||||
return Type::nonNull($type);
|
||||
}
|
||||
|
||||
return $this->type();
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* The arguments of the type.
|
||||
*
|
||||
* @return Argument[]
|
||||
*/
|
||||
public function arguments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* The args for the field.
|
||||
*
|
||||
* @return array<string, array<string, mixed>>
|
||||
*/
|
||||
public function args(): array
|
||||
{
|
||||
return collect($this->arguments())
|
||||
->mapWithKeys(fn (Argument $argument) => [
|
||||
$argument->name => [
|
||||
'name' => $argument->name,
|
||||
'type' => $argument->getType(),
|
||||
|
||||
...(! is_null($argument->getDefaultValue()) ? ['defaultValue' => $argument->getDefaultValue()] : []),
|
||||
],
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
abstract public function type(): Type;
|
||||
abstract public function baseType(): Type|BaseType;
|
||||
|
||||
/**
|
||||
* Resolve the field.
|
||||
*/
|
||||
public function resolve($root): mixed
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return Arr::get($root, $this->column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the directives of the field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function directives(): array
|
||||
{
|
||||
$deprecated = $this->resolveDeprecatedAttribute();
|
||||
$field = $this->resolveFieldAttribute();
|
||||
$paginate = $this->resolvePaginateAttribute();
|
||||
|
||||
return [
|
||||
...(is_string($deprecated) ? ['deprecated' => ['reason' => $deprecated]] : []),
|
||||
|
||||
...(is_string($field) ? ['field' => ['resolver' => $field]] : []),
|
||||
|
||||
...(is_array($paginate) ? ['paginate' => $paginate] : []),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field as a string representation.
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
$string = Str::of($this->getName());
|
||||
|
||||
if ($this instanceof HasArgumentsField) {
|
||||
$string = $string->append($this->buildArguments($this->arguments()));
|
||||
}
|
||||
|
||||
$string = $string->append(': ')
|
||||
->append($this->getType()->__toString());
|
||||
|
||||
if ($this->shouldRename()) {
|
||||
$string = $string->append(" @rename(attribute: {$this->column})");
|
||||
}
|
||||
|
||||
if (filled($this->directives())) {
|
||||
$string = $string->append(' '.$this->resolveDirectives($this->directives()));
|
||||
}
|
||||
|
||||
return $string->__toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the field is different from the column.
|
||||
*/
|
||||
public function shouldRename(): bool
|
||||
{
|
||||
if (Arr::has($this->directives(), 'field')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getName() !== $this->column;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Support\Directives\Filters\EqFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\GreaterFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\InFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\LesserFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\NotInFilterDirective;
|
||||
use App\GraphQL\Support\Filter\EqFilter;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use App\GraphQL\Support\Filter\GreaterFilter;
|
||||
use App\GraphQL\Support\Filter\InFilter;
|
||||
use App\GraphQL\Support\Filter\LesserFilter;
|
||||
use App\GraphQL\Support\Filter\NotInFilter;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
abstract class FloatField extends Field implements DisplayableField, FilterableField, SortableField
|
||||
@@ -21,7 +21,7 @@ abstract class FloatField extends Field implements DisplayableField, FilterableF
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::float();
|
||||
}
|
||||
@@ -35,18 +35,18 @@ abstract class FloatField extends Field implements DisplayableField, FilterableF
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new EqFilterDirective($this),
|
||||
new InFilterDirective($this),
|
||||
new NotInFilterDirective($this),
|
||||
new LesserFilterDirective($this),
|
||||
new GreaterFilterDirective($this),
|
||||
new EqFilter($this),
|
||||
new InFilter($this),
|
||||
new NotInFilter($this),
|
||||
new LesserFilter($this),
|
||||
new GreaterFilter($this),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Support\Directives\Filters\EqFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\GreaterFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\InFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\LesserFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\NotInFilterDirective;
|
||||
use App\GraphQL\Support\Filter\EqFilter;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use App\GraphQL\Support\Filter\GreaterFilter;
|
||||
use App\GraphQL\Support\Filter\InFilter;
|
||||
use App\GraphQL\Support\Filter\LesserFilter;
|
||||
use App\GraphQL\Support\Filter\NotInFilter;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
abstract class IntField extends Field implements DisplayableField, FilterableField, SortableField
|
||||
@@ -21,7 +21,7 @@ abstract class IntField extends Field implements DisplayableField, FilterableFie
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
@@ -35,18 +35,18 @@ abstract class IntField extends Field implements DisplayableField, FilterableFie
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new EqFilterDirective($this),
|
||||
new InFilterDirective($this),
|
||||
new NotInFilterDirective($this),
|
||||
new LesserFilterDirective($this),
|
||||
new GreaterFilterDirective($this),
|
||||
new EqFilter($this),
|
||||
new InFilter($this),
|
||||
new NotInFilter($this),
|
||||
new LesserFilter($this),
|
||||
new GreaterFilter($this),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -16,20 +16,10 @@ class ExternalProfileIdField extends IdField implements BindableField
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<ExternalProfile>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string
|
||||
public function bindResolver(array $args): null
|
||||
{
|
||||
return ExternalProfile::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string
|
||||
{
|
||||
return $this->column;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,20 +24,10 @@ class PlaylistIdField extends StringField implements BindableField
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<Playlist>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string
|
||||
public function bindResolver(array $args): null
|
||||
{
|
||||
return Playlist::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string
|
||||
{
|
||||
return Playlist::ATTRIBUTE_HASHID;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class PlaylistTrackEntryIdField extends Field implements CreatableField, Require
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
|
||||
@@ -24,20 +24,10 @@ class PlaylistTrackIdField extends StringField implements BindableField
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<PlaylistTrack>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string
|
||||
public function bindResolver(array $args): null
|
||||
{
|
||||
return PlaylistTrack::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string
|
||||
{
|
||||
return PlaylistTrack::ATTRIBUTE_HASHID;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class PlaylistTrackNextField extends Field implements CreatableField, UpdatableF
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::string();
|
||||
}
|
||||
|
||||
+7
-14
@@ -13,6 +13,7 @@ use App\GraphQL\Definition\Fields\Field;
|
||||
use App\Models\List\Playlist;
|
||||
use App\Models\List\Playlist\PlaylistTrack;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class PlaylistTrackPlaylistField extends Field implements BindableField, CreatableField, RequiredOnCreation, RequiredOnUpdate, UpdatableField
|
||||
{
|
||||
@@ -34,27 +35,19 @@ class PlaylistTrackPlaylistField extends Field implements BindableField, Creatab
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::string();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<Playlist>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string
|
||||
public function bindResolver(array $args): Playlist
|
||||
{
|
||||
return Playlist::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string
|
||||
{
|
||||
return Playlist::ATTRIBUTE_HASHID;
|
||||
return Playlist::query()
|
||||
->where(Playlist::ATTRIBUTE_HASHID, Arr::get($args, $this->getName()))
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class PlaylistTrackPreviousField extends Field implements CreatableField, Updata
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::string();
|
||||
}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class PlaylistTrackVideoIdField extends Field implements CreatableField, Require
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Definition\Fields;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
@@ -27,31 +28,17 @@ class LocalizedEnumField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::string();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the directives of the field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function directives(): array
|
||||
{
|
||||
return [
|
||||
'enumField' => [
|
||||
'localize' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the field.
|
||||
*
|
||||
* @param mixed $root
|
||||
*/
|
||||
public function resolve(mixed $root): mixed
|
||||
public function resolve(mixed $root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return Arr::get($root, $this->column)?->localize();
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ namespace App\GraphQL\Definition\Fields\Pivot\Base;
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\EloquentType;
|
||||
use GraphQL\Type\Definition\ObjectType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Str;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class NodeField extends Field implements DisplayableField
|
||||
{
|
||||
@@ -25,14 +25,13 @@ class NodeField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
$type = Str::of(class_basename($this->nodeType))
|
||||
->remove('Type')
|
||||
->__toString();
|
||||
|
||||
// Necessary to prevent memory leak at compile time.
|
||||
return new ObjectType(['name' => $type, 'fields' => []]);
|
||||
return Type::nonNull(GraphQL::type($type));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,12 +6,9 @@ namespace App\GraphQL\Definition\Fields\Pivot\Wiki\AnimeResource;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\Contracts\GraphQL\Fields\UpdatableField;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Definition\Fields\StringField;
|
||||
use App\GraphQL\Resolvers\PivotResolver;
|
||||
use App\Pivots\Wiki\AnimeResource;
|
||||
|
||||
#[UseFieldDirective(PivotResolver::class)]
|
||||
class AnimeResourceAsField extends StringField implements CreatableField, UpdatableField
|
||||
{
|
||||
public function __construct()
|
||||
|
||||
@@ -6,12 +6,9 @@ namespace App\GraphQL\Definition\Fields\Pivot\Wiki\ArtistImage;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\Contracts\GraphQL\Fields\UpdatableField;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Definition\Fields\IntField;
|
||||
use App\GraphQL\Resolvers\PivotResolver;
|
||||
use App\Pivots\Wiki\ArtistImage;
|
||||
|
||||
#[UseFieldDirective(PivotResolver::class)]
|
||||
class ArtistImageDepthField extends IntField implements CreatableField, UpdatableField
|
||||
{
|
||||
public function __construct()
|
||||
|
||||
@@ -6,12 +6,9 @@ namespace App\GraphQL\Definition\Fields\Pivot\Wiki\ArtistMember;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\Contracts\GraphQL\Fields\UpdatableField;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Definition\Fields\StringField;
|
||||
use App\GraphQL\Resolvers\PivotResolver;
|
||||
use App\Pivots\Wiki\ArtistMember;
|
||||
|
||||
#[UseFieldDirective(PivotResolver::class)]
|
||||
class ArtistMemberAliasField extends StringField implements CreatableField, UpdatableField
|
||||
{
|
||||
public function __construct()
|
||||
|
||||
@@ -6,12 +6,9 @@ namespace App\GraphQL\Definition\Fields\Pivot\Wiki\ArtistMember;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\Contracts\GraphQL\Fields\UpdatableField;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Definition\Fields\StringField;
|
||||
use App\GraphQL\Resolvers\PivotResolver;
|
||||
use App\Pivots\Wiki\ArtistMember;
|
||||
|
||||
#[UseFieldDirective(PivotResolver::class)]
|
||||
class ArtistMemberAsField extends StringField implements CreatableField, UpdatableField
|
||||
{
|
||||
public function __construct()
|
||||
|
||||
@@ -6,12 +6,9 @@ namespace App\GraphQL\Definition\Fields\Pivot\Wiki\ArtistMember;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\Contracts\GraphQL\Fields\UpdatableField;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Definition\Fields\StringField;
|
||||
use App\GraphQL\Resolvers\PivotResolver;
|
||||
use App\Pivots\Wiki\ArtistMember;
|
||||
|
||||
#[UseFieldDirective(PivotResolver::class)]
|
||||
class ArtistMemberNotesField extends StringField implements CreatableField, UpdatableField
|
||||
{
|
||||
public function __construct()
|
||||
|
||||
@@ -6,12 +6,9 @@ namespace App\GraphQL\Definition\Fields\Pivot\Wiki\ArtistResource;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\CreatableField;
|
||||
use App\Contracts\GraphQL\Fields\UpdatableField;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Definition\Fields\StringField;
|
||||
use App\GraphQL\Resolvers\PivotResolver;
|
||||
use App\Pivots\Wiki\ArtistResource;
|
||||
|
||||
#[UseFieldDirective(PivotResolver::class)]
|
||||
class ArtistResourceAsField extends StringField implements CreatableField, UpdatableField
|
||||
{
|
||||
public function __construct()
|
||||
|
||||
@@ -12,13 +12,13 @@ class MessageResponseField extends Field implements DisplayableField
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('message');
|
||||
parent::__construct('message', nullable: false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::string();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\Wiki\AnimeType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class SearchAnimeField extends Field implements DisplayableField
|
||||
{
|
||||
@@ -27,9 +28,9 @@ class SearchAnimeField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::listOf(Type::nonNull(new AnimeType()));
|
||||
return Type::listOf(Type::nonNull(GraphQL::type(new AnimeType()->getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\Wiki\Anime\AnimeThemeType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class SearchAnimeThemesField extends Field implements DisplayableField
|
||||
{
|
||||
@@ -27,9 +28,9 @@ class SearchAnimeThemesField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::listOf(Type::nonNull(new AnimeThemeType()));
|
||||
return Type::listOf(Type::nonNull(GraphQL::type(new AnimeThemeType()->getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\Wiki\ArtistType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class SearchArtistsField extends Field implements DisplayableField
|
||||
{
|
||||
@@ -27,9 +28,9 @@ class SearchArtistsField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::listOf(Type::nonNull(new ArtistType()));
|
||||
return Type::listOf(Type::nonNull(GraphQL::type(new ArtistType()->getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\List\PlaylistType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class SearchPlaylistsField extends Field implements DisplayableField
|
||||
{
|
||||
@@ -27,9 +28,9 @@ class SearchPlaylistsField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::listOf(Type::nonNull(new PlaylistType()));
|
||||
return Type::listOf(Type::nonNull(GraphQL::type(new PlaylistType()->getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\Wiki\SeriesType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class SearchSeriesField extends Field implements DisplayableField
|
||||
{
|
||||
@@ -27,9 +28,9 @@ class SearchSeriesField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::listOf(Type::nonNull(new SeriesType()));
|
||||
return Type::listOf(Type::nonNull(GraphQL::type(new SeriesType()->getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\Wiki\SongType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class SearchSongsField extends Field implements DisplayableField
|
||||
{
|
||||
@@ -27,9 +28,9 @@ class SearchSongsField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::listOf(Type::nonNull(new SongType()));
|
||||
return Type::listOf(Type::nonNull(GraphQL::type(new SongType()->getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\Wiki\StudioType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class SearchStudiosField extends Field implements DisplayableField
|
||||
{
|
||||
@@ -27,9 +28,9 @@ class SearchStudiosField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::listOf(Type::nonNull(new StudioType()));
|
||||
return Type::listOf(Type::nonNull(GraphQL::type(new StudioType()->getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\Wiki\VideoType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class SearchVideosField extends Field implements DisplayableField
|
||||
{
|
||||
@@ -27,9 +28,9 @@ class SearchVideosField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::listOf(Type::nonNull(new VideoType()));
|
||||
return Type::listOf(Type::nonNull(GraphQL::type(new VideoType()->getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,9 +8,9 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Support\Directives\Filters\EqFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\LikeFilterDirective;
|
||||
use App\GraphQL\Support\Filter\EqFilter;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use App\GraphQL\Support\Filter\LikeFilter;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
abstract class StringField extends Field implements DisplayableField, FilterableField, SortableField
|
||||
@@ -18,7 +18,7 @@ abstract class StringField extends Field implements DisplayableField, Filterable
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::string();
|
||||
}
|
||||
@@ -32,15 +32,15 @@ abstract class StringField extends Field implements DisplayableField, Filterable
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new EqFilterDirective($this),
|
||||
new LikeFilterDirective($this),
|
||||
new EqFilter($this),
|
||||
new LikeFilter($this),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use App\GraphQL\Controllers\User\LikeController;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\Models\List\Playlist;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class LikePlaylistField extends Field implements BindableField, CreatableField, DeletableField
|
||||
@@ -31,27 +32,19 @@ class LikePlaylistField extends Field implements BindableField, CreatableField,
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::string();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<Playlist>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string
|
||||
public function bindResolver(array $args): Playlist
|
||||
{
|
||||
return Playlist::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string
|
||||
{
|
||||
return Playlist::ATTRIBUTE_HASHID;
|
||||
return Playlist::query()
|
||||
->where(Playlist::ATTRIBUTE_HASHID, Arr::get($args, $this->getName()))
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,6 +11,7 @@ use App\GraphQL\Controllers\User\LikeController;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\Models\Wiki\Video;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class LikeVideoField extends Field implements BindableField, CreatableField, DeletableField
|
||||
@@ -31,27 +32,19 @@ class LikeVideoField extends Field implements BindableField, CreatableField, Del
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<Video>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string
|
||||
public function bindResolver(array $args): Video
|
||||
{
|
||||
return Video::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string
|
||||
{
|
||||
return Video::ATTRIBUTE_ID;
|
||||
return Video::query()
|
||||
->where(Video::ATTRIBUTE_ID, Arr::get($args, $this->getName()))
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@ class NotificationDataField extends JsonField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): NotificationDataType
|
||||
{
|
||||
return new NotificationDataType();
|
||||
}
|
||||
|
||||
@@ -29,21 +29,11 @@ class AnimeSlugField extends StringField implements BindableField, CreatableFiel
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<Anime>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string
|
||||
public function bindResolver(array $args): null
|
||||
{
|
||||
return Anime::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string
|
||||
{
|
||||
return $this->column;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+22
-3
@@ -6,15 +6,17 @@ namespace App\GraphQL\Definition\Fields\Wiki\Anime\AnimeYear\AnimeYearSeason;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\HasArgumentsField;
|
||||
use App\GraphQL\Attributes\Resolvers\UsePaginateDirective;
|
||||
use App\GraphQL\Controllers\Wiki\Anime\AnimeYearsController;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Queries\Models\Paginator\Wiki\AnimePaginatorQuery;
|
||||
use App\GraphQL\Definition\Types\Wiki\AnimeType;
|
||||
use App\GraphQL\Support\Argument\Argument;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Contracts\Pagination\Paginator;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
#[UsePaginateDirective(true, AnimeYearsController::class.'@applyBuilderToAnimeField')]
|
||||
class AnimeYearSeasonAnimeField extends Field implements DisplayableField, HasArgumentsField
|
||||
{
|
||||
final public const FIELD = 'anime';
|
||||
@@ -35,11 +37,19 @@ class AnimeYearSeasonAnimeField extends Field implements DisplayableField, HasAr
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): AnimeType
|
||||
{
|
||||
return new AnimeType();
|
||||
}
|
||||
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
{
|
||||
return Type::nonNull(GraphQL::paginate($this->baseType()->getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the field should be displayed to the user.
|
||||
*/
|
||||
@@ -57,4 +67,13 @@ class AnimeYearSeasonAnimeField extends Field implements DisplayableField, HasAr
|
||||
{
|
||||
return new AnimePaginatorQuery()->arguments();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Paginator
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return App::make(AnimeYearsController::class)
|
||||
->resolveAnimeField($root, $args, $context, $resolveInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,15 @@ namespace App\GraphQL\Definition\Fields\Wiki\Anime\AnimeYear;
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\HasArgumentsField;
|
||||
use App\Enums\Models\Wiki\AnimeSeason;
|
||||
use App\GraphQL\Attributes\Resolvers\UseFieldDirective;
|
||||
use App\GraphQL\Controllers\Wiki\Anime\AnimeYearsController;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\Wiki\Anime\AnimeYear\AnimeYearSeasonType;
|
||||
use App\GraphQL\Support\Argument\Argument;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Nuwave\Lighthouse\Schema\TypeRegistry;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
#[UseFieldDirective(AnimeYearsController::class, 'applyFieldToSeasonField')]
|
||||
class AnimeYearSeasonField extends Field implements DisplayableField, HasArgumentsField
|
||||
{
|
||||
final public const FIELD = 'season';
|
||||
@@ -37,7 +37,7 @@ class AnimeYearSeasonField extends Field implements DisplayableField, HasArgumen
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): AnimeYearSeasonType
|
||||
{
|
||||
return new AnimeYearSeasonType();
|
||||
}
|
||||
@@ -57,10 +57,20 @@ class AnimeYearSeasonField extends Field implements DisplayableField, HasArgumen
|
||||
*/
|
||||
public function arguments(): array
|
||||
{
|
||||
$season = app(TypeRegistry::class)->get(class_basename(AnimeSeason::class));
|
||||
$season = GraphQL::type(class_basename(AnimeSeason::class));
|
||||
|
||||
return [
|
||||
new Argument(self::ARGUMENT_SEASON, Type::nonNull($season)),
|
||||
new Argument(self::ARGUMENT_SEASON, $season)
|
||||
->required(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return App::make(AnimeYearsController::class)
|
||||
->resolveSeasonField($root, $args, $context, $resolveInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Definition\Fields\Field;
|
||||
use App\GraphQL\Definition\Types\Wiki\Anime\AnimeYear\AnimeYearSeasonsType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
class AnimeYearSeasonsField extends Field implements DisplayableField
|
||||
{
|
||||
@@ -29,9 +30,11 @@ class AnimeYearSeasonsField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::listOf(Type::nonNull(new AnimeYearSeasonsType()));
|
||||
$type = GraphQL::type(new AnimeYearSeasonsType()->getName());
|
||||
|
||||
return Type::listOf(Type::nonNull($type));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ class AnimeYearYearField extends Field implements DisplayableField
|
||||
/**
|
||||
* The type returned by the field.
|
||||
*/
|
||||
public function type(): Type
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ use App\Contracts\GraphQL\Fields\RequiredOnCreation;
|
||||
use App\Contracts\GraphQL\Fields\UpdatableField;
|
||||
use App\Enums\Models\Wiki\ThemeType;
|
||||
use App\GraphQL\Definition\Fields\EnumField;
|
||||
use App\GraphQL\Support\Directives\Filters\EqFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\FilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\InFilterDirective;
|
||||
use App\GraphQL\Support\Directives\Filters\NotInFilterDirective;
|
||||
use App\GraphQL\Support\Filter\EqFilter;
|
||||
use App\GraphQL\Support\Filter\Filter;
|
||||
use App\GraphQL\Support\Filter\InFilter;
|
||||
use App\GraphQL\Support\Filter\NotInFilter;
|
||||
use App\Models\Wiki\Anime\AnimeTheme;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
|
||||
@@ -32,16 +32,16 @@ class AnimeThemeTypeField extends EnumField implements CreatableField, RequiredO
|
||||
}
|
||||
|
||||
/**
|
||||
* The directives available for this filter.
|
||||
* The filters of the field.
|
||||
*
|
||||
* @return FilterDirective[]
|
||||
* @return Filter[]
|
||||
*/
|
||||
public function filterDirectives(): array
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new EqFilterDirective($this),
|
||||
new InFilterDirective($this, '[OP, ED]'),
|
||||
new NotInFilterDirective($this),
|
||||
new EqFilter($this),
|
||||
new InFilter($this, [ThemeType::OP->value, ThemeType::ED->value]),
|
||||
new NotInFilter($this),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -29,21 +29,11 @@ class ArtistSlugField extends StringField implements BindableField, CreatableFie
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<Artist>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string
|
||||
public function bindResolver(array $args): null
|
||||
{
|
||||
return Artist::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string
|
||||
{
|
||||
return $this->column;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,12 +4,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Definition\Fields\Wiki\Audio;
|
||||
|
||||
use App\GraphQL\Attributes\Deprecated;
|
||||
use App\Contracts\GraphQL\Fields\DeprecatedField;
|
||||
use App\GraphQL\Definition\Fields\Base\CountAggregateField;
|
||||
use App\Models\Wiki\Audio;
|
||||
|
||||
#[Deprecated('We will no longer track views.')]
|
||||
class AudioViewsCountField extends CountAggregateField
|
||||
class AudioViewsCountField extends CountAggregateField implements DeprecatedField
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
@@ -23,4 +22,12 @@ class AudioViewsCountField extends CountAggregateField
|
||||
{
|
||||
return 'The number of views recorded for the resource';
|
||||
}
|
||||
|
||||
/**
|
||||
* The reason which the field is deprecated.
|
||||
*/
|
||||
public function deprecationReason(): string
|
||||
{
|
||||
return 'We will no longer track views.';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,21 +29,11 @@ class SeriesSlugField extends StringField implements BindableField, CreatableFie
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model that the field should bind to.
|
||||
*
|
||||
* @return class-string<Series>
|
||||
* The resolver to cast the model.
|
||||
*/
|
||||
public function bindTo(): string
|
||||
public function bindResolver(array $args): null
|
||||
{
|
||||
return Series::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column that the field should use to bind.
|
||||
*/
|
||||
public function bindUsingColumn(): string
|
||||
{
|
||||
return $this->column;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user