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