mirror of
https://github.com/AnimeThemes/animethemes-server.git
synced 2026-07-11 01:24:46 +02:00
168 lines
3.9 KiB
PHP
168 lines
3.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\GraphQL\Schema\Fields\Relations;
|
|
|
|
use App\Concerns\Actions\GraphQL\FiltersModels;
|
|
use App\Contracts\GraphQL\EnumSort;
|
|
use App\Enums\GraphQL\PaginationType;
|
|
use App\GraphQL\Argument\Argument;
|
|
use App\GraphQL\Argument\FirstArgument;
|
|
use App\GraphQL\Argument\PageArgument;
|
|
use App\GraphQL\Argument\SortArgument;
|
|
use App\GraphQL\Criteria\Filter\FilterCriteria;
|
|
use App\GraphQL\Filter\Filter;
|
|
use App\GraphQL\Schema\Fields\Field;
|
|
use App\GraphQL\Schema\Types\BaseType;
|
|
use App\GraphQL\Schema\Types\Pivot\PivotType;
|
|
use App\GraphQL\Schema\Unions\BaseUnion;
|
|
use GraphQL\Type\Definition\ResolveInfo;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Collection;
|
|
use UnitEnum;
|
|
|
|
abstract class Relation extends Field
|
|
{
|
|
use FiltersModels;
|
|
|
|
protected bool $asPivot = false;
|
|
|
|
/** @var class-string<UnitEnum&EnumSort>|null */
|
|
protected ?string $sortEnum = null;
|
|
|
|
public function __construct(
|
|
protected BaseType|BaseUnion $relatedType,
|
|
protected string $relationName,
|
|
) {
|
|
parent::__construct($relationName);
|
|
}
|
|
|
|
/**
|
|
* Rename the relation to something else.
|
|
*/
|
|
public function renameTo(string $name): static
|
|
{
|
|
$this->name = $name;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Mark the relation as non-nullable.
|
|
*/
|
|
public function nonNullable(): static
|
|
{
|
|
$this->nullable = false;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Mark the relation as a relation of the pivot model.
|
|
*/
|
|
public function asPivot(): static
|
|
{
|
|
$this->asPivot = true;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param class-string<UnitEnum&EnumSort> $enum
|
|
*/
|
|
public function setSortEnum(string $enum): static
|
|
{
|
|
$this->sortEnum = $enum;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the relation name in the model.
|
|
*/
|
|
public function getRelationName(): string
|
|
{
|
|
return $this->getColumn();
|
|
}
|
|
|
|
public function isPivot(): bool
|
|
{
|
|
return $this->asPivot;
|
|
}
|
|
|
|
/**
|
|
* Resolve the arguments of the sub-query.
|
|
*
|
|
* @return Argument[]
|
|
*/
|
|
public function arguments(): array
|
|
{
|
|
$arguments = [];
|
|
|
|
$type = $this->relatedType;
|
|
|
|
if ($this->paginationType() !== PaginationType::NONE && $type instanceof BaseType && $type->hasFilterableColumns()) {
|
|
$arguments[] = FilterCriteria::getFilters($type)
|
|
->map(fn (Filter $filter): array => $filter->getArguments())
|
|
->flatten();
|
|
}
|
|
|
|
if ($this->paginationType() !== PaginationType::NONE) {
|
|
$arguments[] = new FirstArgument(true);
|
|
$arguments[] = new PageArgument();
|
|
|
|
if ($type instanceof BaseType && $type->getEnumSortClass() !== null) {
|
|
$arguments[] = new SortArgument($type);
|
|
}
|
|
}
|
|
|
|
return Arr::flatten($arguments);
|
|
}
|
|
|
|
/**
|
|
* @return BaseType|BaseUnion
|
|
*/
|
|
public function baseType()
|
|
{
|
|
return $this->relatedType;
|
|
}
|
|
|
|
/**
|
|
* Get the pivot type if it exists.
|
|
*/
|
|
public function getPivotType(): ?PivotType
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Resolve the relation.
|
|
*
|
|
* @param Model $root
|
|
* @param array<string, mixed> $args
|
|
*/
|
|
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
|
|
{
|
|
/** @var Collection $collection */
|
|
$collection = $root->{$this->getRelationName()};
|
|
|
|
$first = max(1, Arr::integer($args, 'first'));
|
|
$page = Arr::get($args, 'page');
|
|
|
|
return new LengthAwarePaginator(
|
|
$collection->forPage($page, $first),
|
|
$collection->count(),
|
|
$first,
|
|
$page
|
|
);
|
|
}
|
|
|
|
/**
|
|
* The pagination type.
|
|
*/
|
|
abstract public function paginationType(): PaginationType;
|
|
}
|