1: <?php declare(strict_types=1);
2:
3: namespace Salient\Curler\Pager;
4:
5: use Psr\Http\Message\RequestInterface;
6: use Salient\Contract\Curler\CurlerInterface;
7: use Salient\Contract\Curler\CurlerPageInterface;
8: use Salient\Contract\Curler\CurlerPagerInterface;
9: use Salient\Contract\Http\HttpHeader;
10: use Salient\Contract\Http\HttpResponseInterface;
11: use Salient\Curler\CurlerPage;
12: use Salient\Http\HttpHeaders;
13: use Salient\Http\Uri;
14: use Salient\Utility\Exception\InvalidArgumentTypeException;
15:
16: /**
17: * Follows OData "nextLink" annotations in responses from the endpoint
18: *
19: * @api
20: */
21: final class ODataPager implements CurlerPagerInterface
22: {
23: private ?int $MaxPageSize;
24:
25: /**
26: * Creates a new ODataPager object
27: */
28: public function __construct(?int $maxPageSize = null)
29: {
30: $this->MaxPageSize = $maxPageSize;
31: }
32:
33: /**
34: * @inheritDoc
35: */
36: public function getFirstRequest(
37: RequestInterface $request,
38: CurlerInterface $curler,
39: ?array $query = null
40: ): RequestInterface {
41: if ($this->MaxPageSize === null) {
42: return $request;
43: }
44:
45: $prefs = HttpHeaders::from($request)->getPreferences();
46: if (
47: isset($prefs['odata.maxpagesize'])
48: && $prefs['odata.maxpagesize']['value'] === (string) $this->MaxPageSize
49: ) {
50: return $request;
51: }
52:
53: $prefs['odata.maxpagesize']['value'] = (string) $this->MaxPageSize;
54:
55: return $request->withHeader(
56: HttpHeader::PREFER,
57: HttpHeaders::mergePreferences($prefs),
58: );
59: }
60:
61: /**
62: * @inheritDoc
63: */
64: public function getPage(
65: $data,
66: RequestInterface $request,
67: HttpResponseInterface $response,
68: CurlerInterface $curler,
69: ?CurlerPageInterface $previousPage = null,
70: ?array $query = null
71: ): CurlerPageInterface {
72: if (!is_array($data)) {
73: throw new InvalidArgumentTypeException(1, 'data', 'mixed[]', $data);
74: }
75: /** @var array{'@odata.nextLink'?:string,'@nextLink'?:string,value:list<mixed>,...} $data */
76: if ($response->getHeaderLine(HttpHeader::ODATA_VERSION) === '4.0') {
77: $nextLink = $data['@odata.nextLink'] ?? null;
78: } else {
79: $nextLink = $data['@nextLink'] ?? $data['@odata.nextLink'] ?? null;
80: }
81:
82: return new CurlerPage(
83: $data['value'],
84: $nextLink === null
85: ? null
86: : $request->withUri(new Uri($nextLink))
87: );
88: }
89: }
90: