diff --git a/docs/content/en/features/keyboards.md b/docs/content/en/features/keyboards.md index 494d95027..e9b4bcb81 100644 --- a/docs/content/en/features/keyboards.md +++ b/docs/content/en/features/keyboards.md @@ -199,3 +199,22 @@ Keyboard::make() ->button('Dismiss')->action('dismiss')->param('id', '42')->width(0.5) ->when($userCanDelete, fn(Keyboard $keyboard) => $keyboard->button('Delete')->action('delete')->param('id', '42')->width(0.5)) ``` + +## Right to left layout + +A `rightToLeft` method allows to change buttons layout from left-to-right to right-to-left (RTL). + +```php +use DefStudio\Telegraph\Keyboard\Button; +use DefStudio\Telegraph\Keyboard\Keyboard; + +$keyboard = Keyboard::make() + ->row([ + Button::make('Delete')->action('delete')->param('id', '42'), + Button::make('Dismiss')->action('dismiss')->param('id', '42'), + ]) + ->row([ + Button::make('open')->url('https://test.it'), + ]) + ->rightToLeft(); +``` diff --git a/src/Keyboard/Keyboard.php b/src/Keyboard/Keyboard.php index 4abad31a6..2f035c1c7 100644 --- a/src/Keyboard/Keyboard.php +++ b/src/Keyboard/Keyboard.php @@ -12,6 +12,8 @@ class Keyboard implements Arrayable /** @var Collection */ protected Collection $buttons; + protected bool $rtl = false; + public function __construct() { /* @phpstan-ignore-next-line */ @@ -35,6 +37,13 @@ public function when(bool $condition, callable $callback): Keyboard return $this; } + public function rightToLeft(bool $condition = true): Keyboard + { + $this->rtl = $condition; + + return $this; + } + protected function clone(): Keyboard { $clone = Keyboard::make(); @@ -222,6 +231,6 @@ public function toArray(): array $keyboard[] = $row; - return $keyboard; + return $this->rtl ? array_map('array_reverse', $keyboard) : $keyboard; } } diff --git a/src/Keyboard/ReplyKeyboard.php b/src/Keyboard/ReplyKeyboard.php index d6774177d..86b7d60c6 100644 --- a/src/Keyboard/ReplyKeyboard.php +++ b/src/Keyboard/ReplyKeyboard.php @@ -13,6 +13,7 @@ class ReplyKeyboard implements Arrayable /** @var Collection */ protected Collection $buttons; + protected bool $rtl = false; protected bool $resize = false; protected bool $oneTime = false; protected bool $selective = false; @@ -41,6 +42,13 @@ public function when(bool $condition, callable $callback): self return $this; } + public function rightToLeft(bool $condition = true): self + { + $this->rtl = $condition; + + return $this; + } + protected function clone(): self { $clone = self::make(); @@ -265,7 +273,7 @@ public function toArray(): array $keyboard[] = $row; - return $keyboard; + return $this->rtl ? array_map('array_reverse', $keyboard) : $keyboard; } /** diff --git a/tests/Unit/Keyboards/KeyboardTest.php b/tests/Unit/Keyboards/KeyboardTest.php index 38bf3edb7..bd7cda7de 100644 --- a/tests/Unit/Keyboards/KeyboardTest.php +++ b/tests/Unit/Keyboards/KeyboardTest.php @@ -186,3 +186,28 @@ ], ]); }); + +it('can right to left layout for buttons', function () { + $keyboard = Keyboard::make() + ->row([ + Button::make('foo')->url('bar'), + Button::make('baz')->action('quuz'), + ]) + ->row([ + Button::make('baz')->action('quuz'), + Button::make('foo')->url('bar'), + ]); + + $keyboard->rightToLeft(); + + expect($keyboard->toArray())->toMatchArray([ + [ + ['text' => 'baz', 'callback_data' => 'action:quuz'], + ['text' => 'foo', 'url' => 'bar'], + ], + [ + ['text' => 'foo', 'url' => 'bar'], + ['text' => 'baz', 'callback_data' => 'action:quuz'], + ], + ]); +}); diff --git a/tests/Unit/Keyboards/ReplyKeyboardTest.php b/tests/Unit/Keyboards/ReplyKeyboardTest.php index 857371cc7..9bf202867 100644 --- a/tests/Unit/Keyboards/ReplyKeyboardTest.php +++ b/tests/Unit/Keyboards/ReplyKeyboardTest.php @@ -167,3 +167,30 @@ ], ]); }); + +it('can right to left layout for buttons', function () { + $keyboard = ReplyKeyboard::make() + ->row([ + ReplyButton::make('quzz')->requestLocation(), + ReplyButton::make('baz')->requestPoll(), + ReplyButton::make('foo'), + ]) + ->row([ + ReplyButton::make('foo'), + ReplyButton::make('baz')->requestLocation(), + ]); + + $keyboard->rightToLeft(); + + expect($keyboard->toArray())->toMatchArray([ + [ + ['text' => 'foo'], + ['text' => 'baz', 'request_poll' => ['type' => 'regular']], + ['text' => 'quzz', 'request_location' => true], + ], + [ + ['text' => 'baz', 'request_location' => true], + ['text' => 'foo'], + ], + ]); +});