*/ public function pageInfoResolver(LengthAwarePaginator $paginator): array { /** @var int|null $firstItem Laravel type-hints are inaccurate here */ $firstItem = $paginator->firstItem(); /** @var int|null $lastItem Laravel type-hints are inaccurate here */ $lastItem = $paginator->lastItem(); return [ 'hasNextPage' => $paginator->hasMorePages(), 'hasPreviousPage' => $paginator->currentPage() > 1, 'startCursor' => $firstItem !== null ? Cursor::encode($firstItem) : null, 'endCursor' => $lastItem !== null ? Cursor::encode($lastItem) : null, 'total' => $paginator->total(), 'count' => $paginator->count(), 'currentPage' => $paginator->currentPage(), 'lastPage' => $paginator->lastPage(), ]; } /** * Resolve edges for connection. * * @param \Illuminate\Pagination\LengthAwarePaginator $paginator * @param array $args */ public function edgeResolver(LengthAwarePaginator $paginator, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Collection { // We know those types because we manipulated them during PaginationManipulator /** @var \GraphQL\Type\Definition\NonNull $nonNullList */ $nonNullList = $resolveInfo->returnType; /** @var \GraphQL\Type\Definition\ObjectType|\GraphQL\Type\Definition\InterfaceType $objectLikeType */ $objectLikeType = $nonNullList->getWrappedType(true); $returnTypeFields = $objectLikeType->getFields(); /** @var int|null $firstItem Laravel type-hints are inaccurate here */ $firstItem = $paginator->firstItem(); return $paginator ->values() ->map(function ($item, int $index) use ($returnTypeFields, $firstItem): array { $data = []; foreach ($returnTypeFields as $field) { switch ($field->name) { case 'cursor': $data['cursor'] = Cursor::encode((int) $firstItem + $index); break; case 'node': $data['node'] = $item; break; default: // All other fields on the return type are assumed to be part // of the edge, so we try to locate them in the pivot attribute if (isset($item->pivot->{$field->name})) { $data[$field->name] = $item->pivot->{$field->name}; } } } return $data; }); } }