1 | <?php |
||
30 | class Paginator extends Nette\Object implements \Iterator |
||
31 | { |
||
32 | const PER_PAGE_MAX = 100; |
||
33 | |||
34 | /** |
||
35 | * @var ApiCall |
||
36 | */ |
||
37 | private $client; |
||
38 | |||
39 | /** |
||
40 | * @var IPub\OAuth\HttpClient |
||
41 | */ |
||
42 | private $httpClient; |
||
43 | |||
44 | /** |
||
45 | * @var int |
||
46 | */ |
||
47 | private $firstPage = 1; |
||
48 | |||
49 | /** |
||
50 | * @var int |
||
51 | */ |
||
52 | private $perPage; |
||
53 | |||
54 | /** |
||
55 | * @var int|NULL |
||
56 | */ |
||
57 | private $maxResults; |
||
58 | |||
59 | /** |
||
60 | * @var array |
||
61 | */ |
||
62 | private $resources = []; |
||
63 | |||
64 | /** |
||
65 | * @var IPub\OAuth\Api\Response[] |
||
66 | */ |
||
67 | private $responses = []; |
||
68 | |||
69 | /** |
||
70 | * @var int |
||
71 | */ |
||
72 | private $itemCursor; |
||
73 | |||
74 | /** |
||
75 | * @var int |
||
76 | */ |
||
77 | private $pageCursor; |
||
78 | |||
79 | /** |
||
80 | * @param ApiCall $client |
||
81 | * @param IPub\OAuth\Api\Response $response |
||
82 | */ |
||
83 | public function __construct(ApiCall $client, IPub\OAuth\Api\Response $response) |
||
84 | { |
||
85 | $this->client = $client; |
||
86 | |||
87 | $this->httpClient = $client->getHttpClient(); |
||
88 | $resource = $response->toArray(); |
||
89 | |||
90 | $params = $response->request->getParameters(); |
||
91 | $this->perPage = isset($params['count']) ? (int) $params['count'] : count($resource); |
||
92 | |||
93 | $this->responses[$this->firstPage] = $response; |
||
94 | $this->resources[$this->firstPage] = $resource; |
||
95 | } |
||
96 | |||
97 | /** |
||
98 | * If you setup maximum number of results, the pagination will stop after fetching the desired number. |
||
99 | * If you have count=50 and wan't to fetch 200 results, it will make 4 requests in total. |
||
100 | * |
||
101 | * @param int $maxResults |
||
102 | * |
||
103 | * @return $this |
||
104 | */ |
||
105 | public function limitResults($maxResults) |
||
106 | { |
||
107 | $this->maxResults = (int)$maxResults; |
||
108 | |||
109 | return $this; |
||
110 | } |
||
111 | |||
112 | public function rewind() |
||
113 | { |
||
114 | $this->itemCursor = 0; |
||
115 | $this->pageCursor = $this->firstPage; |
||
116 | } |
||
117 | |||
118 | public function valid() |
||
119 | { |
||
120 | return isset($this->resources[$this->pageCursor][$this->itemCursor]) |
||
121 | && ! $this->loadedMaxResults(); |
||
122 | } |
||
123 | |||
124 | /** |
||
125 | * @return bool |
||
126 | */ |
||
127 | public function loadedMaxResults() |
||
128 | { |
||
129 | if ($this->maxResults === NULL) { |
||
130 | return FALSE; |
||
131 | } |
||
132 | |||
133 | return $this->maxResults <= ($this->itemCursor + ($this->pageCursor - $this->firstPage) * $this->perPage); |
||
134 | } |
||
135 | |||
136 | public function current() |
||
137 | { |
||
138 | if (!$this->valid()) { |
||
139 | return NULL; |
||
140 | } |
||
141 | |||
142 | return Nette\Utils\ArrayHash::from($this->resources[$this->pageCursor][$this->itemCursor]); |
||
143 | } |
||
144 | |||
145 | public function next() |
||
146 | { |
||
147 | $this->itemCursor++; |
||
148 | |||
149 | // if cursor points at result of next page, try to load it |
||
150 | if ($this->itemCursor < $this->perPage || $this->itemCursor % $this->perPage !== 0) { |
||
151 | return; |
||
152 | } |
||
153 | |||
154 | if (isset($this->resources[$this->pageCursor + 1])) { // already loaded |
||
155 | $this->itemCursor = 0; |
||
156 | $this->pageCursor++; |
||
157 | |||
158 | return; |
||
159 | } |
||
160 | |||
161 | if ($this->loadedMaxResults()) { |
||
162 | return; |
||
163 | } |
||
164 | |||
165 | try { |
||
166 | $prevRequest = $this->responses[$this->pageCursor]->getRequest(); |
||
167 | |||
168 | // Get all request parameters |
||
169 | $params = $this->responses[$this->pageCursor]->request->getParameters(); |
||
170 | // Get last record |
||
171 | $current = Nette\Utils\ArrayHash::from($this->resources[$this->pageCursor][$this->itemCursor-1]); |
||
172 | // And set maximum ID |
||
173 | $params['max_id'] = $current->id; |
||
174 | // Get requested path |
||
175 | $path = $prevRequest->getUrl()->getPath(); |
||
176 | $path = ltrim($path, '/1.1/'); |
||
177 | |||
178 | $response = $this->httpClient->makeRequest( |
||
179 | $prevRequest->copyWithUrl($this->client->getConfig()->createUrl('api', $path, $params)), |
||
180 | 'HMAC-SHA1' |
||
181 | ); |
||
182 | |||
183 | $this->itemCursor = 0; |
||
184 | $this->pageCursor++; |
||
185 | $this->responses[$this->pageCursor] = $response; |
||
186 | $this->resources[$this->pageCursor] = $response->toArray(); |
||
187 | |||
188 | } catch (\Exception $e) { |
||
189 | $this->itemCursor--; // revert back so the user can continue if needed |
||
190 | } |
||
191 | } |
||
192 | |||
193 | public function key() |
||
197 | } |