saloonphp / saloon

🤠 Build beautiful API integrations and SDKs with Saloon
https://docs.saloon.dev
MIT License
2.09k stars 107 forks source link

Body-based Pagination #361

Closed faustbrian closed 10 months ago

faustbrian commented 10 months ago

Hey, is it currently possible to create a paginator that adds parameters to the body instead of headers and query? I would basically need a slightly adjusted version of what is shown on this page.

public function paginate(Request $request): CursorPaginator
{
    return new class(connector: $this, request: $request) extends CursorPaginator
    {
        protected function getNextCursor(Response $response): int|string
        {
            return $response->json('result.page.next');
        }

        protected function isLastPage(Response $response): bool
        {
            return is_null($response->json('result.page.next'));
        }

        protected function getPageItems(Response $response, Request $request): array
        {
            return $response->json('result.data');
        }

        protected function applyPagination(Request $request): Request
        {
            if ($this->currentResponse instanceof Response) {
                // Pseudo Code
                $request->body()->add('params.page.cursor', $this->getNextCursor($this->currentResponse));
            }

            if (isset($this->perPageLimit)) {
                // Pseudo Code
                $request->body()->add('params.page.size', $this->perPageLimit);
            }

            return $request;
        }
    };
}
faustbrian commented 10 months ago

This seems to do the trick, didn't think of checking if HasJsonBody is used. Though it doesn't seem to be possible to set nested keys via dot-notation so merge has to be used.

protected function applyPagination(Request $request): Request
{
    if (!\in_array(HasJsonBody::class, \class_uses($request), true)) {
        return $request;
    }

    if ($this->currentResponse instanceof Response) {
        // @phpstan-ignore-next-line
        $request->body()->merge([
            'params' => [
                'page' => [
                    'cursor' => $this->getNextCursor($this->currentResponse),
                    'size' => $this->perPageLimit,
                ],
            ],
        ]);
    }

    return $request;
}