Skip to content

Commit f737a03

Browse files
committed
Create simple pagination for inline keyboard.
Simplify (inline) keyboard tests with helpers.
1 parent acfe9d6 commit f737a03

File tree

3 files changed

+324
-119
lines changed

3 files changed

+324
-119
lines changed

src/Entities/InlineKeyboard.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,86 @@
1717
*/
1818
class InlineKeyboard extends Keyboard
1919
{
20+
/**
21+
* Get an inline pagination keyboard.
22+
*
23+
* - $callback_data is an ID for the CallbackqueryCommand, to know where the request comes from.
24+
* It must contain a '%d' placeholder for the page number. If no placeholder is found, the ID is automatically appended with '_page_%d'
25+
*
26+
* - $labels allows for custom button labels, using '%d' placeholders.
27+
* Default:
28+
* ```
29+
* [
30+
* 'first' => '« %d',
31+
* 'previous' => '‹ %d',
32+
* 'current' => '· %d ·',
33+
* 'next' => '%d ›',
34+
* 'last' => '%d »',
35+
* ]
36+
* ``
37+
*`
38+
* initial idea from: https://stackoverflow.com/a/42879866
39+
*
40+
* @param string $callback_data
41+
* @param int $current_page
42+
* @param int $max_pages
43+
* @param array $labels
44+
*
45+
* @return \Longman\TelegramBot\Entities\InlineKeyboard
46+
*/
47+
public static function getPagination($callback_data, $current_page, $max_pages, array $labels = [])
48+
{
49+
if (strpos($callback_data, '%d') === false) {
50+
$callback_data .= '_page_%d';
51+
}
52+
53+
// Merge labels with defaults.
54+
$labels = array_merge([
55+
'first' => '« %d',
56+
'previous' => '‹ %d',
57+
'current' => '· %d ·',
58+
'next' => '%d ›',
59+
'last' => '%d »',
60+
], $labels);
61+
$pages = [
62+
'first' => 1,
63+
'previous' => $current_page - 1,
64+
'current' => $current_page,
65+
'next' => $current_page + 1,
66+
'last' => $max_pages,
67+
];
68+
69+
// Set labels for keyboard, replacing placeholders with page numbers.
70+
foreach ($labels as $key => &$label) {
71+
if (strpos($label, '%d') !== false) {
72+
$label = sprintf($label, $pages[$key]);
73+
}
74+
}
75+
unset($label);
76+
77+
$callbacks_data = [];
78+
foreach ($pages as $key => $page) {
79+
$callbacks_data[$key] = sprintf($callback_data, $page);
80+
}
81+
82+
$buttons = [];
83+
84+
if ($current_page > 1) {
85+
$buttons[] = new InlineKeyboardButton(['text' => $labels['first'], 'callback_data' => $callbacks_data['first']]);
86+
}
87+
if ($current_page > 2) {
88+
$buttons[] = new InlineKeyboardButton(['text' => $labels['previous'], 'callback_data' => $callbacks_data['previous']]);
89+
}
90+
91+
$buttons[] = new InlineKeyboardButton(['text' => $labels['current'], 'callback_data' => $callbacks_data['current']]);
92+
93+
if ($current_page < $max_pages - 1) {
94+
$buttons[] = new InlineKeyboardButton(['text' => $labels['next'], 'callback_data' => $callbacks_data['next']]);
95+
}
96+
if ($current_page < $max_pages) {
97+
$buttons[] = new InlineKeyboardButton(['text' => $labels['last'], 'callback_data' => $callbacks_data['last']]);
98+
}
99+
100+
return new InlineKeyboard($buttons);
101+
}
20102
}

tests/unit/Entities/InlineKeyboardTest.php

Lines changed: 121 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -54,51 +54,60 @@ public function testInlineKeyboardDataMalformedSubfield()
5454

5555
public function testInlineKeyboardSingleButtonSingleRow()
5656
{
57-
$inline_keyboard = (new InlineKeyboard(
57+
$keyboard = new InlineKeyboard(
5858
$this->getRandomButton('Button Text 1')
59-
))->getProperty('inline_keyboard');
60-
self::assertSame('Button Text 1', $inline_keyboard[0][0]->getText());
59+
);
60+
KeyboardTest::assertAllButtonPropertiesEqual([
61+
['Button Text 1'],
62+
], 'text', $keyboard);
6163

62-
$inline_keyboard = (new InlineKeyboard(
64+
$keyboard = new InlineKeyboard(
6365
[$this->getRandomButton('Button Text 2')]
64-
))->getProperty('inline_keyboard');
65-
self::assertSame('Button Text 2', $inline_keyboard[0][0]->getText());
66+
);
67+
KeyboardTest::assertAllButtonPropertiesEqual([
68+
['Button Text 2'],
69+
], 'text', $keyboard);
6670
}
6771

6872
public function testInlineKeyboardSingleButtonMultipleRows()
6973
{
70-
$keyboard = (new InlineKeyboard(
74+
$keyboard = new InlineKeyboard(
7175
$this->getRandomButton('Button Text 1'),
7276
$this->getRandomButton('Button Text 2'),
7377
$this->getRandomButton('Button Text 3')
74-
))->getProperty('inline_keyboard');
75-
self::assertSame('Button Text 1', $keyboard[0][0]->getText());
76-
self::assertSame('Button Text 2', $keyboard[1][0]->getText());
77-
self::assertSame('Button Text 3', $keyboard[2][0]->getText());
78+
);
79+
KeyboardTest::assertAllButtonPropertiesEqual([
80+
['Button Text 1'],
81+
['Button Text 2'],
82+
['Button Text 3'],
83+
], 'text', $keyboard);
7884

79-
$keyboard = (new InlineKeyboard(
85+
$keyboard = new InlineKeyboard(
8086
[$this->getRandomButton('Button Text 4')],
8187
[$this->getRandomButton('Button Text 5')],
8288
[$this->getRandomButton('Button Text 6')]
83-
))->getProperty('inline_keyboard');
84-
self::assertSame('Button Text 4', $keyboard[0][0]->getText());
85-
self::assertSame('Button Text 5', $keyboard[1][0]->getText());
86-
self::assertSame('Button Text 6', $keyboard[2][0]->getText());
89+
);
90+
KeyboardTest::assertAllButtonPropertiesEqual([
91+
['Button Text 4'],
92+
['Button Text 5'],
93+
['Button Text 6'],
94+
], 'text', $keyboard);
8795
}
8896

8997
public function testInlineKeyboardMultipleButtonsSingleRow()
9098
{
91-
$keyboard = (new InlineKeyboard([
99+
$keyboard = new InlineKeyboard([
92100
$this->getRandomButton('Button Text 1'),
93101
$this->getRandomButton('Button Text 2'),
94-
]))->getProperty('inline_keyboard');
95-
self::assertSame('Button Text 1', $keyboard[0][0]->getText());
96-
self::assertSame('Button Text 2', $keyboard[0][1]->getText());
102+
]);
103+
KeyboardTest::assertAllButtonPropertiesEqual([
104+
['Button Text 1', 'Button Text 2'],
105+
], 'text', $keyboard);
97106
}
98107

99108
public function testInlineKeyboardMultipleButtonsMultipleRows()
100109
{
101-
$keyboard = (new InlineKeyboard(
110+
$keyboard = new InlineKeyboard(
102111
[
103112
$this->getRandomButton('Button Text 1'),
104113
$this->getRandomButton('Button Text 2'),
@@ -107,32 +116,107 @@ public function testInlineKeyboardMultipleButtonsMultipleRows()
107116
$this->getRandomButton('Button Text 3'),
108117
$this->getRandomButton('Button Text 4'),
109118
]
110-
))->getProperty('inline_keyboard');
119+
);
111120

112-
self::assertSame('Button Text 1', $keyboard[0][0]->getText());
113-
self::assertSame('Button Text 2', $keyboard[0][1]->getText());
114-
self::assertSame('Button Text 3', $keyboard[1][0]->getText());
115-
self::assertSame('Button Text 4', $keyboard[1][1]->getText());
121+
KeyboardTest::assertAllButtonPropertiesEqual([
122+
['Button Text 1', 'Button Text 2'],
123+
['Button Text 3', 'Button Text 4'],
124+
], 'text', $keyboard);
116125
}
117126

118127
public function testInlineKeyboardAddRows()
119128
{
120-
$keyboard_obj = new InlineKeyboard([]);
129+
$keyboard = new InlineKeyboard([]);
121130

122-
$keyboard_obj->addRow($this->getRandomButton('Button Text 1'));
123-
$keyboard = $keyboard_obj->getProperty('inline_keyboard');
124-
self::assertSame('Button Text 1', $keyboard[0][0]->getText());
131+
$keyboard->addRow($this->getRandomButton('Button Text 1'));
132+
KeyboardTest::assertAllButtonPropertiesEqual([
133+
['Button Text 1'],
134+
], 'text', $keyboard);
125135

126-
$keyboard_obj->addRow(
136+
$keyboard->addRow(
127137
$this->getRandomButton('Button Text 2'),
128138
$this->getRandomButton('Button Text 3')
129139
);
130-
$keyboard = $keyboard_obj->getProperty('inline_keyboard');
131-
self::assertSame('Button Text 2', $keyboard[1][0]->getText());
132-
self::assertSame('Button Text 3', $keyboard[1][1]->getText());
140+
KeyboardTest::assertAllButtonPropertiesEqual([
141+
['Button Text 1'],
142+
['Button Text 2', 'Button Text 3'],
143+
], 'text', $keyboard);
144+
145+
$keyboard->addRow($this->getRandomButton('Button Text 4'));
146+
KeyboardTest::assertAllButtonPropertiesEqual([
147+
['Button Text 1'],
148+
['Button Text 2', 'Button Text 3'],
149+
['Button Text 4'],
150+
], 'text', $keyboard);
151+
}
133152

134-
$keyboard_obj->addRow($this->getRandomButton('Button Text 4'));
135-
$keyboard = $keyboard_obj->getProperty('inline_keyboard');
136-
self::assertSame('Button Text 4', $keyboard[2][0]->getText());
153+
public function testInlineKeyboardPagination()
154+
{
155+
// Should get '_page_%d' appended to it.
156+
$callback_data = 'pagination_callback';
157+
158+
// current
159+
$keyboard = InlineKeyboard::getPagination($callback_data, 1, 1);
160+
KeyboardTest::assertAllButtonPropertiesEqual([
161+
['· 1 ·'],
162+
], 'text', $keyboard);
163+
KeyboardTest::assertAllButtonPropertiesEqual([
164+
['pagination_callback_page_1'],
165+
], 'callback_data', $keyboard);
166+
167+
// Shorter custom callback data.
168+
$callback_data = 'p%d';
169+
170+
// current, next, last
171+
$keyboard = InlineKeyboard::getPagination($callback_data, 1, 10);
172+
KeyboardTest::assertAllButtonPropertiesEqual([
173+
['· 1 ·', '2 ›', '10 »'],
174+
], 'text', $keyboard);
175+
KeyboardTest::assertAllButtonPropertiesEqual([
176+
['p1', 'p2', 'p10'],
177+
], 'callback_data', $keyboard);
178+
179+
// first, previous, current, next, last
180+
$keyboard = InlineKeyboard::getPagination($callback_data, 5, 10);
181+
KeyboardTest::assertAllButtonPropertiesEqual([
182+
['« 1', '‹ 4', '· 5 ·', '6 ›', '10 »'],
183+
], 'text', $keyboard);
184+
KeyboardTest::assertAllButtonPropertiesEqual([
185+
['p1', 'p4', 'p5', 'p6', 'p10'],
186+
], 'callback_data', $keyboard);
187+
188+
// first, previous, current, last
189+
$keyboard = InlineKeyboard::getPagination($callback_data, 9, 10);
190+
KeyboardTest::assertAllButtonPropertiesEqual([
191+
['« 1', '‹ 8', '· 9 ·', '10 »'],
192+
], 'text', $keyboard);
193+
KeyboardTest::assertAllButtonPropertiesEqual([
194+
['p1', 'p8', 'p9', 'p10'],
195+
], 'callback_data', $keyboard);
196+
197+
// first, previous, current
198+
$keyboard = InlineKeyboard::getPagination($callback_data, 10, 10);
199+
KeyboardTest::assertAllButtonPropertiesEqual([
200+
['« 1', '‹ 9', '· 10 ·'],
201+
], 'text', $keyboard);
202+
KeyboardTest::assertAllButtonPropertiesEqual([
203+
['p1', 'p9', 'p10'],
204+
], 'callback_data', $keyboard);
205+
206+
// custom labels
207+
// first, previous, current, next, last
208+
$keyboard = InlineKeyboard::getPagination($callback_data, 5, 10, [
209+
'first' => 'first %d',
210+
'previous' => 'previous %d',
211+
'current' => 'cur %d rent',
212+
'next' => '%d next',
213+
'last' => '%d last',
214+
]);
215+
KeyboardTest::assertAllButtonPropertiesEqual([
216+
['first 1', 'previous 4', 'cur 5 rent', '6 next', '10 last'],
217+
], 'text', $keyboard);
218+
KeyboardTest::assertAllButtonPropertiesEqual([
219+
['p1', 'p4', 'p5', 'p6', 'p10'],
220+
], 'callback_data', $keyboard);
137221
}
138222
}

0 commit comments

Comments
 (0)