Skip to content

Commit e277a35

Browse files
committed
Curler: Add TPage template to CurlerPagerInterface::getPage()
- Add `CurlerInterface::alwaysPaginates()` - Simplify built-in pagers after recent interface improvements
1 parent 73bd24d commit e277a35

File tree

7 files changed

+51
-56
lines changed

7 files changed

+51
-56
lines changed

src/Toolkit/Contract/Curler/CurlerInterface.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,12 @@ public function withoutMiddleware($middleware);
463463
*/
464464
public function getPager(): ?CurlerPagerInterface;
465465

466+
/**
467+
* Check if the endpoint's pagination handler is used to process every
468+
* request
469+
*/
470+
public function alwaysPaginates(): bool;
471+
466472
/**
467473
* Get an instance with the given pagination handler
468474
*

src/Toolkit/Contract/Curler/CurlerPagerInterface.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,13 @@ public function getFirstRequest(
3030
/**
3131
* Convert data returned by the endpoint to a new page object
3232
*
33+
* @template TPage of CurlerPageInterface|null
34+
*
3335
* @param mixed $data
36+
* @param TPage $previousPage
3437
* @param mixed[]|null $query The query applied to `$request` or returned by
3538
* {@see CurlerPageRequestInterface::getNextQuery()}, if applicable.
39+
* @return (TPage is null ? CurlerPageInterface : TPage)
3640
*/
3741
public function getPage(
3842
$data,

src/Toolkit/Curler/Curler.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,14 @@ public function getPager(): ?CurlerPagerInterface
648648
return $this->Pager;
649649
}
650650

651+
/**
652+
* @inheritDoc
653+
*/
654+
public function alwaysPaginates(): bool
655+
{
656+
return $this->AlwaysPaginate;
657+
}
658+
651659
/**
652660
* @inheritDoc
653661
*/

src/Toolkit/Curler/Pager/LinkPager.php

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
use Salient\Contract\Http\HttpHeader;
1010
use Salient\Contract\Http\HttpResponseInterface;
1111
use Salient\Curler\CurlerPage;
12+
use Salient\Curler\CurlerPageRequest;
1213
use Salient\Http\Http;
1314
use Salient\Http\Uri;
1415
use Closure;
1516

1617
/**
17-
* Follows "Link" headers in responses from the endpoint
18+
* Follows "Link" headers with rel="next" in responses from the endpoint
1819
*
1920
* @api
2021
*/
@@ -54,16 +55,16 @@ public function getFirstRequest(
5455
RequestInterface $request,
5556
CurlerInterface $curler,
5657
?array $query = null
57-
): RequestInterface {
58+
) {
5859
if ($this->PageSize === null) {
5960
return $request;
6061
}
6162

6263
$query[$this->PageSizeKey] = $this->PageSize;
63-
$uri = $request->getUri();
64-
$uri = $curler->replaceQuery($uri, $query);
65-
66-
return $request->withUri($uri);
64+
return new CurlerPageRequest(
65+
$curler->replaceQuery($request, $query),
66+
$query,
67+
);
6768
}
6869

6970
/**
@@ -79,18 +80,15 @@ public function getPage(
7980
): CurlerPageInterface {
8081
$data = ($this->EntitySelector)($data);
8182

82-
$response = $curler->getLastResponse();
83-
if ($response && ($links = $response->getHeaderValues(HttpHeader::LINK))) {
84-
foreach ($links as $link) {
85-
/** @var array{string,rel?:string} */
86-
$link = Http::getParameters($link);
87-
if (($link['rel'] ?? null) === 'next') {
88-
$link = trim($link[0], '<>');
89-
$uri = $request->getUri();
90-
$uri = Uri::from($uri)->follow($link);
91-
$nextRequest = $request->withUri($uri);
92-
break;
93-
}
83+
foreach ($response->getHeaderValues(HttpHeader::LINK) as $link) {
84+
/** @var array{string,rel?:string} */
85+
$link = Http::getParameters($link);
86+
if (($link['rel'] ?? null) === 'next') {
87+
$link = trim($link[0], '<>');
88+
$uri = $request->getUri();
89+
$uri = Uri::from($uri)->follow($link);
90+
$nextRequest = $request->withUri($uri);
91+
break;
9492
}
9593
}
9694

src/Toolkit/Curler/Pager/ODataPager.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ public function getPage(
7373
throw new InvalidArgumentTypeException(1, 'data', 'mixed[]', $data);
7474
}
7575
/** @var array{'@odata.nextLink'?:string,'@nextLink'?:string,value:list<mixed>,...} $data */
76-
$response = $curler->getLastResponse();
77-
if ($response && $response->getHeaderLine(HttpHeader::ODATA_VERSION) === '4.0') {
76+
if ($response->getHeaderLine(HttpHeader::ODATA_VERSION) === '4.0') {
7877
$nextLink = $data['@odata.nextLink'] ?? null;
7978
} else {
8079
$nextLink = $data['@nextLink'] ?? $data['@odata.nextLink'] ?? null;

src/Toolkit/Curler/Pager/QueryPager.php

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
use Salient\Contract\Curler\CurlerPagerInterface;
99
use Salient\Contract\Http\HttpResponseInterface;
1010
use Salient\Curler\CurlerPage;
11+
use Salient\Utility\Test;
1112
use Closure;
13+
use LogicException;
1214

1315
/**
1416
* Increments a value in the query string of each request until no results are
@@ -22,11 +24,8 @@ final class QueryPager implements CurlerPagerInterface
2224

2325
/** @var array-key|null */
2426
private $PageKey;
27+
/** @var int<1,max>|null */
2528
private ?int $PageSize;
26-
/** @var mixed[] */
27-
private array $CurrentQuery;
28-
/** @var array-key|null */
29-
private $CurrentPageKey;
3029

3130
/**
3231
* Creates a new QueryPager object
@@ -40,10 +39,9 @@ final class QueryPager implements CurlerPagerInterface
4039
* - `Arr::get($data, $entitySelector)` if `$entitySelector` is a string or
4140
* integer, or
4241
* - `$data` if `$entitySelector` is `null`
43-
* @param int|null $pageSize Another page is requested if:
42+
* @param int<1,max>|null $pageSize Another page is requested if:
4443
* - `$pageSize` is `null` and at least one result is returned, or
45-
* - `$pageSize` is greater than `0` and exactly `$pageSize` results are
46-
* returned
44+
* - exactly `$pageSize` results are returned
4745
*/
4846
public function __construct(
4947
$pageKey = null,
@@ -63,18 +61,6 @@ public function getFirstRequest(
6361
CurlerInterface $curler,
6462
?array $query = null
6563
): RequestInterface {
66-
$this->CurrentQuery = $query ?? [];
67-
$this->CurrentPageKey = null;
68-
69-
// If `$this->PageKey` does not appear in the query, add it to
70-
// `$this->CurrentQuery` without changing the first request
71-
if (
72-
$this->PageKey !== null
73-
&& !array_key_exists($this->PageKey, $this->CurrentQuery)
74-
) {
75-
$this->CurrentQuery[$this->PageKey] = 1;
76-
}
77-
7864
return $request;
7965
}
8066

@@ -93,26 +79,20 @@ public function getPage(
9379

9480
if ($data && (
9581
$this->PageSize === null
96-
|| $this->PageSize < 1
9782
|| count($data) === $this->PageSize
9883
)) {
99-
if (
100-
$this->PageKey === null
101-
&& !$previousPage
102-
&& $this->CurrentQuery
103-
&& is_int(reset($this->CurrentQuery))
104-
) {
105-
$this->CurrentPageKey = key($this->CurrentQuery);
84+
$key = $this->PageKey;
85+
if ($key === null && $query && Test::isInteger(reset($query))) {
86+
$key = key($query);
10687
}
107-
$key = $this->PageKey ?? $this->CurrentPageKey;
108-
if ($key !== null) {
109-
$this->CurrentQuery[$key]++;
110-
$uri = $request->getUri();
111-
$uri = $curler->replaceQuery($uri, $this->CurrentQuery);
112-
$nextRequest = $request->withUri($uri);
88+
if ($key === null) {
89+
throw new LogicException('No page key and no integer value at query offset 0');
11390
}
91+
$query[$key] ??= 1;
92+
$query[$key]++;
93+
$nextRequest = $curler->replaceQuery($request, $query);
11494
}
11595

116-
return new CurlerPage($data, $nextRequest ?? null);
96+
return new CurlerPage($data, $nextRequest ?? null, $query);
11797
}
11898
}

tests/fixtures/Toolkit/Sync/Provider/MockoonPager.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function getFirstRequest(
2222
$query['limit'] ??= 50;
2323
unset($query['page']);
2424
return new CurlerPageRequest(
25-
$request->withUri($curler->replaceQuery($request->getUri(), $query)),
25+
$curler->replaceQuery($request, $query),
2626
$query,
2727
);
2828
}
@@ -49,7 +49,7 @@ public function getPage(
4949
/** @var array{page?:int} $query */
5050
$query['page'] ??= 1;
5151
$query['page']++;
52-
$nextRequest = $request->withUri($curler->replaceQuery($request->getUri(), $query));
52+
$nextRequest = $curler->replaceQuery($request, $query);
5353
}
5454

5555
return new CurlerPage($data, $nextRequest ?? null, $query, $count, $total);

0 commit comments

Comments
 (0)