Paginator   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 168
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 17
c 3
b 0
f 0
lcom 1
cbo 7
dl 0
loc 168
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A key() 0 4 1
A __construct() 0 13 2
A limitResults() 0 6 1
A rewind() 0 5 1
A valid() 0 5 2
A loadedMaxResults() 0 8 2
A current() 0 8 2
B next() 0 47 6
1
<?php
2
/**
3
 * Paginator.php
4
 *
5
 * @copyright	More in license.md
6
 * @license		http://www.ipublikuj.eu
7
 * @author		Adam Kadlec http://www.ipublikuj.eu
8
 * @package		iPublikuj:Twitter!
9
 * @subpackage	common
10
 * @since		5.0
11
 *
12
 * @date		20.02.15
13
 */
14
15
namespace IPub\Twitter;
16
17
use Nette;
18
19
use IPub;
20
21
/**
22
 * Response paginator
23
 *
24
 * @package		iPublikuj:Twitter!
25
 * @subpackage	common
26
 *
27
 * @author Adam Kadlec <[email protected]>
28
 * @author Filip Procházka <[email protected]>
29
 */
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()
194
	{
195
		return $this->itemCursor + ($this->pageCursor - 1) * $this->perPage;
196
	}
197
}