|
@@ -20,10 +20,28 @@ class ProductSearchResolver implements QueryItemResolverInterface
|
|
|
public function __invoke(?object $item, array $context): object
|
|
public function __invoke(?object $item, array $context): object
|
|
|
{
|
|
{
|
|
|
$args = $context['args'] ?? [];
|
|
$args = $context['args'] ?? [];
|
|
|
|
|
+ $productArgs = $args;
|
|
|
|
|
+
|
|
|
|
|
+ // The product provider only understands Relay cursor args (after/before),
|
|
|
|
|
+ // so translate a direct `page` arg into an equivalent `after` cursor.
|
|
|
|
|
+ if (! empty($productArgs['page'])) {
|
|
|
|
|
+ $page = max(1, (int) $productArgs['page']);
|
|
|
|
|
+ $limit = max(1, (int) ($productArgs['first'] ?? $productArgs['last'] ?? 30));
|
|
|
|
|
+ $offset = ($page - 1) * $limit;
|
|
|
|
|
+
|
|
|
|
|
+ unset($productArgs['after'], $productArgs['before']);
|
|
|
|
|
+
|
|
|
|
|
+ if ($offset > 0) {
|
|
|
|
|
+ $productArgs['after'] = base64_encode((string) ($offset - 1));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ unset($productArgs['page']);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
$paginator = $this->productProvider->provide(
|
|
$paginator = $this->productProvider->provide(
|
|
|
$context['operation'],
|
|
$context['operation'],
|
|
|
[],
|
|
[],
|
|
|
- ['args' => $args]
|
|
|
|
|
|
|
+ ['args' => $productArgs]
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
if (! $paginator instanceof PaginatorInterface) {
|
|
if (! $paginator instanceof PaginatorInterface) {
|
|
@@ -34,6 +52,7 @@ class ProductSearchResolver implements QueryItemResolverInterface
|
|
|
$result->total_count = (int) $paginator->getTotalItems();
|
|
$result->total_count = (int) $paginator->getTotalItems();
|
|
|
|
|
|
|
|
$offset = $this->resolveOffset($args, $result->total_count);
|
|
$offset = $this->resolveOffset($args, $result->total_count);
|
|
|
|
|
+ $limit = max(1, (int) ($args['first'] ?? $args['last'] ?? 30));
|
|
|
|
|
|
|
|
foreach ($paginator as $index => $product) {
|
|
foreach ($paginator as $index => $product) {
|
|
|
$edge = new ProductSearchEdgeDto;
|
|
$edge = new ProductSearchEdgeDto;
|
|
@@ -42,7 +61,7 @@ class ProductSearchResolver implements QueryItemResolverInterface
|
|
|
$result->edges[] = $edge;
|
|
$result->edges[] = $edge;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- $result->page_info = $this->buildPageInfo($result->edges, $offset, $paginator);
|
|
|
|
|
|
|
+ $result->page_info = $this->buildPageInfo($result->edges, $offset, $limit, $result->total_count, $paginator);
|
|
|
|
|
|
|
|
$metadata = request()->attributes->get('bagistoapi.search_metadata');
|
|
$metadata = request()->attributes->get('bagistoapi.search_metadata');
|
|
|
|
|
|
|
@@ -55,17 +74,24 @@ class ProductSearchResolver implements QueryItemResolverInterface
|
|
|
return $result;
|
|
return $result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Resolve the current page offset.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Supports both Relay cursor args (after/before) and a direct `page` arg.
|
|
|
|
|
+ * When `page` is provided it takes precedence over after/before.
|
|
|
|
|
+ */
|
|
|
private function resolveOffset(array $args, int $total): int
|
|
private function resolveOffset(array $args, int $total): int
|
|
|
{
|
|
{
|
|
|
$limit = max(1, (int) ($args['first'] ?? $args['last'] ?? 30));
|
|
$limit = max(1, (int) ($args['first'] ?? $args['last'] ?? 30));
|
|
|
$offset = 0;
|
|
$offset = 0;
|
|
|
|
|
|
|
|
- if (! empty($args['after'])) {
|
|
|
|
|
|
|
+ if (! empty($args['page'])) {
|
|
|
|
|
+ $page = max(1, (int) $args['page']);
|
|
|
|
|
+ $offset = ($page - 1) * $limit;
|
|
|
|
|
+ } elseif (! empty($args['after'])) {
|
|
|
$decoded = base64_decode($args['after'], true);
|
|
$decoded = base64_decode($args['after'], true);
|
|
|
$offset = ctype_digit((string) $decoded) ? ((int) $decoded + 1) : 0;
|
|
$offset = ctype_digit((string) $decoded) ? ((int) $decoded + 1) : 0;
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (! empty($args['before'])) {
|
|
|
|
|
|
|
+ } elseif (! empty($args['before'])) {
|
|
|
$decoded = base64_decode($args['before'], true);
|
|
$decoded = base64_decode($args['before'], true);
|
|
|
$cursor = ctype_digit((string) $decoded) ? (int) $decoded : 0;
|
|
$cursor = ctype_digit((string) $decoded) ? (int) $decoded : 0;
|
|
|
$offset = max(0, $cursor - $limit);
|
|
$offset = max(0, $cursor - $limit);
|
|
@@ -81,6 +107,8 @@ class ProductSearchResolver implements QueryItemResolverInterface
|
|
|
private function buildPageInfo(
|
|
private function buildPageInfo(
|
|
|
array $edges,
|
|
array $edges,
|
|
|
int $offset,
|
|
int $offset,
|
|
|
|
|
+ int $limit,
|
|
|
|
|
+ int $total,
|
|
|
PaginatorInterface $paginator
|
|
PaginatorInterface $paginator
|
|
|
): ProductSearchPageInfoDto {
|
|
): ProductSearchPageInfoDto {
|
|
|
$pageInfo = new ProductSearchPageInfoDto;
|
|
$pageInfo = new ProductSearchPageInfoDto;
|
|
@@ -90,6 +118,8 @@ class ProductSearchResolver implements QueryItemResolverInterface
|
|
|
: $paginator->getCurrentPage() < $paginator->getLastPage();
|
|
: $paginator->getCurrentPage() < $paginator->getLastPage();
|
|
|
$pageInfo->startCursor = $edges[0]->cursor ?? null;
|
|
$pageInfo->startCursor = $edges[0]->cursor ?? null;
|
|
|
$pageInfo->endCursor = $edges[array_key_last($edges)]->cursor ?? null;
|
|
$pageInfo->endCursor = $edges[array_key_last($edges)]->cursor ?? null;
|
|
|
|
|
+ $pageInfo->current_page = $total > 0 ? (int) floor($offset / $limit) + 1 : 1;
|
|
|
|
|
+ $pageInfo->total_pages = $total > 0 ? (int) ceil($total / $limit) : 1;
|
|
|
|
|
|
|
|
return $pageInfo;
|
|
return $pageInfo;
|
|
|
}
|
|
}
|