mirror of
https://github.com/AnimeThemes/animethemes-server.git
synced 2026-07-11 01:24:46 +02:00
feat(graphql): aggregates (#1061)
This commit is contained in:
@@ -5,9 +5,9 @@ declare(strict_types=1);
|
||||
namespace App\Actions\GraphQL;
|
||||
|
||||
use App\Concerns\Actions\GraphQL\ConstrainsEagerLoads;
|
||||
use App\Concerns\Actions\GraphQL\FieldSelection;
|
||||
use App\Concerns\Actions\GraphQL\PaginatesModels;
|
||||
use App\Concerns\Actions\GraphQL\SortsModels;
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Argument\SortArgument;
|
||||
use App\GraphQL\Criteria\Sort\RelationSortCriteria;
|
||||
use App\GraphQL\Criteria\Sort\SortCriteria;
|
||||
@@ -26,11 +26,14 @@ use Illuminate\Support\Facades\Validator;
|
||||
class IndexAction
|
||||
{
|
||||
use ConstrainsEagerLoads;
|
||||
use FieldSelection;
|
||||
use PaginatesModels;
|
||||
use SortsModels;
|
||||
|
||||
public function index(Builder $builder, array $args, BaseType $type, ResolveInfo $resolveInfo): Paginator
|
||||
{
|
||||
$this->withAggregates($builder, $args, $this->getSelection($resolveInfo), $type);
|
||||
|
||||
$this->filter($builder, $args, $type);
|
||||
|
||||
$this->sort($builder, $args, $type);
|
||||
@@ -46,6 +49,8 @@ class IndexAction
|
||||
|
||||
$searchBuilder = Search::search($builder->getModel(), $criteria)
|
||||
->passToEloquentBuilder(function (Builder $builder) use ($args, $type, $resolveInfo): void {
|
||||
$this->withAggregates($builder, $args, $this->getSelection($resolveInfo), $type);
|
||||
|
||||
$this->filter($builder, $args, $type);
|
||||
|
||||
$this->sort($builder, $args, $type);
|
||||
@@ -81,22 +86,19 @@ class IndexAction
|
||||
|
||||
$column = $criterion->getField()->getColumn();
|
||||
$direction = $criterion->getDirection();
|
||||
$sortType = $criterion->getField()->sortType();
|
||||
$isString = $criterion->getField() instanceof StringField;
|
||||
|
||||
if ($sortType === SortType::ROOT) {
|
||||
$sortsRaw[$column] = [
|
||||
'direction' => $direction,
|
||||
'isString' => $isString,
|
||||
];
|
||||
}
|
||||
|
||||
if ($criterion instanceof RelationSortCriteria) {
|
||||
$sortsRaw[$column] = [
|
||||
'direction' => $direction->value,
|
||||
'isString' => $isString,
|
||||
'relation' => $criterion->relation,
|
||||
];
|
||||
} else {
|
||||
$sortsRaw[$column] = [
|
||||
'direction' => $direction,
|
||||
'isString' => $isString,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ class ShowAction
|
||||
|
||||
public function show(Builder $builder, array $args, BaseType $type, ResolveInfo $resolveInfo): Model
|
||||
{
|
||||
$this->withAggregates($builder, $args, $this->getSelection($resolveInfo), $type);
|
||||
|
||||
$this->filter($builder, $args, $type);
|
||||
|
||||
$this->constrainEagerLoads($builder, $resolveInfo, $type);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Concerns\Actions\GraphQL;
|
||||
|
||||
use App\GraphQL\Schema\Fields\Base\Aggregate\AggregateField;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Types\BaseType;
|
||||
use App\GraphQL\Schema\Unions\BaseUnion;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
trait AggregatesFields
|
||||
{
|
||||
public function withAggregates(Builder $builder, array $args, array $selection, BaseType|BaseUnion $type): Builder
|
||||
{
|
||||
if ($type instanceof BaseUnion) {
|
||||
return $builder;
|
||||
}
|
||||
|
||||
collect($type->fieldClasses())
|
||||
->filter(fn (Field $field): bool => $field instanceof AggregateField && $field->shouldAggregate($args, $selection, $type))
|
||||
->each(fn (AggregateField $selectedAggregate): Builder => $selectedAggregate->with($builder));
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
public function loadAggregates(Model $model, array $args, array $selection, BaseType|BaseUnion $type): Model
|
||||
{
|
||||
if ($type instanceof BaseUnion) {
|
||||
return $model;
|
||||
}
|
||||
|
||||
collect($type->fieldClasses())
|
||||
->filter(fn (Field $field): bool => $field instanceof AggregateField && $field->shouldAggregate($args, $selection, $type))
|
||||
->each(fn (AggregateField $selectedAggregate): Model => $selectedAggregate->load($model));
|
||||
|
||||
return $model;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Concerns\Actions\GraphQL;
|
||||
|
||||
use App\GraphQL\ResolveInfo as CustomResolveInfo;
|
||||
use App\GraphQL\Schema\Relations\Relation;
|
||||
use App\GraphQL\Schema\Types\BaseType;
|
||||
use App\GraphQL\Schema\Types\EloquentType;
|
||||
@@ -17,6 +16,8 @@ use Illuminate\Support\Arr;
|
||||
|
||||
trait ConstrainsEagerLoads
|
||||
{
|
||||
use AggregatesFields;
|
||||
use FieldSelection;
|
||||
use FiltersModels;
|
||||
use SortsModels;
|
||||
|
||||
@@ -25,12 +26,7 @@ trait ConstrainsEagerLoads
|
||||
*/
|
||||
protected function constrainEagerLoads(Builder $query, ResolveInfo $resolveInfo, BaseType $type, string $fieldName = 'data'): void
|
||||
{
|
||||
$resolveInfo = new CustomResolveInfo($resolveInfo);
|
||||
|
||||
$selection = Arr::get($resolveInfo->getFieldSelectionWithAliases(100), "{$fieldName}.{$fieldName}.selectionSet")
|
||||
?? $resolveInfo->getFieldSelectionWithAliases(100);
|
||||
|
||||
$this->processEagerLoadForType($query, $selection, $type);
|
||||
$this->processEagerLoadForType($query, $this->getSelection($resolveInfo, $fieldName), $type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,6 +112,8 @@ trait ConstrainsEagerLoads
|
||||
|
||||
$args = Arr::get($selection, 'args');
|
||||
|
||||
$this->withAggregates($builder, $args, $selection, $type);
|
||||
|
||||
$this->filter($builder, $args, $type);
|
||||
|
||||
$this->sort($builder, $args, $type, $relation, $graphqlRelation);
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Concerns\Actions\GraphQL;
|
||||
|
||||
use App\GraphQL\ResolveInfo as GraphQLResolveInfo;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait FieldSelection
|
||||
{
|
||||
protected function getSelection(ResolveInfo $resolveInfo, string $fieldName = 'data'): array
|
||||
{
|
||||
$resolveInfo = new GraphQLResolveInfo($resolveInfo);
|
||||
|
||||
return Arr::get($resolveInfo->getFieldSelectionWithAliases(100), "{$fieldName}.{$fieldName}.selectionSet")
|
||||
?? $resolveInfo->getFieldSelectionWithAliases(100);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Contracts\GraphQL\Fields;
|
||||
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Criteria\Sort\Sort;
|
||||
|
||||
interface SortableField
|
||||
{
|
||||
public function sortType(): SortType;
|
||||
public function getSort(): Sort;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enums\GraphQL\Field;
|
||||
|
||||
enum AggregateFunction: string
|
||||
{
|
||||
case AVG = 'avg';
|
||||
case COUNT = 'count';
|
||||
case EXISTS = 'exists';
|
||||
case MAX = 'max';
|
||||
case MIN = 'min';
|
||||
case SUM = 'sum';
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enums\GraphQL\Filter;
|
||||
|
||||
enum Clause
|
||||
{
|
||||
case WHERE;
|
||||
case HAVING;
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enums\GraphQL;
|
||||
namespace App\Enums\GraphQL\Filter;
|
||||
|
||||
use App\Concerns\Enums\CoercesInstances;
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enums\GraphQL;
|
||||
namespace App\Enums\GraphQL\Filter;
|
||||
|
||||
use App\Concerns\Enums\CoercesInstances;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enums\GraphQL;
|
||||
namespace App\Enums\GraphQL\Filter;
|
||||
|
||||
use GraphQL\Type\Definition\Description;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enums\GraphQL;
|
||||
|
||||
enum QualifyColumn
|
||||
{
|
||||
case YES;
|
||||
case NO;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enums\GraphQL;
|
||||
namespace App\Enums\GraphQL\Sort;
|
||||
|
||||
enum SortDirection: string
|
||||
{
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enums\GraphQL;
|
||||
|
||||
enum SortType: int
|
||||
{
|
||||
case NONE = 0;
|
||||
case ROOT = 1;
|
||||
case AGGREGATE = 2;
|
||||
case RELATION = 3;
|
||||
case COUNT_RELATION = 4;
|
||||
}
|
||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Criteria\Filter;
|
||||
|
||||
use App\Enums\GraphQL\TrashedFilter;
|
||||
use App\Enums\GraphQL\Filter\TrashedFilter;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class TrashedFilterCriteria extends FilterCriteria
|
||||
|
||||
@@ -6,11 +6,11 @@ namespace App\GraphQL\Criteria\Filter;
|
||||
|
||||
use App\Concerns\Actions\GraphQL\FiltersModels;
|
||||
use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Enums\GraphQL\ComparisonOperator;
|
||||
use App\Enums\GraphQL\LogicalOperator;
|
||||
use App\Enums\GraphQL\Filter\Clause;
|
||||
use App\Enums\GraphQL\Filter\ComparisonOperator;
|
||||
use App\Enums\GraphQL\Filter\LogicalOperator;
|
||||
use App\GraphQL\Filter\Filter;
|
||||
use App\GraphQL\Schema\Enums\FilterableColumns;
|
||||
use App\GraphQL\Schema\Fields\Base\CountField;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Types\EloquentType;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
@@ -64,22 +64,20 @@ class WhereConditionsFilterCriteria extends FilterCriteria
|
||||
if (filled($fieldName) && filled($value)) {
|
||||
$field = $this->filterableFields->get($fieldName);
|
||||
|
||||
if ($field instanceof CountField) {
|
||||
$builder->withCount(Str::replace('Count', '', $field->getName()));
|
||||
$builder->having(
|
||||
Str::snake($field->getColumn()),
|
||||
ComparisonOperator::unstrictCoerce(Arr::get($where, 'operator'))->value,
|
||||
Arr::first($field->getFilter()->getFilterValues(Arr::wrap($value))),
|
||||
$logical->value
|
||||
);
|
||||
} else {
|
||||
$builder->where(
|
||||
match ($field->getFilter()->getClause()) {
|
||||
Clause::WHERE => $builder->where(
|
||||
$field->getColumn(),
|
||||
ComparisonOperator::unstrictCoerce(Arr::get($where, 'operator'))->value,
|
||||
Arr::first($field->getFilter()->getFilterValues(Arr::wrap($value))),
|
||||
$logical->value
|
||||
);
|
||||
}
|
||||
),
|
||||
Clause::HAVING => $builder->having(
|
||||
Str::snake($field->getColumn()),
|
||||
ComparisonOperator::unstrictCoerce(Arr::get($where, 'operator'))->value,
|
||||
Arr::first($field->getFilter()->getFilterValues(Arr::wrap($value))),
|
||||
$logical->value
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
$builder->where(function (Builder $builder) use ($where): void {
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Criteria\Sort;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class AggregateSortCriteria extends SortCriteria
|
||||
{
|
||||
/**
|
||||
* Apply the ordering to the current Eloquent builder.
|
||||
*/
|
||||
public function sort(Builder $builder): Builder
|
||||
{
|
||||
try {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$relation = $this->field->{'relation'}();
|
||||
} catch (Exception) {
|
||||
throw new Exception("'relation' method is required for the aggregate sort type.");
|
||||
}
|
||||
|
||||
$builder->withAggregate([
|
||||
"$relation as {$relation}_value" => function ($query): void {
|
||||
$query->orderBy('value', $this->direction->value);
|
||||
},
|
||||
], 'value');
|
||||
|
||||
return $builder->orderBy("{$relation}_value", $this->direction->value);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Criteria\Sort;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class CountSortCriteria extends SortCriteria
|
||||
{
|
||||
/**
|
||||
* Apply the ordering to the current Eloquent builder.
|
||||
*/
|
||||
public function sort(Builder $builder): Builder
|
||||
{
|
||||
try {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$relation = $this->field->{'relation'}();
|
||||
} catch (Exception) {
|
||||
throw new Exception("'relation' method is required for the aggregate sort type");
|
||||
}
|
||||
|
||||
return $builder->withCount($relation)->orderBy("{$relation}_count", $this->direction->value);
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,12 @@ class FieldSortCriteria extends SortCriteria
|
||||
*/
|
||||
public function sort(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orderBy(
|
||||
$builder->qualifyColumn($this->field->getColumn()),
|
||||
$this->direction->value
|
||||
);
|
||||
$sort = $this->field->getSort();
|
||||
|
||||
$column = $sort->shouldQualifyColumn()
|
||||
? $builder->qualifyColumn($sort->getColumn())
|
||||
: $sort->getColumn();
|
||||
|
||||
return $builder->orderBy($column, $this->direction->value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Criteria\Sort;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortDirection;
|
||||
use App\Enums\GraphQL\Sort\SortDirection;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
@@ -44,9 +44,10 @@ class PivotSortCriteria extends SortCriteria
|
||||
*/
|
||||
public function sort(Builder $builder): Builder
|
||||
{
|
||||
return $builder->orderBy(
|
||||
$this->relation?->qualifyPivotColumn($this->field->getColumn()),
|
||||
$this->direction->value
|
||||
);
|
||||
$column = $this->field->getSort()->shouldQualifyColumn()
|
||||
? $this->relation?->qualifyPivotColumn($this->field->getColumn())
|
||||
: $this->field->getColumn();
|
||||
|
||||
return $builder->orderBy($column, $this->direction->value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Criteria\Sort;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortDirection;
|
||||
use App\Enums\GraphQL\Sort\SortDirection;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Str;
|
||||
@@ -46,12 +46,6 @@ class RelationSortCriteria extends SortCriteria
|
||||
{
|
||||
$column = $this->field->getColumn();
|
||||
|
||||
$builder->withAggregate([
|
||||
"{$this->relation} as {$this->relation}_$column" => function ($query) use ($column): void {
|
||||
$query->orderBy($column, $this->direction->value);
|
||||
},
|
||||
], $column);
|
||||
|
||||
return $builder->orderBy("{$this->relation}_$column", $this->direction->value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Criteria\Sort;
|
||||
|
||||
use App\Enums\GraphQL\QualifyColumn;
|
||||
|
||||
class Sort
|
||||
{
|
||||
public function __construct(
|
||||
protected readonly string $key,
|
||||
protected readonly ?string $column = null,
|
||||
protected readonly QualifyColumn $qualifyColumn = QualifyColumn::YES
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Get sort key value.
|
||||
*/
|
||||
public function getKey(): string
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sort column.
|
||||
*/
|
||||
public function getColumn(): string
|
||||
{
|
||||
return $this->column ?? $this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the column should be qualified for the sort.
|
||||
*/
|
||||
public function shouldQualifyColumn(): bool
|
||||
{
|
||||
return $this->qualifyColumn === QualifyColumn::YES;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Criteria\Sort;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortDirection;
|
||||
use App\Enums\GraphQL\Sort\SortDirection;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Filter;
|
||||
|
||||
use App\Enums\GraphQL\Filter\Clause;
|
||||
use App\Enums\Http\Api\Filter\ComparisonOperator;
|
||||
use App\GraphQL\Argument\Argument;
|
||||
use App\GraphQL\Argument\FilterArgument;
|
||||
@@ -20,6 +21,7 @@ abstract class Filter
|
||||
public function __construct(
|
||||
protected readonly string $fieldName,
|
||||
protected readonly ?string $column = null,
|
||||
protected readonly Clause $clause = Clause::WHERE,
|
||||
) {}
|
||||
|
||||
public function getFieldName(): string
|
||||
@@ -32,6 +34,11 @@ abstract class Filter
|
||||
return $this->column ?? $this->getFieldName();
|
||||
}
|
||||
|
||||
public function getClause(): Clause
|
||||
{
|
||||
return $this->clause;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Argument[]
|
||||
*/
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Filter;
|
||||
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class RelationFilter extends Filter
|
||||
{
|
||||
public function getBaseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert filter values if needed. By default, no conversion is needed.
|
||||
*/
|
||||
protected function convertFilterValues(array $filterValues): array
|
||||
{
|
||||
return Arr::map(
|
||||
$filterValues,
|
||||
fn (string $filterValue): ?int => filter_var($filterValue, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules for the filter.
|
||||
*/
|
||||
protected function getRules(): array
|
||||
{
|
||||
return [
|
||||
'required',
|
||||
'integer',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Filter;
|
||||
|
||||
use App\Enums\GraphQL\TrashedFilter as TrashedFilterEnum;
|
||||
use App\Enums\GraphQL\Filter\TrashedFilter as TrashedFilterEnum;
|
||||
use App\GraphQL\Argument\Argument;
|
||||
use Rebing\GraphQL\Support\Facades\GraphQL;
|
||||
|
||||
|
||||
@@ -5,10 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Schema\Enums;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortDirection;
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Criteria\Sort\AggregateSortCriteria;
|
||||
use App\GraphQL\Criteria\Sort\CountSortCriteria;
|
||||
use App\Enums\GraphQL\Sort\SortDirection;
|
||||
use App\GraphQL\Criteria\Sort\FieldSortCriteria;
|
||||
use App\GraphQL\Criteria\Sort\PivotSortCriteria;
|
||||
use App\GraphQL\Criteria\Sort\RandomSortCriteria;
|
||||
@@ -65,8 +62,6 @@ class SortableColumns extends EnumType
|
||||
{
|
||||
return $this->getFieldSortCriteria()
|
||||
->merge($this->getPivotSortCriteria())
|
||||
->merge($this->getCountSortCriteria())
|
||||
->merge($this->getAggregateSortCriteria())
|
||||
->merge($this->getRelationSortCriteria())
|
||||
->push(new RandomSortCriteria());
|
||||
}
|
||||
@@ -74,7 +69,6 @@ class SortableColumns extends EnumType
|
||||
private function getFieldSortCriteria(): Collection
|
||||
{
|
||||
return $this->getSortableFields()
|
||||
->filter(fn (Field $field): bool => $field->sortType() === SortType::ROOT)
|
||||
->map(fn (Field $field): array => [
|
||||
new FieldSortCriteria($field),
|
||||
new FieldSortCriteria($field, SortDirection::DESC),
|
||||
@@ -93,28 +87,6 @@ class SortableColumns extends EnumType
|
||||
->flatten();
|
||||
}
|
||||
|
||||
private function getCountSortCriteria(): Collection
|
||||
{
|
||||
return $this->getSortableFields()
|
||||
->filter(fn (Field $field): bool => $field->sortType() === SortType::COUNT_RELATION)
|
||||
->map(fn (Field $field): array => [
|
||||
new CountSortCriteria($field),
|
||||
new CountSortCriteria($field, SortDirection::DESC),
|
||||
])
|
||||
->flatten();
|
||||
}
|
||||
|
||||
private function getAggregateSortCriteria(): Collection
|
||||
{
|
||||
return $this->getSortableFields()
|
||||
->filter(fn (Field $field): bool => $field->sortType() === SortType::AGGREGATE)
|
||||
->map(fn (Field $field): array => [
|
||||
new AggregateSortCriteria($field),
|
||||
new AggregateSortCriteria($field, SortDirection::DESC),
|
||||
])
|
||||
->flatten();
|
||||
}
|
||||
|
||||
private function getRelationSortCriteria(): Collection
|
||||
{
|
||||
return $this->getRelations($this->type)
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Auth\User\Me;
|
||||
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Schema\Fields\StringField;
|
||||
use App\Models\Auth\User;
|
||||
|
||||
@@ -19,9 +18,4 @@ class MeEmailField extends StringField
|
||||
{
|
||||
return 'The email of the user';
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
{
|
||||
return SortType::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Auth\User\Me;
|
||||
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Schema\Fields\DateTimeTzField;
|
||||
use App\Models\Auth\User;
|
||||
|
||||
@@ -19,9 +18,4 @@ class MeEmailVerifiedAtField extends DateTimeTzField
|
||||
{
|
||||
return 'The date the user verified their email';
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
{
|
||||
return SortType::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Auth\User\Me;
|
||||
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Schema\Fields\StringField;
|
||||
use App\Models\Auth\User;
|
||||
|
||||
@@ -19,9 +18,4 @@ class MeNameField extends StringField
|
||||
{
|
||||
return 'The username of authenticated user';
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
{
|
||||
return SortType::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Auth\User\Me;
|
||||
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Schema\Fields\DateTimeTzField;
|
||||
use App\Models\Auth\User;
|
||||
|
||||
@@ -19,9 +18,4 @@ class MeTwoFactorConfirmedAtField extends DateTimeTzField
|
||||
{
|
||||
return 'The date the user confirmed their two-factor authentication';
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
{
|
||||
return SortType::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Base\Aggregate;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\Field\AggregateFunction;
|
||||
use App\Enums\GraphQL\QualifyColumn;
|
||||
use App\GraphQL\Criteria\Filter\FilterCriteria;
|
||||
use App\GraphQL\Criteria\Filter\WhereConditionsFilterCriteria;
|
||||
use App\GraphQL\Criteria\Sort\Sort;
|
||||
use App\GraphQL\Criteria\Sort\SortCriteria;
|
||||
use App\GraphQL\Schema\Enums\FilterableColumns;
|
||||
use App\GraphQL\Schema\Enums\SortableColumns;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Types\BaseType;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Stringable;
|
||||
|
||||
abstract class AggregateField extends Field implements FilterableField, SortableField
|
||||
{
|
||||
private Collection $filterableFields;
|
||||
|
||||
public function __construct(
|
||||
public string $relation,
|
||||
protected string $fieldName,
|
||||
protected AggregateFunction $function,
|
||||
protected string $aggregateColumn,
|
||||
bool $nullable = true
|
||||
) {
|
||||
parent::__construct($this->alias(), $fieldName, $nullable);
|
||||
}
|
||||
|
||||
public function getSort(): Sort
|
||||
{
|
||||
return new Sort($this->fieldName, $this->alias(), qualifyColumn: QualifyColumn::NO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load the aggregate value for the query builder.
|
||||
*/
|
||||
public function shouldAggregate(array $args, array $selection, BaseType $type): bool
|
||||
{
|
||||
// If the field is being requested.
|
||||
if (Arr::has($selection, $this->getName())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the sorting is requesting an aggregate function.
|
||||
/** @var SortCriteria[] $sortCriteria */
|
||||
$sortCriteria = Arr::get(new SortableColumns($type)->getAttributes(), 'criteria');
|
||||
$sorts = Arr::get($args, 'sort', []);
|
||||
foreach ($sortCriteria as $sortCriterion) {
|
||||
if (in_array($sortCriterion->__toString(), $sorts) && $sortCriterion->getField()->getName() === $this->getName()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If the filtering is requesting an aggregate function.
|
||||
$filterCriteria = FilterCriteria::parse($type, $args);
|
||||
foreach ($filterCriteria as $filterCriterion) {
|
||||
if ($filterCriterion instanceof WhereConditionsFilterCriteria) {
|
||||
$this->filterableFields = new FilterableColumns($type)->getValues();
|
||||
foreach ($filterCriterion->getFilterValues() as $filterValue) {
|
||||
if ($this->recursiveWhere($filterValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load the aggregate value for the query builder.
|
||||
*/
|
||||
public function with(Builder $builder): Builder
|
||||
{
|
||||
return $builder->withAggregate($this->relation, $this->aggregateColumn, $this->function->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load the aggregate value for the query builder.
|
||||
*/
|
||||
public function load(Model $model): Model
|
||||
{
|
||||
return $model->loadAggregate($this->relation, $this->aggregateColumn, $this->function->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the field.
|
||||
*
|
||||
* @param Model $root
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return $root->getAttribute($this->alias());
|
||||
}
|
||||
|
||||
public function alias(): string
|
||||
{
|
||||
return Str::of($this->relation)
|
||||
->snake()
|
||||
->append('_')
|
||||
->append($this->function->value)
|
||||
->when($this->aggregateColumn !== '*', fn (Stringable $string) => $string->append('_')->append($this->aggregateColumn))
|
||||
->__toString();
|
||||
}
|
||||
|
||||
private function recursiveWhere(array $value): bool
|
||||
{
|
||||
$fieldName = Arr::get($value, 'field');
|
||||
$fieldValue = Arr::get($value, 'value');
|
||||
|
||||
if ($fieldName && $fieldValue) {
|
||||
$field = $this->filterableFields->get($fieldName);
|
||||
if ($field instanceof Field && $field->getName() === $this->getName()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($and = Arr::get($value, 'AND')) {
|
||||
foreach ($and as $andSolo) {
|
||||
if ($this->recursiveWhere($andSolo)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($or = Arr::get($value, 'OR')) {
|
||||
foreach ($or as $orSolo) {
|
||||
if ($this->recursiveWhere($orSolo)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Base\Aggregate;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\Field\AggregateFunction;
|
||||
use App\Enums\GraphQL\Filter\Clause;
|
||||
use App\GraphQL\Filter\IntFilter;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
class CountAggregateField extends AggregateField implements DisplayableField, SortableField
|
||||
{
|
||||
public function __construct(
|
||||
public string $aggregateRelation,
|
||||
string $name,
|
||||
protected bool $nullable = false,
|
||||
) {
|
||||
parent::__construct($aggregateRelation, $name, AggregateFunction::SUM, 'value', $nullable);
|
||||
}
|
||||
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
|
||||
public function canBeDisplayed(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFilter(): IntFilter
|
||||
{
|
||||
return new IntFilter($this->getName(), $this->alias(), Clause::HAVING);
|
||||
}
|
||||
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return (int) parent::resolve(...func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Base\Aggregate;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\FilterableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\Field\AggregateFunction;
|
||||
use App\Enums\GraphQL\Filter\Clause;
|
||||
use App\GraphQL\Filter\IntFilter;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
class CountField extends AggregateField implements DisplayableField, FilterableField, SortableField
|
||||
{
|
||||
public function __construct(
|
||||
protected string $aggregateRelation,
|
||||
protected ?string $name = null,
|
||||
protected bool $nullable = false,
|
||||
) {
|
||||
parent::__construct($aggregateRelation, $aggregateRelation.'Count', AggregateFunction::COUNT, '*', $nullable);
|
||||
}
|
||||
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
|
||||
public function canBeDisplayed(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFilter(): IntFilter
|
||||
{
|
||||
return new IntFilter($this->getName(), $this->alias(), Clause::HAVING);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Base\Aggregate;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Enums\GraphQL\Field\AggregateFunction;
|
||||
use App\Enums\GraphQL\Filter\Clause;
|
||||
use App\GraphQL\Filter\BooleanFilter;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
class ExistsField extends AggregateField implements DisplayableField
|
||||
{
|
||||
public function __construct(
|
||||
protected string $aggregateRelation,
|
||||
protected bool $nullable = false,
|
||||
) {
|
||||
parent::__construct($aggregateRelation, $aggregateRelation.'Exists', AggregateFunction::EXISTS, '*', $nullable);
|
||||
}
|
||||
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::boolean();
|
||||
}
|
||||
|
||||
public function canBeDisplayed(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFilter(): BooleanFilter
|
||||
{
|
||||
return new BooleanFilter($this->getName(), $this->alias(), Clause::HAVING);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Base;
|
||||
namespace App\GraphQL\Schema\Fields\Base\Aggregate;
|
||||
|
||||
use App\Contracts\Models\HasAggregateLikes;
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Base;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\Contracts\GraphQL\Fields\SortableField;
|
||||
use App\Enums\GraphQL\SortType;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CountAggregateField extends Field implements DisplayableField, SortableField
|
||||
{
|
||||
public function __construct(
|
||||
public string $aggregateRelation,
|
||||
protected string $column,
|
||||
protected ?string $name = null,
|
||||
protected bool $nullable = false,
|
||||
) {
|
||||
parent::__construct($column, $name, $nullable);
|
||||
}
|
||||
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
|
||||
public function canBeDisplayed(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
{
|
||||
return SortType::AGGREGATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* The relation to sort the type.
|
||||
*/
|
||||
public function relation(): ?string
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Base;
|
||||
|
||||
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\Filter\RelationFilter;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
class CountField extends Field implements DisplayableField, FilterableField, SortableField
|
||||
{
|
||||
public function __construct(
|
||||
protected string $relation,
|
||||
protected string $column,
|
||||
protected ?string $name = null,
|
||||
protected bool $nullable = false,
|
||||
) {
|
||||
parent::__construct($column, $name, $nullable);
|
||||
}
|
||||
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::int();
|
||||
}
|
||||
|
||||
public function canBeDisplayed(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
{
|
||||
return SortType::COUNT_RELATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* The relation to sort the type.
|
||||
*/
|
||||
public function relation(): ?string
|
||||
{
|
||||
return $this->relation;
|
||||
}
|
||||
|
||||
public function getFilter(): RelationFilter
|
||||
{
|
||||
return new RelationFilter($this->getName(), $this->getColumn());
|
||||
}
|
||||
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return $root->hasAttribute($attribute = "{$this->relation}_count")
|
||||
? (int) $root->getAttribute($attribute)
|
||||
: $root->{$this->relation}->count();
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Base;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DisplayableField;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ExistsField extends Field implements DisplayableField
|
||||
{
|
||||
public function __construct(
|
||||
protected string $relation,
|
||||
protected ?string $name = null,
|
||||
protected bool $nullable = false,
|
||||
) {
|
||||
parent::__construct($relation.'Exists', $name, $nullable);
|
||||
}
|
||||
|
||||
public function baseType(): Type
|
||||
{
|
||||
return Type::boolean();
|
||||
}
|
||||
|
||||
public function canBeDisplayed(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the field.
|
||||
*
|
||||
* @param Model $root
|
||||
*/
|
||||
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
||||
{
|
||||
return $root->{$this->relation}->isNotEmpty();
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace App\GraphQL\Schema\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\Criteria\Sort\Sort;
|
||||
use App\GraphQL\Filter\BooleanFilter;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
@@ -29,8 +29,8 @@ abstract class BooleanField extends Field implements DisplayableField, Filterabl
|
||||
->useEq();
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
public function getSort(): Sort
|
||||
{
|
||||
return SortType::ROOT;
|
||||
return new Sort($this->getName(), $this->getColumn());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace App\GraphQL\Schema\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\Criteria\Sort\Sort;
|
||||
use App\GraphQL\Filter\EnumFilter;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
@@ -52,8 +52,8 @@ abstract class EnumField extends Field implements DisplayableField, FilterableFi
|
||||
->useNotIn();
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
public function getSort(): Sort
|
||||
{
|
||||
return SortType::ROOT;
|
||||
return new Sort($this->getName(), $this->getColumn());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace App\GraphQL\Schema\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\Criteria\Sort\Sort;
|
||||
use App\GraphQL\Filter\FloatFilter;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
@@ -33,8 +33,8 @@ abstract class FloatField extends Field implements DisplayableField, FilterableF
|
||||
->useNotIn();
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
public function getSort(): Sort
|
||||
{
|
||||
return SortType::ROOT;
|
||||
return new Sort($this->getName(), $this->getColumn());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace App\GraphQL\Schema\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\Criteria\Sort\Sort;
|
||||
use App\GraphQL\Filter\IntFilter;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
@@ -33,8 +33,8 @@ abstract class IntField extends Field implements DisplayableField, FilterableFie
|
||||
->useNotIn();
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
public function getSort(): Sort
|
||||
{
|
||||
return SortType::ROOT;
|
||||
return new Sort($this->getName(), $this->getColumn());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\List\Playlist;
|
||||
|
||||
use App\GraphQL\Schema\Fields\Base\CountField;
|
||||
use App\GraphQL\Schema\Fields\Base\Aggregate\CountField;
|
||||
use App\Models\List\Playlist;
|
||||
|
||||
class PlaylistTracksCountField extends CountField
|
||||
|
||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\List\Playlist;
|
||||
|
||||
use App\GraphQL\Schema\Fields\Base\ExistsField;
|
||||
use App\GraphQL\Schema\Fields\Base\Aggregate\ExistsField;
|
||||
use App\Models\List\Playlist;
|
||||
|
||||
class PlaylistTracksExistsField extends ExistsField
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace App\GraphQL\Schema\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\Criteria\Sort\Sort;
|
||||
use App\GraphQL\Filter\Filter;
|
||||
use App\GraphQL\Filter\StringFilter;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
@@ -31,8 +31,8 @@ abstract class StringField extends Field implements DisplayableField, Filterable
|
||||
->useLike();
|
||||
}
|
||||
|
||||
public function sortType(): SortType
|
||||
public function getSort(): Sort
|
||||
{
|
||||
return SortType::ROOT;
|
||||
return new Sort($this->getName(), $this->getColumn());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Fields\Wiki\Anime\Theme\Entry;
|
||||
|
||||
use App\GraphQL\Schema\Fields\Base\CountField;
|
||||
use App\GraphQL\Schema\Fields\Base\Aggregate\CountField;
|
||||
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
|
||||
|
||||
class AnimeThemeEntryTracksCountField extends CountField
|
||||
|
||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Schema\Fields\Wiki\Audio;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DeprecatedField;
|
||||
use App\GraphQL\Schema\Fields\Base\CountAggregateField;
|
||||
use App\GraphQL\Schema\Fields\Base\Aggregate\CountAggregateField;
|
||||
use App\Models\Wiki\Audio;
|
||||
|
||||
class AudioViewsCountField extends CountAggregateField implements DeprecatedField
|
||||
|
||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Schema\Fields\Wiki\Video;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\DeprecatedField;
|
||||
use App\GraphQL\Schema\Fields\Base\CountAggregateField;
|
||||
use App\GraphQL\Schema\Fields\Base\Aggregate\CountAggregateField;
|
||||
use App\Models\Wiki\Video;
|
||||
|
||||
class VideoViewsCountField extends CountAggregateField implements DeprecatedField
|
||||
|
||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Inputs;
|
||||
|
||||
use App\Enums\GraphQL\ComparisonOperator;
|
||||
use App\Enums\GraphQL\Filter\ComparisonOperator;
|
||||
use App\GraphQL\Schema\Enums\FilterableColumns;
|
||||
use App\GraphQL\Schema\Types\EloquentType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
@@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Schema\Types\List;
|
||||
|
||||
use App\GraphQL\Schema\Fields\Base\Aggregate\LikesCountField;
|
||||
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
|
||||
use App\GraphQL\Schema\Fields\Base\LikesCountField;
|
||||
use App\GraphQL\Schema\Fields\Base\UpdatedAtField;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Fields\List\Playlist\PlaylistDescriptionField;
|
||||
|
||||
@@ -5,10 +5,10 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Schema\Types\Wiki\Anime\Theme;
|
||||
|
||||
use App\Contracts\GraphQL\Types\SubmitableType;
|
||||
use App\GraphQL\Schema\Fields\Base\Aggregate\LikesCountField;
|
||||
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
|
||||
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
|
||||
use App\GraphQL\Schema\Fields\Base\IdField;
|
||||
use App\GraphQL\Schema\Fields\Base\LikesCountField;
|
||||
use App\GraphQL\Schema\Fields\Base\UpdatedAtField;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Fields\Wiki\Anime\Theme\Entry\AnimeThemeEntryEpisodesField;
|
||||
|
||||
@@ -26,7 +26,7 @@ abstract class AggregateField extends Field implements FilterableField, Renderab
|
||||
|
||||
public function __construct(
|
||||
Schema $schema,
|
||||
protected readonly string $relation,
|
||||
public readonly string $relation,
|
||||
protected readonly AggregateFunction $function,
|
||||
protected readonly string $aggregateColumn
|
||||
) {
|
||||
|
||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Enums\GraphQL\ComparisonOperator;
|
||||
use App\Enums\GraphQL\SortDirection;
|
||||
use App\Enums\GraphQL\TrashedFilter;
|
||||
use App\Enums\GraphQL\Filter\ComparisonOperator;
|
||||
use App\Enums\GraphQL\Filter\TrashedFilter;
|
||||
use App\Enums\GraphQL\Sort\SortDirection;
|
||||
use App\Enums\Models\List\ExternalEntryWatchStatus;
|
||||
use App\Enums\Models\List\ExternalProfileSite;
|
||||
use App\Enums\Models\List\ExternalProfileVisibility;
|
||||
|
||||
Reference in New Issue
Block a user