Skip to content

Commit 8f71963

Browse files
committed
Allow custom labels for all button types, not only current.
1 parent 3203c78 commit 8f71963

File tree

3 files changed

+189
-63
lines changed

3 files changed

+189
-63
lines changed

src/InlineKeyboardPagination.php

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,16 @@ class InlineKeyboardPagination implements InlineKeyboardPaginator
4242
private $command;
4343

4444
/**
45-
* @var string
45+
* @var array
4646
*/
47-
private $wrap_selected_button = '« #VALUE# »';
47+
private $labels = [
48+
'default' => '%d',
49+
'first' => '« %d',
50+
'previous' => '‹ %d',
51+
'current' => '· %d ·',
52+
'next' => '%d ›',
53+
'last' => '%d »',
54+
];
4855

4956
/**
5057
* @inheritdoc
@@ -61,15 +68,21 @@ public function setMaxButtons(int $max_buttons = 5): InlineKeyboardPagination
6168
}
6269

6370
/**
64-
* @inheritdoc
65-
* @throws InlineKeyboardPaginationException
71+
* @return array
6672
*/
67-
public function setWrapSelectedButton(string $wrap_selected_button = '« #VALUE# »'): InlineKeyboardPagination
73+
public function getLabels(): array
6874
{
69-
if (false === strpos($wrap_selected_button, '/#VALUE#/')) {
70-
throw new InlineKeyboardPaginationException('Invalid selected button wrapper');
71-
}
72-
$this->wrap_selected_button = $wrap_selected_button;
75+
return $this->labels;
76+
}
77+
78+
/**
79+
* @param array $labels
80+
*
81+
* @return InlineKeyboardPagination
82+
*/
83+
public function setLabels($labels): InlineKeyboardPagination
84+
{
85+
$this->labels = array_merge($this->labels, $labels);
7386

7487
return $this;
7588
}
@@ -128,7 +141,7 @@ public function setItemsPerPage($items_per_page): InlineKeyboardPagination
128141
* @inheritdoc
129142
* @throws InlineKeyboardPaginationException
130143
*/
131-
public function __construct(array $items, string $command = 'pagination', int $selected_page = 1, int $items_per_page = 3)
144+
public function __construct(array $items, string $command = 'pagination', int $selected_page = 1, int $items_per_page = 5)
132145
{
133146
$this->number_of_pages = $this->countTheNumberOfPage(count($items), $items_per_page);
134147

@@ -143,15 +156,15 @@ public function __construct(array $items, string $command = 'pagination', int $s
143156
* @inheritdoc
144157
* @throws InlineKeyboardPaginationException
145158
*/
146-
public function paginate(int $selected_page = null): array
159+
public function getPagination(int $selected_page = null): array
147160
{
148161
if ($selected_page !== null) {
149162
$this->setSelectedPage($selected_page);
150163
}
151164

152165
return [
153166
'items' => $this->getPreparedItems(),
154-
'keyboard' => $this->generateKeyboard(),
167+
'keyboard' => [$this->generateKeyboard()],
155168
];
156169
}
157170

@@ -163,22 +176,49 @@ protected function generateKeyboard(): array
163176
$buttons = [];
164177

165178
if ($this->number_of_pages > $this->max_buttons) {
166-
$buttons[] = $this->generateButton(1);
179+
$buttons[1] = $this->generateButton(1);
167180

168181
$range = $this->generateRange();
169-
170182
for ($i = $range['from']; $i < $range['to']; $i++) {
171-
$buttons[] = $this->generateButton($i);
183+
$buttons[$i] = $this->generateButton($i);
172184
}
173185

174-
$buttons[] = $this->generateButton($this->number_of_pages);
186+
$buttons[$this->number_of_pages] = $this->generateButton($this->number_of_pages);
175187
} else {
176188
for ($i = 1; $i <= $this->number_of_pages; $i++) {
177-
$buttons[] = $this->generateButton($i);
189+
$buttons[$i] = $this->generateButton($i);
190+
}
191+
}
192+
193+
// Set the correct labels.
194+
foreach ($buttons as $page => &$button) {
195+
$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;
197+
198+
$label_key = 'next';
199+
if ($page === $this->selected_page) {
200+
$label_key = 'current';
201+
} elseif ($in_first_block || $in_last_block) {
202+
$label_key = 'default';
203+
} elseif ($page === 1) {
204+
$label_key = 'first';
205+
} elseif ($page === $this->number_of_pages) {
206+
$label_key = 'last';
207+
} elseif ($page < $this->selected_page) {
208+
$label_key = 'previous';
209+
}
210+
211+
$label = $this->labels[$label_key];
212+
213+
if ($label === '' || $label === null) {
214+
$button = null;
215+
continue;
178216
}
217+
218+
$button['text'] = sprintf($label, $page);
179219
}
180220

181-
return $buttons;
221+
return array_filter($buttons);
182222
}
183223

184224
/**
@@ -217,16 +257,9 @@ protected function generateRange(): array
217257
*/
218258
protected function generateButton(int $next_page): array
219259
{
220-
$label = "$next_page";
221-
$callbackData = $this->generateCallbackData($next_page);
222-
223-
if ($next_page === $this->selected_page) {
224-
$label = str_replace('#VALUE#', $label, $this->wrap_selected_button);
225-
}
226-
227260
return [
228-
'text' => $label,
229-
'callback_data' => $callbackData,
261+
'text' => "$next_page",
262+
'callback_data' => $this->generateCallbackData($next_page),
230263
];
231264
}
232265

src/InlineKeyboardPaginator.php

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,21 @@
1010
interface InlineKeyboardPaginator
1111
{
1212
/**
13-
* @param int $max_buttons
13+
* InlineKeyboardPaginator constructor.
1414
*
15-
* @return InlineKeyboardPagination
15+
* @param array $items
16+
* @param string $command
17+
* @param int $selected_page
18+
* @param int $items_per_page
1619
*/
17-
public function setMaxButtons(int $max_buttons = 5): InlineKeyboardPagination;
20+
public function __construct(array $items, string $command, int $selected_page, int $items_per_page);
1821

1922
/**
20-
* >#VALUE#<, <#VALUE#>, |#VALUE#| etc...
21-
*
22-
* @param string $wrap_selected_button
23+
* @param int $max_buttons
2324
*
2425
* @return InlineKeyboardPagination
2526
*/
26-
public function setWrapSelectedButton(string $wrap_selected_button = '« #VALUE# »'): InlineKeyboardPagination;
27+
public function setMaxButtons(int $max_buttons = 5): InlineKeyboardPagination;
2728

2829
/**
2930
* @param string $command
@@ -39,20 +40,10 @@ public function setCommand(string $command = 'pagination'): InlineKeyboardPagina
3940
*/
4041
public function setSelectedPage(int $selected_page): InlineKeyboardPagination;
4142

42-
/**
43-
* InlineKeyboardPaginator constructor.
44-
*
45-
* @param array $items
46-
* @param string $command
47-
* @param int $selected_page
48-
* @param int $items_per_page
49-
*/
50-
public function __construct(array $items, string $command, int $selected_page, int $items_per_page);
51-
5243
/**
5344
* @param int $selected_page
5445
*
5546
* @return array
5647
*/
57-
public function paginate(int $selected_page = null): array;
48+
public function getPagination(int $selected_page = null): array;
5849
}

tests/InlineKeyboardPaginationTest.php

Lines changed: 120 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ public function testValidConstructor()
4545
{
4646
$ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selected_page, $this->items_per_page);
4747

48-
$data = $ikp->paginate();
48+
$data = $ikp->getPagination();
4949

5050
$this->assertCount($this->items_per_page, $data['items']);
5151
$this->assertArrayHasKey('keyboard', $data);
52-
$this->assertArrayHasKey(0, $data['keyboard']);
53-
$this->assertArrayHasKey('text', $data['keyboard'][0]);
54-
$this->assertStringStartsWith($this->command, $data['keyboard'][0]['callback_data']);
52+
$this->assertArrayHasKey(1, $data['keyboard'][0]);
53+
$this->assertArrayHasKey('text', $data['keyboard'][0][1]);
54+
$this->assertStringStartsWith($this->command, $data['keyboard'][0][1]['callback_data']);
5555
}
5656

5757
/**
@@ -60,17 +60,17 @@ public function testValidConstructor()
6060
public function testInvalidConstructor()
6161
{
6262
$ikp = new InlineKeyboardPagination($this->items, $this->command, 10000, $this->items_per_page);
63-
$ikp->paginate();
63+
$ikp->getPagination();
6464
}
6565

66-
public function testValidPaginate()
66+
public function testValidPagination()
6767
{
6868
$ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selected_page, $this->items_per_page);
6969

7070
$length = (int) ceil(count($this->items) / $this->items_per_page);
7171

7272
for ($i = 1; $i < $length; $i++) {
73-
$ikp->paginate($i);
73+
$ikp->getPagination($i);
7474
}
7575

7676
$this->assertTrue(true);
@@ -79,14 +79,14 @@ public function testValidPaginate()
7979
/**
8080
* @expectedException \TelegramBot\InlineKeyboardPagination\Exceptions\InlineKeyboardPaginationException
8181
*/
82-
public function testInvalidPaginate()
82+
public function testInvalidPagination()
8383
{
8484
$ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selected_page, $this->items_per_page);
8585

8686
$length = (int) ceil(count($this->items) / $this->items_per_page) + 1;
8787

8888
for ($i = $length; $i < $length * 2; $i++) {
89-
$ikp->paginate($i);
89+
$ikp->getPagination($i);
9090
}
9191
}
9292

@@ -97,7 +97,7 @@ public function testInvalidMaxButtons()
9797
{
9898
$ikp = new InlineKeyboardPagination(range(1, 240));
9999
$ikp->setMaxButtons(2);
100-
$ikp->paginate();
100+
$ikp->getPagination();
101101
}
102102

103103
/**
@@ -107,16 +107,118 @@ public function testInvalidSelectedPage()
107107
{
108108
$ikp = new InlineKeyboardPagination(range(1, 240));
109109
$ikp->setSelectedPage(-5);
110-
$ikp->paginate();
110+
$ikp->getPagination();
111111
}
112112

113-
/**
114-
* @expectedException \TelegramBot\InlineKeyboardPagination\Exceptions\InlineKeyboardPaginationException
115-
*/
116-
public function testInvalidWrapSelectedButton()
113+
114+
public function testButtonLabels()
117115
{
118-
$ikp = new InlineKeyboardPagination(range(1, 240));
119-
$ikp->setWrapSelectedButton('$sdlfk$');
120-
$ikp->paginate();
116+
$cbdata = '%s?currentPage=%d&nextPage=%d';
117+
$command = 'cbdata';
118+
$ikp1 = new InlineKeyboardPagination(range(1, 1), $command);
119+
$ikp10 = new InlineKeyboardPagination(range(1, 50), $command);
120+
121+
// current
122+
$keyboard = $ikp1->getPagination(1)['keyboard'];
123+
self::assertAllButtonPropertiesEqual([
124+
['· 1 ·'],
125+
], 'text', $keyboard);
126+
self::assertAllButtonPropertiesEqual([
127+
[
128+
sprintf($cbdata, $command, 1, 1),
129+
],
130+
], 'callback_data', $keyboard);
131+
132+
// first, previous, current, next, last
133+
$keyboard = $ikp10->getPagination(5)['keyboard'];
134+
self::assertAllButtonPropertiesEqual([
135+
['« 1', '‹ 4', '· 5 ·', '6 ›', '10 »'],
136+
], 'text', $keyboard);
137+
self::assertAllButtonPropertiesEqual([
138+
[
139+
sprintf($cbdata, $command, 5, 1),
140+
sprintf($cbdata, $command, 5, 4),
141+
sprintf($cbdata, $command, 5, 5),
142+
sprintf($cbdata, $command, 5, 6),
143+
sprintf($cbdata, $command, 5, 10),
144+
],
145+
], 'callback_data', $keyboard);
146+
147+
// first, previous, current, last
148+
$keyboard = $ikp10->getPagination(9)['keyboard'];
149+
self::assertAllButtonPropertiesEqual([
150+
['« 1', '‹ 7', '8', '· 9 ·', '10'],
151+
], 'text', $keyboard);
152+
self::assertAllButtonPropertiesEqual([
153+
[
154+
sprintf($cbdata, $command, 9, 1),
155+
sprintf($cbdata, $command, 9, 7),
156+
sprintf($cbdata, $command, 9, 8),
157+
sprintf($cbdata, $command, 9, 9),
158+
sprintf($cbdata, $command, 9, 10),
159+
],
160+
], 'callback_data', $keyboard);
161+
162+
// first, previous, current
163+
$keyboard = $ikp10->getPagination(10)['keyboard'];
164+
self::assertAllButtonPropertiesEqual([
165+
['« 1', '‹ 7', '8', '9', '· 10 ·'],
166+
], 'text', $keyboard);
167+
self::assertAllButtonPropertiesEqual([
168+
[
169+
sprintf($cbdata, $command, 10, 1),
170+
sprintf($cbdata, $command, 10, 7),
171+
sprintf($cbdata, $command, 10, 8),
172+
sprintf($cbdata, $command, 10, 9),
173+
sprintf($cbdata, $command, 10, 10),
174+
],
175+
], 'callback_data', $keyboard);
176+
177+
// custom labels, skipping some buttons
178+
// first, previous, current, next, last
179+
$ikp10->setLabels([
180+
'first' => '',
181+
'previous' => 'previous %d',
182+
'current' => null,
183+
'next' => '%d next',
184+
'last' => 'last',
185+
]);
186+
$keyboard = $ikp10->getPagination(5)['keyboard'];
187+
self::assertAllButtonPropertiesEqual([
188+
['previous 4', '6 next', 'last'],
189+
], 'text', $keyboard);
190+
self::assertAllButtonPropertiesEqual([
191+
[
192+
sprintf($cbdata, $command, 5, 4),
193+
sprintf($cbdata, $command, 5, 6),
194+
sprintf($cbdata, $command, 5, 10),
195+
],
196+
], 'callback_data', $keyboard);
197+
}
198+
199+
public static function assertButtonPropertiesEqual($value, $property, $keyboard, $row, $column, $message = '')
200+
{
201+
$row_raw = array_values($keyboard)[$row];
202+
$column_raw = array_values($row_raw)[$column];
203+
204+
self::assertSame($value, $column_raw[$property], $message);
205+
}
206+
207+
public static function assertRowButtonPropertiesEqual(array $values, $property, $keyboard, $row, $message = '')
208+
{
209+
$column = 0;
210+
foreach ($values as $value) {
211+
self::assertButtonPropertiesEqual($value, $property, $keyboard, $row, $column++, $message);
212+
}
213+
self::assertCount(count(array_values($keyboard)[$row]), $values);
214+
}
215+
216+
public static function assertAllButtonPropertiesEqual(array $all_values, $property, $keyboard, $message = '')
217+
{
218+
$row = 0;
219+
foreach ($all_values as $values) {
220+
self::assertRowButtonPropertiesEqual($values, $property, $keyboard, $row++, $message);
221+
}
222+
self::assertCount(count($keyboard), $all_values);
121223
}
122224
}

0 commit comments

Comments
 (0)