Skip to content

Commit 07f1168

Browse files
committed
Check exception messages for tests.
Throw exception when empty item list is passed. Allow public querying of number of pages.
1 parent 8f71963 commit 07f1168

File tree

3 files changed

+98
-57
lines changed

3 files changed

+98
-57
lines changed

src/InlineKeyboardPagination.php

Lines changed: 70 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ class InlineKeyboardPagination implements InlineKeyboardPaginator
2626
*/
2727
private $selected_page;
2828

29-
/**
30-
* @var integer
31-
*/
32-
private $number_of_pages;
33-
3429
/**
3530
* @var array
3631
*/
@@ -68,6 +63,8 @@ public function setMaxButtons(int $max_buttons = 5): InlineKeyboardPagination
6863
}
6964

7065
/**
66+
* Return list of keyboard button labels.
67+
*
7168
* @return array
7269
*/
7370
public function getLabels(): array
@@ -76,13 +73,15 @@ public function getLabels(): array
7673
}
7774

7875
/**
76+
* Set the keyboard button labels.
77+
*
7978
* @param array $labels
8079
*
8180
* @return InlineKeyboardPagination
8281
*/
8382
public function setLabels($labels): InlineKeyboardPagination
8483
{
85-
$this->labels = array_merge($this->labels, $labels);
84+
$this->labels = $labels;
8685

8786
return $this;
8887
}
@@ -103,8 +102,9 @@ public function setCommand(string $command = 'pagination'): InlineKeyboardPagina
103102
*/
104103
public function setSelectedPage(int $selected_page): InlineKeyboardPagination
105104
{
106-
if ($selected_page < 1 || $selected_page > $this->number_of_pages) {
107-
throw new InlineKeyboardPaginationException('Invalid selected page, must be between 1 and ' . $this->number_of_pages);
105+
$number_of_pages = $this->getNumberOfPages();
106+
if ($selected_page < 1 || $selected_page > $number_of_pages) {
107+
throw new InlineKeyboardPaginationException('Invalid selected page, must be between 1 and ' . $number_of_pages);
108108
}
109109
$this->selected_page = $selected_page;
110110

@@ -135,6 +135,32 @@ public function setItemsPerPage($items_per_page): InlineKeyboardPagination
135135
return $this;
136136
}
137137

138+
/**
139+
* @param array $items
140+
*
141+
* @return InlineKeyboardPagination
142+
* @throws InlineKeyboardPaginationException
143+
*/
144+
public function setItems(array $items): InlineKeyboardPagination
145+
{
146+
if (empty($items)) {
147+
throw new InlineKeyboardPaginationException('Items list empty.');
148+
}
149+
$this->items = $items;
150+
151+
return $this;
152+
}
153+
154+
/**
155+
* Calculate and return the number of pages.
156+
*
157+
* @return int
158+
*/
159+
public function getNumberOfPages(): int
160+
{
161+
return (int) ceil(count($this->items) / $this->items_per_page);
162+
}
163+
138164
/**
139165
* TelegramBotPagination constructor.
140166
*
@@ -143,13 +169,10 @@ public function setItemsPerPage($items_per_page): InlineKeyboardPagination
143169
*/
144170
public function __construct(array $items, string $command = 'pagination', int $selected_page = 1, int $items_per_page = 5)
145171
{
146-
$this->number_of_pages = $this->countTheNumberOfPage(count($items), $items_per_page);
147-
172+
$this->setCommand($command);
173+
$this->setItemsPerPage($items_per_page);
174+
$this->setItems($items);
148175
$this->setSelectedPage($selected_page);
149-
150-
$this->items = $items;
151-
$this->items_per_page = $items_per_page;
152-
$this->command = $command;
153176
}
154177

155178
/**
@@ -169,31 +192,34 @@ public function getPagination(int $selected_page = null): array
169192
}
170193

171194
/**
195+
* Generate the keyboard with the correctly labelled buttons.
196+
*
172197
* @return array
173198
*/
174199
protected function generateKeyboard(): array
175200
{
176-
$buttons = [];
201+
$buttons = [];
202+
$number_of_pages = $this->getNumberOfPages();
177203

178-
if ($this->number_of_pages > $this->max_buttons) {
204+
if ($number_of_pages > $this->max_buttons) {
179205
$buttons[1] = $this->generateButton(1);
180206

181207
$range = $this->generateRange();
182208
for ($i = $range['from']; $i < $range['to']; $i++) {
183209
$buttons[$i] = $this->generateButton($i);
184210
}
185211

186-
$buttons[$this->number_of_pages] = $this->generateButton($this->number_of_pages);
212+
$buttons[$number_of_pages] = $this->generateButton($number_of_pages);
187213
} else {
188-
for ($i = 1; $i <= $this->number_of_pages; $i++) {
214+
for ($i = 1; $i <= $number_of_pages; $i++) {
189215
$buttons[$i] = $this->generateButton($i);
190216
}
191217
}
192218

193219
// Set the correct labels.
194220
foreach ($buttons as $page => &$button) {
195221
$in_first_block = $this->selected_page <= 3 && $page <= 3;
196-
$in_last_block = $this->selected_page >= $this->number_of_pages - 2 && $page >= $this->number_of_pages - 2;
222+
$in_last_block = $this->selected_page >= $number_of_pages - 2 && $page >= $number_of_pages - 2;
197223

198224
$label_key = 'next';
199225
if ($page === $this->selected_page) {
@@ -202,15 +228,15 @@ protected function generateKeyboard(): array
202228
$label_key = 'default';
203229
} elseif ($page === 1) {
204230
$label_key = 'first';
205-
} elseif ($page === $this->number_of_pages) {
231+
} elseif ($page === $number_of_pages) {
206232
$label_key = 'last';
207233
} elseif ($page < $this->selected_page) {
208234
$label_key = 'previous';
209235
}
210236

211-
$label = $this->labels[$label_key];
237+
$label = $this->labels[$label_key] ?? '';
212238

213-
if ($label === '' || $label === null) {
239+
if ($label === '') {
214240
$button = null;
215241
continue;
216242
}
@@ -222,22 +248,25 @@ protected function generateKeyboard(): array
222248
}
223249

224250
/**
251+
* Get the range of intermediate buttons for the keyboard.
252+
*
225253
* @return array
226254
*/
227255
protected function generateRange(): array
228256
{
229257
$number_of_intermediate_buttons = $this->max_buttons - 2;
258+
$number_of_pages = $this->getNumberOfPages();
230259

231260
if ($this->selected_page === 1) {
232261
$from = 2;
233262
$to = $from + $number_of_intermediate_buttons;
234-
} elseif ($this->selected_page === $this->number_of_pages) {
235-
$from = $this->number_of_pages - $number_of_intermediate_buttons;
236-
$to = $this->number_of_pages;
263+
} elseif ($this->selected_page === $number_of_pages) {
264+
$from = $number_of_pages - $number_of_intermediate_buttons;
265+
$to = $number_of_pages;
237266
} else {
238-
if (($this->selected_page + $number_of_intermediate_buttons) > $this->number_of_pages) {
239-
$from = $this->number_of_pages - $number_of_intermediate_buttons;
240-
$to = $this->number_of_pages;
267+
if (($this->selected_page + $number_of_intermediate_buttons) > $number_of_pages) {
268+
$from = $number_of_pages - $number_of_intermediate_buttons;
269+
$to = $number_of_pages;
241270
} elseif (($this->selected_page - 2) < 1) {
242271
$from = $this->selected_page;
243272
$to = $this->selected_page + $number_of_intermediate_buttons;
@@ -251,29 +280,35 @@ protected function generateRange(): array
251280
}
252281

253282
/**
254-
* @param int $next_page
283+
* Generate the button for the passed page.
284+
*
285+
* @param int $page
255286
*
256287
* @return array
257288
*/
258-
protected function generateButton(int $next_page): array
289+
protected function generateButton(int $page): array
259290
{
260291
return [
261-
'text' => "$next_page",
262-
'callback_data' => $this->generateCallbackData($next_page),
292+
'text' => (string) $page,
293+
'callback_data' => $this->generateCallbackData($page),
263294
];
264295
}
265296

266297
/**
267-
* @param int $next_page
298+
* Generate the callback data for the passed page.
299+
*
300+
* @param int $page
268301
*
269302
* @return string
270303
*/
271-
protected function generateCallbackData(int $next_page): string
304+
protected function generateCallbackData(int $page): string
272305
{
273-
return "$this->command?currentPage=$this->selected_page&nextPage=$next_page";
306+
return "{$this->command}?currentPage={$this->selected_page}&nextPage={$page}";
274307
}
275308

276309
/**
310+
* Get the prepared items for the selected page.
311+
*
277312
* @return array
278313
*/
279314
protected function getPreparedItems(): array
@@ -288,15 +323,4 @@ protected function getOffset(): int
288323
{
289324
return $this->items_per_page * ($this->selected_page - 1);
290325
}
291-
292-
/**
293-
* @param $items_count
294-
* @param $items_per_page
295-
*
296-
* @return int
297-
*/
298-
protected function countTheNumberOfPage($items_count, $items_per_page): int
299-
{
300-
return (int) ceil($items_count / $items_per_page);
301-
}
302326
}

src/InlineKeyboardPaginator.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,35 @@ interface InlineKeyboardPaginator
2020
public function __construct(array $items, string $command, int $selected_page, int $items_per_page);
2121

2222
/**
23+
* Set the maximum number of keyboard buttons to show.
24+
*
2325
* @param int $max_buttons
2426
*
2527
* @return InlineKeyboardPagination
2628
*/
2729
public function setMaxButtons(int $max_buttons = 5): InlineKeyboardPagination;
2830

2931
/**
32+
* Set command for this pagination.
33+
*
3034
* @param string $command
3135
*
3236
* @return InlineKeyboardPagination
3337
*/
3438
public function setCommand(string $command = 'pagination'): InlineKeyboardPagination;
3539

3640
/**
41+
* Set the selected page.
42+
*
3743
* @param int $selected_page
3844
*
3945
* @return InlineKeyboardPagination
4046
*/
4147
public function setSelectedPage(int $selected_page): InlineKeyboardPagination;
4248

4349
/**
50+
* Get the pagination data for the passed page.
51+
*
4452
* @param int $selected_page
4553
*
4654
* @return array

tests/InlineKeyboardPaginationTest.php

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public function testValidConstructor()
4747

4848
$data = $ikp->getPagination();
4949

50+
$this->assertArrayHasKey('items', $data);
5051
$this->assertCount($this->items_per_page, $data['items']);
5152
$this->assertArrayHasKey('keyboard', $data);
5253
$this->assertArrayHasKey(1, $data['keyboard'][0]);
@@ -56,13 +57,24 @@ public function testValidConstructor()
5657

5758
/**
5859
* @expectedException \TelegramBot\InlineKeyboardPagination\Exceptions\InlineKeyboardPaginationException
60+
* @expectedExceptionMessage Invalid selected page, must be between 1 and 20
5961
*/
6062
public function testInvalidConstructor()
6163
{
6264
$ikp = new InlineKeyboardPagination($this->items, $this->command, 10000, $this->items_per_page);
6365
$ikp->getPagination();
6466
}
6567

68+
/**
69+
* @expectedException \TelegramBot\InlineKeyboardPagination\Exceptions\InlineKeyboardPaginationException
70+
* @expectedExceptionMessage Items list empty.
71+
*/
72+
public function testEmptyItemsConstructor()
73+
{
74+
$ikp = new InlineKeyboardPagination([]);
75+
$ikp->getPagination();
76+
}
77+
6678
public function testValidPagination()
6779
{
6880
$ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selected_page, $this->items_per_page);
@@ -78,45 +90,42 @@ public function testValidPagination()
7890

7991
/**
8092
* @expectedException \TelegramBot\InlineKeyboardPagination\Exceptions\InlineKeyboardPaginationException
93+
* @expectedExceptionMessage Invalid selected page, must be between 1 and 20
8194
*/
8295
public function testInvalidPagination()
8396
{
8497
$ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selected_page, $this->items_per_page);
85-
86-
$length = (int) ceil(count($this->items) / $this->items_per_page) + 1;
87-
88-
for ($i = $length; $i < $length * 2; $i++) {
89-
$ikp->getPagination($i);
90-
}
98+
$ikp->getPagination($ikp->getNumberOfPages() + 1);
9199
}
92100

93101
/**
94102
* @expectedException \TelegramBot\InlineKeyboardPagination\Exceptions\InlineKeyboardPaginationException
103+
* @expectedExceptionMessage Invalid max buttons, must be between 5 and 8.
95104
*/
96105
public function testInvalidMaxButtons()
97106
{
98-
$ikp = new InlineKeyboardPagination(range(1, 240));
107+
$ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selected_page, $this->items_per_page);
99108
$ikp->setMaxButtons(2);
100109
$ikp->getPagination();
101110
}
102111

103112
/**
104113
* @expectedException \TelegramBot\InlineKeyboardPagination\Exceptions\InlineKeyboardPaginationException
114+
* @expectedExceptionMessage Invalid selected page, must be between 1 and 20
105115
*/
106116
public function testInvalidSelectedPage()
107117
{
108-
$ikp = new InlineKeyboardPagination(range(1, 240));
118+
$ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selected_page, $this->items_per_page);
109119
$ikp->setSelectedPage(-5);
110120
$ikp->getPagination();
111121
}
112122

113-
114123
public function testButtonLabels()
115124
{
116125
$cbdata = '%s?currentPage=%d&nextPage=%d';
117126
$command = 'cbdata';
118-
$ikp1 = new InlineKeyboardPagination(range(1, 1), $command);
119-
$ikp10 = new InlineKeyboardPagination(range(1, 50), $command);
127+
$ikp1 = new InlineKeyboardPagination(range(1, 1), $command, 1, $this->items_per_page);
128+
$ikp10 = new InlineKeyboardPagination(range(1, $this->items_per_page * 10), $command, 1, $this->items_per_page);
120129

121130
// current
122131
$keyboard = $ikp1->getPagination(1)['keyboard'];

0 commit comments

Comments
 (0)