diff --git a/.gitignore b/.gitignore index cad2986..fdac767 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ /.idea +/.phpunit.result.cache /composer.phar -/vendor/ +/coverage.xml +/phpcs.xml /phpunit.xml -.phpunit.result.cache +/vendor/ diff --git a/.scrutinizer.yml b/.scrutinizer.yml index a0392c1..eadddd6 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -1,18 +1,12 @@ -filter: - paths: [src/*] +build: + environment: + php: 7.3.0 + nodes: + analysis: + tests: + override: + - php-scrutinizer-run -checks: - php: - remove_extra_empty_lines: true - remove_php_closing_tag: true - remove_trailing_whitespace: true - fix_use_statements: - remove_unused: true - preserve_multiple: false - preserve_blanklines: true - order_alphabetically: true - fix_php_opening_tag: true - fix_linefeed: true - fix_line_ending: true - fix_identation_4spaces: true - fix_doc_comments: true +filter: + paths: + - src/ diff --git a/.travis.yml b/.travis.yml index fe7fd52..ba3dc9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,20 +4,18 @@ language: php cache: directories: - - "$HOME/.composer/cache" + - vendor + - $HOME/.composer/cache php: - 7.3 - 7.4 - 8.0 - nightly - - hhvm - -matrix: +jobs: allow_failures: - php: nightly - - php: hhvm fast_finish: true notifications: @@ -34,5 +32,5 @@ script: - composer check-code - if [ "$TRAVIS_PHP_VERSION" == "8.0" ]; then composer test-cov; else composer test; fi -after_script: +after_success: - if [ "$TRAVIS_PHP_VERSION" == "8.0" ]; then composer test-cov-upload; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index f4a049e..7d5e51d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,15 @@ Exclamation symbols (:exclamation:) note something of importance e.g. breaking c ## [Unreleased] ### Added +- Bump minimum PHP to 7.3 and support PHP 8. (@MyZik) (#8) ### Changed +- Bump development dependencies, update tests. +- Improve all development configurations. ### Deprecated ### Removed ### Fixed ### Security +- Minimum PHP 7.3. (@MyZik) (#8) ## [0.1.0] - 2017-09-08 ### Added diff --git a/README.md b/README.md index dd4e13e..0fedf87 100644 --- a/README.md +++ b/README.md @@ -19,18 +19,20 @@ ## Installation ### Composer + ```bash -composer require php-telegram-bot/inline-keyboard-pagination:^1.0.0 +composer require php-telegram-bot/inline-keyboard-pagination ``` ## Usage ### Test Data + ```php -$items = range(1, 100); // required. -$command = 'testCommand'; // optional. Default: pagination +$items = range(1, 100); // required. +$command = 'testCommand'; // optional. Default: pagination $selectedPage = 10; // optional. Default: 1 -$labels = [ // optional. Change button labels (showing defaults) +$labels = [ // optional. Change button labels (showing defaults) 'default' => '%d', 'first' => '« %d', 'previous' => '‹ %d', @@ -44,6 +46,7 @@ $callbackDataFormat = 'command={COMMAND}&oldPage={OLD_PAGE}&newPage={NEW_PAGE}' ``` ### How To Use + ```php // Define inline keyboard pagination. $ikp = new InlineKeyboardPagination($items, $command); @@ -68,7 +71,7 @@ if (!empty($pagination['keyboard'])) { //$pagination['keyboard'][1]['callback_data']; // command=testCommand&oldPage=10&newPage=7 ... - $data['reply_markup' => [ + $data['reply_markup'] = [ 'inline_keyboard' => [ $pagination['keyboard'], ], @@ -78,6 +81,7 @@ if (!empty($pagination['keyboard'])) { ``` To get the callback data, you can use the provided helper method (only works when using the default callback data format): + ```php // e.g. Callback data. $callback_data = 'command=testCommand&oldPage=10&newPage=1'; @@ -96,7 +100,7 @@ parse_str($callbackData, $params); ## Code Quality -Run the PHPUnit tests via Composer script. +Run the PHPUnit tests via Composer script. ```bash composer test @@ -118,7 +122,7 @@ Project based on [Telegram Bot Pagination][github-lartie-tbp] by [lartie][github [code-coverage-badge]: https://img.shields.io/codecov/c/github/php-telegram-bot/inline-keyboard-pagination.svg [code-coverage]: https://codecov.io/gh/php-telegram-bot/inline-keyboard-pagination "Code coverage on Codecov" [build-status-badge]: https://img.shields.io/travis/php-telegram-bot/inline-keyboard-pagination.svg -[build-status]: https://travis-ci.org/php-telegram-bot/inline-keyboard-pagination "Build status on Travis-CI" +[build-status]: https://travis-ci.com/php-telegram-bot/inline-keyboard-pagination "Build status on Travis-CI" [latest-version-badge]: https://img.shields.io/packagist/v/php-telegram-bot/inline-keyboard-pagination.svg [total-downloads-badge]: https://img.shields.io/packagist/dt/php-telegram-bot/inline-keyboard-pagination.svg diff --git a/composer.json b/composer.json index d876d29..9f63fd7 100644 --- a/composer.json +++ b/composer.json @@ -27,10 +27,9 @@ "php": "^7.3|^8.0" }, "require-dev": { - "jakub-onderka/php-parallel-lint": "^0.9.2", - "php-parallel-lint/php-parallel-lint": "v1.2.0", - "phpunit/phpunit": "^9.5.2", - "squizlabs/php_codesniffer": "^3.0" + "php-parallel-lint/php-parallel-lint": "v1.2", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.5" }, "autoload": { "psr-4": { @@ -45,13 +44,14 @@ "scripts": { "check-code": [ "vendor/bin/parallel-lint . --exclude vendor", - "vendor/bin/phpcs src/ tests/ -snp --standard=psr2 --encoding=utf-8 --report-width=150" + "vendor/bin/phpcs" ], "test": [ "vendor/bin/phpunit" ], "test-cov": [ - "vendor/bin/phpunit --coverage-clover=clover.xml" + "@putenv XDEBUG_MODE=coverage", + "vendor/bin/phpunit --coverage-clover coverage.xml" ], "test-cov-upload": [ "curl -s https://codecov.io/bash | bash" diff --git a/composer.lock b/composer.lock index 4e86a08..773427a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "855a1c750118cb30be08e825719ec123", + "content-hash": "87efc59c2d63899439d5e2f79c9748d0", "packages": [], "packages-dev": [ { @@ -2026,7 +2026,7 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.22.0", + "version": "v1.22.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -2085,7 +2085,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" }, "funding": [ { diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..68127a2 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,16 @@ + + + PHP Code Sniffer + + + + + + + + + src/ + tests/ + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 51753f4..3d7f024 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,25 +1,16 @@ - + + + + ./src + + + ./src/Exception + + - ./tests + ./tests - - - ./src - - diff --git a/src/InlineKeyboardPagination.php b/src/InlineKeyboardPagination.php index 860f154..c4d8f0d 100644 --- a/src/InlineKeyboardPagination.php +++ b/src/InlineKeyboardPagination.php @@ -206,7 +206,7 @@ public function setItems(array $items): InlineKeyboardPagination */ public function getNumberOfPages(): int { - return (int)ceil(count($this->items) / $this->itemsPerPage); + return (int) ceil(count($this->items) / $this->itemsPerPage); } /** @@ -309,31 +309,28 @@ protected function generateRange(): array $numberOfIntermediateButtons = $this->maxButtons - 2; $numberOfPages = $this->getNumberOfPages(); + // @todo: Find a nicer solution for page 3 + $from = $this->selectedPage - 1; + $to = $this->selectedPage + ($this->selectedPage === 3 ? $numberOfIntermediateButtons - 1 : 2); + if ($this->selectedPage === 1) { $from = 2; $to = $this->maxButtons; } elseif ($this->selectedPage === $numberOfPages) { $from = $numberOfPages - $numberOfIntermediateButtons; $to = $numberOfPages; - } else { - if ($this->selectedPage < 3) { - $from = $this->selectedPage; - $to = $this->selectedPage + $numberOfIntermediateButtons; - } elseif (($numberOfPages - $this->selectedPage) < 3) { - $from = $numberOfPages - $numberOfIntermediateButtons; - $to = $numberOfPages; - } else { - // @todo: Find a nicer solution for page 3 - if ($this->forceButtonCount) { - $from = $this->selectedPage - floor($numberOfIntermediateButtons / 2); - $to = $this->selectedPage + ceil( - $numberOfIntermediateButtons / 2 - ) + ($this->selectedPage === 3 && $this->maxButtons > 5); - } else { - $from = $this->selectedPage - 1; - $to = $this->selectedPage + ($this->selectedPage === 3 ? $numberOfIntermediateButtons - 1 : 2); - } - } + } elseif ($this->selectedPage < 3) { + $from = $this->selectedPage; + $to = $this->selectedPage + $numberOfIntermediateButtons; + } elseif (($numberOfPages - $this->selectedPage) < 3) { + $from = $numberOfPages - $numberOfIntermediateButtons; + $to = $numberOfPages; + } elseif ($this->forceButtonCount) { + $from = $this->selectedPage - + floor($numberOfIntermediateButtons / 2); + $to = $this->selectedPage + + ceil($numberOfIntermediateButtons / 2) + + (int) ($this->selectedPage === 3 && $this->maxButtons > 5); } return compact('from', 'to'); @@ -349,7 +346,7 @@ protected function generateRange(): array protected function generateButton(int $page): array { return [ - 'text' => (string)$page, + 'text' => (string) $page, 'callback_data' => $this->generateCallbackData($page), ]; } @@ -393,10 +390,11 @@ protected function getOffset(): int /** * Get the parameters from the callback query. * + * @todo Possibly make it work for custom formats too? + * * @param string $data * * @return array - * @todo Possibly make it work for custom formats too? */ public static function getParametersFromCallbackData(string $data): array { diff --git a/tests/InlineKeyboardPaginationTest.php b/tests/InlineKeyboardPaginationTest.php index 87751a5..b3c81ef 100644 --- a/tests/InlineKeyboardPaginationTest.php +++ b/tests/InlineKeyboardPaginationTest.php @@ -36,13 +36,13 @@ public function __construct() { parent::__construct(); - $this->items = range(1, 100); - $this->command = 'testCommand'; + $this->items = range(1, 100); + $this->command = 'testCommand'; $this->selectedPage = random_int(1, 15); } - public function testValidConstructor() + public function testValidConstructor(): void { $ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selectedPage, $this->itemsPerPage); @@ -56,7 +56,7 @@ public function testValidConstructor() self::assertStringStartsWith("command={$this->command}", $data['keyboard'][0]['callback_data']); } - public function testInvalidConstructor() + public function testInvalidConstructor(): void { $this->expectException( \TelegramBot\InlineKeyboardPagination\Exceptions\InlineKeyboardPaginationException::class @@ -67,7 +67,7 @@ public function testInvalidConstructor() $ikp->getPagination(); } - public function testEmptyItemsConstructor() + public function testEmptyItemsConstructor(): void { $this->expectExceptionMessage("Items list empty."); $this->expectException( @@ -78,7 +78,7 @@ public function testEmptyItemsConstructor() $ikp->getPagination(); } - public function testCallbackDataFormat() + public function testCallbackDataFormat(): void { $ikp = new InlineKeyboardPagination(range(1, 10), 'cmd', 2, 5); @@ -99,7 +99,7 @@ public function testCallbackDataFormat() ], 'callback_data', [$ikp->getPagination()['keyboard']]); } - public function testCallbackDataParser() + public function testCallbackDataParser(): void { $ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selectedPage, $this->itemsPerPage); $data = $ikp->getPagination(); @@ -108,12 +108,12 @@ public function testCallbackDataParser() self::assertSame([ 'command' => $this->command, - 'oldPage' => (string)$this->selectedPage, + 'oldPage' => (string) $this->selectedPage, 'newPage' => '1', // because we're getting the button at position 0, which is page 1 ], $callback_data); } - public function testValidPagination() + public function testValidPagination(): void { $ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selectedPage, $this->itemsPerPage); @@ -126,7 +126,7 @@ public function testValidPagination() $this->assertTrue(true); } - public function testInvalidPagination() + public function testInvalidPagination(): void { $this->expectExceptionMessage("Invalid selected page, must be between 1 and 20"); $this->expectException( @@ -137,7 +137,7 @@ public function testInvalidPagination() $ikp->getPagination($ikp->getNumberOfPages() + 1); } - public function testSetMaxButtons() + public function testSetMaxButtons(): void { $ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selectedPage, $this->itemsPerPage); $ikp->setMaxButtons(6); @@ -145,7 +145,7 @@ public function testSetMaxButtons() self::assertTrue(true); } - public function testForceButtonsCount() + public function testForceButtonsCount(): void { $ikp = new InlineKeyboardPagination(range(1, 10), 'cbdata', 1, 1); @@ -191,7 +191,7 @@ public function testForceButtonsCount() ], 'text', [$ikp->getPagination(10)['keyboard']]); } - public function testInvalidMaxButtons() + public function testInvalidMaxButtons(): void { $this->expectExceptionMessage("Invalid max buttons, must be between 5 and 8."); $this->expectException( @@ -203,7 +203,25 @@ public function testInvalidMaxButtons() $ikp->getPagination(); } - public function testInvalidSelectedPage() + public function testGetCallbackDataFormat(): void + { + $ikp = new InlineKeyboardPagination($this->items); + // Test default value. + self::assertSame( + 'command={COMMAND}&oldPage={OLD_PAGE}&newPage={NEW_PAGE}', + $ikp->getCallbackDataFormat() + ); + + // Test custom value. + $customCallbackDataFormat = 'c={COMMAND}&op={OLD_PAGE}&np={NEW_PAGE}'; + $ikp->setCallbackDataFormat($customCallbackDataFormat); + self::assertSame( + $customCallbackDataFormat, + $ikp->getCallbackDataFormat() + ); + } + + public function testInvalidSelectedPage(): void { $this->expectExceptionMessage("Invalid selected page, must be between 1 and 20"); $this->expectException( @@ -215,14 +233,14 @@ public function testInvalidSelectedPage() $ikp->getPagination(); } - public function testGetItemsPerPage() + public function testGetItemsPerPage(): void { $ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selectedPage, 4); self::assertEquals(4, $ikp->getItemsPerPage()); } - public function testInvalidItemsPerPage() + public function testInvalidItemsPerPage(): void { $this->expectExceptionMessage("Invalid number of items per page, must be at least 1"); $this->expectException( @@ -233,7 +251,7 @@ public function testInvalidItemsPerPage() $ikp->getPagination(); } - public function testButtonLabels() + public function testButtonLabels(): void { $cbdata = 'command=%s&oldPage=%d&newPage=%d'; $command = 'cbdata'; @@ -321,7 +339,7 @@ public function testButtonLabels() ], 'callback_data', $keyboard); } - public static function assertButtonPropertiesEqual($value, $property, $keyboard, $row, $column, $message = '') + public static function assertButtonPropertiesEqual($value, $property, $keyboard, $row, $column, $message = ''): void { $row_raw = array_values($keyboard)[$row]; $column_raw = array_values($row_raw)[$column]; @@ -329,7 +347,7 @@ public static function assertButtonPropertiesEqual($value, $property, $keyboard, self::assertSame($value, $column_raw[$property], $message); } - public static function assertRowButtonPropertiesEqual(array $values, $property, $keyboard, $row, $message = '') + public static function assertRowButtonPropertiesEqual(array $values, $property, $keyboard, $row, $message = ''): void { $column = 0; foreach ($values as $value) { @@ -338,7 +356,7 @@ public static function assertRowButtonPropertiesEqual(array $values, $property, self::assertCount(count(array_values($keyboard)[$row]), $values); } - public static function assertAllButtonPropertiesEqual(array $all_values, $property, $keyboard, $message = '') + public static function assertAllButtonPropertiesEqual(array $all_values, $property, $keyboard, $message = ''): void { $row = 0; foreach ($all_values as $values) {