├── .gitignore ├── .scrutinizer.yml ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── phpcs.xml.dist ├── phpunit.xml.dist ├── src ├── Exceptions │ └── InlineKeyboardPaginationException.php ├── InlineKeyboardPagination.php └── InlineKeyboardPaginator.php └── tests └── InlineKeyboardPaginationTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.phpunit.result.cache 3 | /composer.phar 4 | /coverage.xml 5 | /phpcs.xml 6 | /phpunit.xml 7 | /vendor/ 8 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | build: 2 | environment: 3 | php: 7.4.0 4 | nodes: 5 | analysis: 6 | tests: 7 | override: 8 | - php-scrutinizer-run 9 | 10 | filter: 11 | paths: 12 | - src/ 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | sudo: required 3 | language: php 4 | 5 | cache: 6 | directories: 7 | - vendor 8 | - $HOME/.composer/cache 9 | 10 | php: 11 | - 7.4 12 | - 8.0 13 | - nightly 14 | 15 | jobs: 16 | allow_failures: 17 | - php: nightly 18 | fast_finish: true 19 | 20 | notifications: 21 | on_success: never 22 | on_failure: always 23 | 24 | git: 25 | depth: 1 26 | 27 | install: 28 | - travis_retry composer install --prefer-dist --no-interaction 29 | 30 | script: 31 | - composer check-code 32 | - if [ "$TRAVIS_PHP_VERSION" == "8.0" ]; then composer test-cov; else composer test; fi 33 | 34 | after_success: 35 | - if [ "$TRAVIS_PHP_VERSION" == "8.0" ]; then composer test-cov-upload; fi 36 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). 3 | 4 | Exclamation symbols (:exclamation:) note something of importance e.g. breaking changes. Click them to learn more. 5 | 6 | ## [Unreleased] 7 | ### Added 8 | ### Changed 9 | ### Deprecated 10 | ### Removed 11 | ### Fixed 12 | ### Security 13 | 14 | ## [1.1.0] - 2021-07-10 15 | ### Added 16 | - Bump minimum PHP to 7.4 and support PHP 8. (@MyZik) (#8) 17 | ### Changed 18 | - Bump development dependencies, update tests. (#11, #12) 19 | - Improve all development configurations. (#11) 20 | ### Fixed 21 | - Strange behaviour with page 3. (#12) 22 | ### Security 23 | - Minimum PHP 7.4. (@MyZik) (#8) 24 | 25 | ## [1.0.0] - 2017-09-08 26 | ### Added 27 | - Initial version! 28 | 29 | [Unreleased]: https://github.com/php-telegram-bot/inline-keyboard-pagination/compare/master...develop 30 | [1.1.0]: https://github.com/php-telegram-bot/inline-keyboard-pagination/compare/1.0.0...1.1.0 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Artem Beliankin 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Telegram Bot Inline Keyboard Pagination][github-tgbot-ikp] 2 | 3 | [![Scrutinizer Code Quality][code-quality-badge]][code-quality] 4 | [![Codecov][code-coverage-badge]][code-coverage] 5 | [![Build Status][build-status-badge]][build-status] 6 | 7 | [![Latest Stable Version][latest-version-badge]][packagist-tgbot-ikp] 8 | [![Total Downloads][total-downloads-badge]][packagist-tgbot-ikp] 9 | [![License][license-badge]][license] 10 | 11 | - [Installation](#installation) 12 | - [Composer](#composer) 13 | - [Usage](#usage) 14 | - [Test Data](#test-data) 15 | - [How To Use](#how-to-use) 16 | - [Code Quality](#code-quality) 17 | - [License](#license) 18 | 19 | ## Installation 20 | 21 | ### Composer 22 | 23 | ```bash 24 | composer require php-telegram-bot/inline-keyboard-pagination 25 | ``` 26 | 27 | ## Usage 28 | 29 | ### Test Data 30 | 31 | ```php 32 | $items = range(1, 100); // required. 33 | $command = 'testCommand'; // optional. Default: pagination 34 | $selectedPage = 10; // optional. Default: 1 35 | $labels = [ // optional. Change button labels (showing defaults) 36 | 'default' => '%d', 37 | 'first' => '« %d', 38 | 'previous' => '‹ %d', 39 | 'current' => '· %d ·', 40 | 'next' => '%d ›', 41 | 'last' => '%d »', 42 | ]; 43 | 44 | // optional. Change the callback_data format, adding placeholders for data (showing default) 45 | $callbackDataFormat = 'command={COMMAND}&oldPage={OLD_PAGE}&newPage={NEW_PAGE}' 46 | ``` 47 | 48 | ### How To Use 49 | 50 | ```php 51 | // Define inline keyboard pagination. 52 | $ikp = new InlineKeyboardPagination($items, $command); 53 | $ikp->setMaxButtons(7, true); // Second parameter set to always show 7 buttons if possible. 54 | $ikp->setLabels($labels); 55 | $ikp->setCallbackDataFormat($callbackDataFormat); 56 | 57 | // Get pagination. 58 | $pagination = $ikp->getPagination($selectedPage); 59 | 60 | // or, in 2 steps. 61 | $ikp->setSelectedPage($selectedPage); 62 | $pagination = $ikp->getPagination(); 63 | ``` 64 | 65 | Now, `$pagination['keyboard']` is basically a row that contains the pagination. 66 | 67 | ```php 68 | // Use it in your request. 69 | if (!empty($pagination['keyboard'])) { 70 | //$pagination['keyboard'][0]['callback_data']; // command=testCommand&oldPage=10&newPage=1 71 | //$pagination['keyboard'][1]['callback_data']; // command=testCommand&oldPage=10&newPage=7 72 | 73 | ... 74 | $data['reply_markup'] = [ 75 | 'inline_keyboard' => [ 76 | $pagination['keyboard'], 77 | ], 78 | ]; 79 | ... 80 | } 81 | ``` 82 | 83 | To get the callback data, you can use the provided helper method (only works when using the default callback data format): 84 | 85 | ```php 86 | // e.g. Callback data. 87 | $callback_data = 'command=testCommand&oldPage=10&newPage=1'; 88 | 89 | $params = InlineKeyboardPagination::getParametersFromCallbackData($callbackData); 90 | 91 | //$params = [ 92 | // 'command' => 'testCommand', 93 | // 'oldPage' => '10', 94 | // 'newPage' => '1', 95 | //]; 96 | 97 | // or, just use PHP directly if you like. (literally what the helper does!) 98 | parse_str($callbackData, $params); 99 | ``` 100 | 101 | ## Code Quality 102 | 103 | Run the PHPUnit tests via Composer script. 104 | 105 | ```bash 106 | composer test 107 | ``` 108 | 109 | ## License 110 | 111 | The MIT License (MIT). Please see [License File][license] for more information. 112 | 113 | Project based on [Telegram Bot Pagination][github-lartie-tbp] by [lartie][github-lartie]. 114 | 115 | 116 | [github-tgbot-ikp]: https://github.com/php-telegram-bot/inline-keyboard-pagination "PHP Telegram Bot Inline Keyboard Pagination on GitHub" 117 | [packagist-tgbot-ikp]: https://packagist.org/packages/php-telegram-bot/inline-keyboard-pagination "PHP Telegram Bot Inline Keyboard Pagination on Packagist" 118 | [license]: https://github.com/php-telegram-bot/inline-keyboard-pagination/blob/master/LICENSE "PHP Telegram Bot Inline Keyboard Pagination license" 119 | 120 | [code-quality-badge]: https://img.shields.io/scrutinizer/g/php-telegram-bot/inline-keyboard-pagination.svg 121 | [code-quality]: https://scrutinizer-ci.com/g/php-telegram-bot/inline-keyboard-pagination/?branch=master "Code quality on Scrutinizer" 122 | [code-coverage-badge]: https://img.shields.io/codecov/c/github/php-telegram-bot/inline-keyboard-pagination.svg 123 | [code-coverage]: https://codecov.io/gh/php-telegram-bot/inline-keyboard-pagination "Code coverage on Codecov" 124 | [build-status-badge]: https://img.shields.io/travis/php-telegram-bot/inline-keyboard-pagination.svg 125 | [build-status]: https://travis-ci.com/php-telegram-bot/inline-keyboard-pagination "Build status on Travis-CI" 126 | 127 | [latest-version-badge]: https://img.shields.io/packagist/v/php-telegram-bot/inline-keyboard-pagination.svg 128 | [total-downloads-badge]: https://img.shields.io/packagist/dt/php-telegram-bot/inline-keyboard-pagination.svg 129 | [license-badge]: https://img.shields.io/packagist/l/php-telegram-bot/inline-keyboard-pagination.svg 130 | 131 | [github-lartie-tbp]: https://github.com/lartie/Telegram-Bot-Pagination "Telegram Bot Pagination by Lartie on GitHub" 132 | [github-lartie]: https://github.com/lartie "Lartie on GitHub" 133 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "php-telegram-bot/inline-keyboard-pagination", 3 | "type": "library", 4 | "description": "PHP Telegram Bot InlineKeyboard Pagination", 5 | "keywords": ["telegram", "bot", "inline", "keyboard", "pagination", "callback", "query"], 6 | "license": "MIT", 7 | "homepage": "https://github.com/php-telegram-bot/inline-keyboard-pagination", 8 | "support": { 9 | "issues": "https://github.com/php-telegram-bot/inline-keyboard-pagination/issues", 10 | "source": "https://github.com/php-telegram-bot/inline-keyboard-pagination" 11 | }, 12 | "authors": [ 13 | { 14 | "name": "Armando Lüscher", 15 | "email": "armando@noplanman.ch", 16 | "homepage": "https://noplanman.ch", 17 | "role": "Developer" 18 | }, 19 | { 20 | "name": "Artie", 21 | "email": "log.wil.log@gmail.com", 22 | "homepage": "https://github.com/lartie", 23 | "role": "Original developer" 24 | } 25 | ], 26 | "require": { 27 | "php": "^7.4|^8.0" 28 | }, 29 | "require-dev": { 30 | "php-parallel-lint/php-parallel-lint": "^1.3", 31 | "phpunit/phpunit": "^9.5", 32 | "squizlabs/php_codesniffer": "^3.6" 33 | }, 34 | "autoload": { 35 | "psr-4": { 36 | "TelegramBot\\InlineKeyboardPagination\\": "src" 37 | } 38 | }, 39 | "autoload-dev": { 40 | "psr-4": { 41 | "TelegramBot\\InlineKeyboardPagination\\Tests\\": "tests" 42 | } 43 | }, 44 | "scripts": { 45 | "check-code": [ 46 | "vendor/bin/parallel-lint . --exclude vendor", 47 | "vendor/bin/phpcs" 48 | ], 49 | "test": [ 50 | "vendor/bin/phpunit" 51 | ], 52 | "test-cov": [ 53 | "@putenv XDEBUG_MODE=coverage", 54 | "vendor/bin/phpunit --coverage-clover coverage.xml" 55 | ], 56 | "test-cov-upload": [ 57 | "curl -s https://codecov.io/bash | bash" 58 | ] 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "c183adbe8af902616e4294de1b0dfd8c", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "doctrine/instantiator", 12 | "version": "1.4.0", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/doctrine/instantiator.git", 16 | "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", 21 | "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": "^7.1 || ^8.0" 26 | }, 27 | "require-dev": { 28 | "doctrine/coding-standard": "^8.0", 29 | "ext-pdo": "*", 30 | "ext-phar": "*", 31 | "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", 32 | "phpstan/phpstan": "^0.12", 33 | "phpstan/phpstan-phpunit": "^0.12", 34 | "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" 35 | }, 36 | "type": "library", 37 | "autoload": { 38 | "psr-4": { 39 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 40 | } 41 | }, 42 | "notification-url": "https://packagist.org/downloads/", 43 | "license": [ 44 | "MIT" 45 | ], 46 | "authors": [ 47 | { 48 | "name": "Marco Pivetta", 49 | "email": "ocramius@gmail.com", 50 | "homepage": "https://ocramius.github.io/" 51 | } 52 | ], 53 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 54 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 55 | "keywords": [ 56 | "constructor", 57 | "instantiate" 58 | ], 59 | "support": { 60 | "issues": "https://github.com/doctrine/instantiator/issues", 61 | "source": "https://github.com/doctrine/instantiator/tree/1.4.0" 62 | }, 63 | "funding": [ 64 | { 65 | "url": "https://www.doctrine-project.org/sponsorship.html", 66 | "type": "custom" 67 | }, 68 | { 69 | "url": "https://www.patreon.com/phpdoctrine", 70 | "type": "patreon" 71 | }, 72 | { 73 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 74 | "type": "tidelift" 75 | } 76 | ], 77 | "time": "2020-11-10T18:47:58+00:00" 78 | }, 79 | { 80 | "name": "myclabs/deep-copy", 81 | "version": "1.10.2", 82 | "source": { 83 | "type": "git", 84 | "url": "https://github.com/myclabs/DeepCopy.git", 85 | "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" 86 | }, 87 | "dist": { 88 | "type": "zip", 89 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", 90 | "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", 91 | "shasum": "" 92 | }, 93 | "require": { 94 | "php": "^7.1 || ^8.0" 95 | }, 96 | "replace": { 97 | "myclabs/deep-copy": "self.version" 98 | }, 99 | "require-dev": { 100 | "doctrine/collections": "^1.0", 101 | "doctrine/common": "^2.6", 102 | "phpunit/phpunit": "^7.1" 103 | }, 104 | "type": "library", 105 | "autoload": { 106 | "psr-4": { 107 | "DeepCopy\\": "src/DeepCopy/" 108 | }, 109 | "files": [ 110 | "src/DeepCopy/deep_copy.php" 111 | ] 112 | }, 113 | "notification-url": "https://packagist.org/downloads/", 114 | "license": [ 115 | "MIT" 116 | ], 117 | "description": "Create deep copies (clones) of your objects", 118 | "keywords": [ 119 | "clone", 120 | "copy", 121 | "duplicate", 122 | "object", 123 | "object graph" 124 | ], 125 | "support": { 126 | "issues": "https://github.com/myclabs/DeepCopy/issues", 127 | "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" 128 | }, 129 | "funding": [ 130 | { 131 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 132 | "type": "tidelift" 133 | } 134 | ], 135 | "time": "2020-11-13T09:40:50+00:00" 136 | }, 137 | { 138 | "name": "nikic/php-parser", 139 | "version": "v4.11.0", 140 | "source": { 141 | "type": "git", 142 | "url": "https://github.com/nikic/PHP-Parser.git", 143 | "reference": "fe14cf3672a149364fb66dfe11bf6549af899f94" 144 | }, 145 | "dist": { 146 | "type": "zip", 147 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/fe14cf3672a149364fb66dfe11bf6549af899f94", 148 | "reference": "fe14cf3672a149364fb66dfe11bf6549af899f94", 149 | "shasum": "" 150 | }, 151 | "require": { 152 | "ext-tokenizer": "*", 153 | "php": ">=7.0" 154 | }, 155 | "require-dev": { 156 | "ircmaxell/php-yacc": "^0.0.7", 157 | "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" 158 | }, 159 | "bin": [ 160 | "bin/php-parse" 161 | ], 162 | "type": "library", 163 | "extra": { 164 | "branch-alias": { 165 | "dev-master": "4.9-dev" 166 | } 167 | }, 168 | "autoload": { 169 | "psr-4": { 170 | "PhpParser\\": "lib/PhpParser" 171 | } 172 | }, 173 | "notification-url": "https://packagist.org/downloads/", 174 | "license": [ 175 | "BSD-3-Clause" 176 | ], 177 | "authors": [ 178 | { 179 | "name": "Nikita Popov" 180 | } 181 | ], 182 | "description": "A PHP parser written in PHP", 183 | "keywords": [ 184 | "parser", 185 | "php" 186 | ], 187 | "support": { 188 | "issues": "https://github.com/nikic/PHP-Parser/issues", 189 | "source": "https://github.com/nikic/PHP-Parser/tree/v4.11.0" 190 | }, 191 | "time": "2021-07-03T13:36:55+00:00" 192 | }, 193 | { 194 | "name": "phar-io/manifest", 195 | "version": "2.0.1", 196 | "source": { 197 | "type": "git", 198 | "url": "https://github.com/phar-io/manifest.git", 199 | "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" 200 | }, 201 | "dist": { 202 | "type": "zip", 203 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", 204 | "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", 205 | "shasum": "" 206 | }, 207 | "require": { 208 | "ext-dom": "*", 209 | "ext-phar": "*", 210 | "ext-xmlwriter": "*", 211 | "phar-io/version": "^3.0.1", 212 | "php": "^7.2 || ^8.0" 213 | }, 214 | "type": "library", 215 | "extra": { 216 | "branch-alias": { 217 | "dev-master": "2.0.x-dev" 218 | } 219 | }, 220 | "autoload": { 221 | "classmap": [ 222 | "src/" 223 | ] 224 | }, 225 | "notification-url": "https://packagist.org/downloads/", 226 | "license": [ 227 | "BSD-3-Clause" 228 | ], 229 | "authors": [ 230 | { 231 | "name": "Arne Blankerts", 232 | "email": "arne@blankerts.de", 233 | "role": "Developer" 234 | }, 235 | { 236 | "name": "Sebastian Heuer", 237 | "email": "sebastian@phpeople.de", 238 | "role": "Developer" 239 | }, 240 | { 241 | "name": "Sebastian Bergmann", 242 | "email": "sebastian@phpunit.de", 243 | "role": "Developer" 244 | } 245 | ], 246 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 247 | "support": { 248 | "issues": "https://github.com/phar-io/manifest/issues", 249 | "source": "https://github.com/phar-io/manifest/tree/master" 250 | }, 251 | "time": "2020-06-27T14:33:11+00:00" 252 | }, 253 | { 254 | "name": "phar-io/version", 255 | "version": "3.1.0", 256 | "source": { 257 | "type": "git", 258 | "url": "https://github.com/phar-io/version.git", 259 | "reference": "bae7c545bef187884426f042434e561ab1ddb182" 260 | }, 261 | "dist": { 262 | "type": "zip", 263 | "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", 264 | "reference": "bae7c545bef187884426f042434e561ab1ddb182", 265 | "shasum": "" 266 | }, 267 | "require": { 268 | "php": "^7.2 || ^8.0" 269 | }, 270 | "type": "library", 271 | "autoload": { 272 | "classmap": [ 273 | "src/" 274 | ] 275 | }, 276 | "notification-url": "https://packagist.org/downloads/", 277 | "license": [ 278 | "BSD-3-Clause" 279 | ], 280 | "authors": [ 281 | { 282 | "name": "Arne Blankerts", 283 | "email": "arne@blankerts.de", 284 | "role": "Developer" 285 | }, 286 | { 287 | "name": "Sebastian Heuer", 288 | "email": "sebastian@phpeople.de", 289 | "role": "Developer" 290 | }, 291 | { 292 | "name": "Sebastian Bergmann", 293 | "email": "sebastian@phpunit.de", 294 | "role": "Developer" 295 | } 296 | ], 297 | "description": "Library for handling version information and constraints", 298 | "support": { 299 | "issues": "https://github.com/phar-io/version/issues", 300 | "source": "https://github.com/phar-io/version/tree/3.1.0" 301 | }, 302 | "time": "2021-02-23T14:00:09+00:00" 303 | }, 304 | { 305 | "name": "php-parallel-lint/php-parallel-lint", 306 | "version": "v1.3.0", 307 | "source": { 308 | "type": "git", 309 | "url": "https://github.com/php-parallel-lint/PHP-Parallel-Lint.git", 310 | "reference": "772a954e5f119f6f5871d015b23eabed8cbdadfb" 311 | }, 312 | "dist": { 313 | "type": "zip", 314 | "url": "https://api.github.com/repos/php-parallel-lint/PHP-Parallel-Lint/zipball/772a954e5f119f6f5871d015b23eabed8cbdadfb", 315 | "reference": "772a954e5f119f6f5871d015b23eabed8cbdadfb", 316 | "shasum": "" 317 | }, 318 | "require": { 319 | "ext-json": "*", 320 | "php": ">=5.3.0" 321 | }, 322 | "replace": { 323 | "grogy/php-parallel-lint": "*", 324 | "jakub-onderka/php-parallel-lint": "*" 325 | }, 326 | "require-dev": { 327 | "nette/tester": "^1.3 || ^2.0", 328 | "php-parallel-lint/php-console-highlighter": "~0.3", 329 | "squizlabs/php_codesniffer": "^3.5" 330 | }, 331 | "suggest": { 332 | "php-parallel-lint/php-console-highlighter": "Highlight syntax in code snippet" 333 | }, 334 | "bin": [ 335 | "parallel-lint" 336 | ], 337 | "type": "library", 338 | "autoload": { 339 | "classmap": [ 340 | "./" 341 | ] 342 | }, 343 | "notification-url": "https://packagist.org/downloads/", 344 | "license": [ 345 | "BSD-2-Clause" 346 | ], 347 | "authors": [ 348 | { 349 | "name": "Jakub Onderka", 350 | "email": "ahoj@jakubonderka.cz" 351 | } 352 | ], 353 | "description": "This tool check syntax of PHP files about 20x faster than serial check.", 354 | "homepage": "https://github.com/php-parallel-lint/PHP-Parallel-Lint", 355 | "support": { 356 | "issues": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/issues", 357 | "source": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/tree/v1.3.0" 358 | }, 359 | "time": "2021-04-07T14:42:48+00:00" 360 | }, 361 | { 362 | "name": "phpdocumentor/reflection-common", 363 | "version": "2.2.0", 364 | "source": { 365 | "type": "git", 366 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 367 | "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" 368 | }, 369 | "dist": { 370 | "type": "zip", 371 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", 372 | "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", 373 | "shasum": "" 374 | }, 375 | "require": { 376 | "php": "^7.2 || ^8.0" 377 | }, 378 | "type": "library", 379 | "extra": { 380 | "branch-alias": { 381 | "dev-2.x": "2.x-dev" 382 | } 383 | }, 384 | "autoload": { 385 | "psr-4": { 386 | "phpDocumentor\\Reflection\\": "src/" 387 | } 388 | }, 389 | "notification-url": "https://packagist.org/downloads/", 390 | "license": [ 391 | "MIT" 392 | ], 393 | "authors": [ 394 | { 395 | "name": "Jaap van Otterdijk", 396 | "email": "opensource@ijaap.nl" 397 | } 398 | ], 399 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 400 | "homepage": "http://www.phpdoc.org", 401 | "keywords": [ 402 | "FQSEN", 403 | "phpDocumentor", 404 | "phpdoc", 405 | "reflection", 406 | "static analysis" 407 | ], 408 | "support": { 409 | "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", 410 | "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" 411 | }, 412 | "time": "2020-06-27T09:03:43+00:00" 413 | }, 414 | { 415 | "name": "phpdocumentor/reflection-docblock", 416 | "version": "5.2.2", 417 | "source": { 418 | "type": "git", 419 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 420 | "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" 421 | }, 422 | "dist": { 423 | "type": "zip", 424 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", 425 | "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", 426 | "shasum": "" 427 | }, 428 | "require": { 429 | "ext-filter": "*", 430 | "php": "^7.2 || ^8.0", 431 | "phpdocumentor/reflection-common": "^2.2", 432 | "phpdocumentor/type-resolver": "^1.3", 433 | "webmozart/assert": "^1.9.1" 434 | }, 435 | "require-dev": { 436 | "mockery/mockery": "~1.3.2" 437 | }, 438 | "type": "library", 439 | "extra": { 440 | "branch-alias": { 441 | "dev-master": "5.x-dev" 442 | } 443 | }, 444 | "autoload": { 445 | "psr-4": { 446 | "phpDocumentor\\Reflection\\": "src" 447 | } 448 | }, 449 | "notification-url": "https://packagist.org/downloads/", 450 | "license": [ 451 | "MIT" 452 | ], 453 | "authors": [ 454 | { 455 | "name": "Mike van Riel", 456 | "email": "me@mikevanriel.com" 457 | }, 458 | { 459 | "name": "Jaap van Otterdijk", 460 | "email": "account@ijaap.nl" 461 | } 462 | ], 463 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 464 | "support": { 465 | "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", 466 | "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" 467 | }, 468 | "time": "2020-09-03T19:13:55+00:00" 469 | }, 470 | { 471 | "name": "phpdocumentor/type-resolver", 472 | "version": "1.4.0", 473 | "source": { 474 | "type": "git", 475 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 476 | "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" 477 | }, 478 | "dist": { 479 | "type": "zip", 480 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", 481 | "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", 482 | "shasum": "" 483 | }, 484 | "require": { 485 | "php": "^7.2 || ^8.0", 486 | "phpdocumentor/reflection-common": "^2.0" 487 | }, 488 | "require-dev": { 489 | "ext-tokenizer": "*" 490 | }, 491 | "type": "library", 492 | "extra": { 493 | "branch-alias": { 494 | "dev-1.x": "1.x-dev" 495 | } 496 | }, 497 | "autoload": { 498 | "psr-4": { 499 | "phpDocumentor\\Reflection\\": "src" 500 | } 501 | }, 502 | "notification-url": "https://packagist.org/downloads/", 503 | "license": [ 504 | "MIT" 505 | ], 506 | "authors": [ 507 | { 508 | "name": "Mike van Riel", 509 | "email": "me@mikevanriel.com" 510 | } 511 | ], 512 | "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", 513 | "support": { 514 | "issues": "https://github.com/phpDocumentor/TypeResolver/issues", 515 | "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" 516 | }, 517 | "time": "2020-09-17T18:55:26+00:00" 518 | }, 519 | { 520 | "name": "phpspec/prophecy", 521 | "version": "1.13.0", 522 | "source": { 523 | "type": "git", 524 | "url": "https://github.com/phpspec/prophecy.git", 525 | "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea" 526 | }, 527 | "dist": { 528 | "type": "zip", 529 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea", 530 | "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea", 531 | "shasum": "" 532 | }, 533 | "require": { 534 | "doctrine/instantiator": "^1.2", 535 | "php": "^7.2 || ~8.0, <8.1", 536 | "phpdocumentor/reflection-docblock": "^5.2", 537 | "sebastian/comparator": "^3.0 || ^4.0", 538 | "sebastian/recursion-context": "^3.0 || ^4.0" 539 | }, 540 | "require-dev": { 541 | "phpspec/phpspec": "^6.0", 542 | "phpunit/phpunit": "^8.0 || ^9.0" 543 | }, 544 | "type": "library", 545 | "extra": { 546 | "branch-alias": { 547 | "dev-master": "1.11.x-dev" 548 | } 549 | }, 550 | "autoload": { 551 | "psr-4": { 552 | "Prophecy\\": "src/Prophecy" 553 | } 554 | }, 555 | "notification-url": "https://packagist.org/downloads/", 556 | "license": [ 557 | "MIT" 558 | ], 559 | "authors": [ 560 | { 561 | "name": "Konstantin Kudryashov", 562 | "email": "ever.zet@gmail.com", 563 | "homepage": "http://everzet.com" 564 | }, 565 | { 566 | "name": "Marcello Duarte", 567 | "email": "marcello.duarte@gmail.com" 568 | } 569 | ], 570 | "description": "Highly opinionated mocking framework for PHP 5.3+", 571 | "homepage": "https://github.com/phpspec/prophecy", 572 | "keywords": [ 573 | "Double", 574 | "Dummy", 575 | "fake", 576 | "mock", 577 | "spy", 578 | "stub" 579 | ], 580 | "support": { 581 | "issues": "https://github.com/phpspec/prophecy/issues", 582 | "source": "https://github.com/phpspec/prophecy/tree/1.13.0" 583 | }, 584 | "time": "2021-03-17T13:42:18+00:00" 585 | }, 586 | { 587 | "name": "phpunit/php-code-coverage", 588 | "version": "9.2.6", 589 | "source": { 590 | "type": "git", 591 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 592 | "reference": "f6293e1b30a2354e8428e004689671b83871edde" 593 | }, 594 | "dist": { 595 | "type": "zip", 596 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde", 597 | "reference": "f6293e1b30a2354e8428e004689671b83871edde", 598 | "shasum": "" 599 | }, 600 | "require": { 601 | "ext-dom": "*", 602 | "ext-libxml": "*", 603 | "ext-xmlwriter": "*", 604 | "nikic/php-parser": "^4.10.2", 605 | "php": ">=7.3", 606 | "phpunit/php-file-iterator": "^3.0.3", 607 | "phpunit/php-text-template": "^2.0.2", 608 | "sebastian/code-unit-reverse-lookup": "^2.0.2", 609 | "sebastian/complexity": "^2.0", 610 | "sebastian/environment": "^5.1.2", 611 | "sebastian/lines-of-code": "^1.0.3", 612 | "sebastian/version": "^3.0.1", 613 | "theseer/tokenizer": "^1.2.0" 614 | }, 615 | "require-dev": { 616 | "phpunit/phpunit": "^9.3" 617 | }, 618 | "suggest": { 619 | "ext-pcov": "*", 620 | "ext-xdebug": "*" 621 | }, 622 | "type": "library", 623 | "extra": { 624 | "branch-alias": { 625 | "dev-master": "9.2-dev" 626 | } 627 | }, 628 | "autoload": { 629 | "classmap": [ 630 | "src/" 631 | ] 632 | }, 633 | "notification-url": "https://packagist.org/downloads/", 634 | "license": [ 635 | "BSD-3-Clause" 636 | ], 637 | "authors": [ 638 | { 639 | "name": "Sebastian Bergmann", 640 | "email": "sebastian@phpunit.de", 641 | "role": "lead" 642 | } 643 | ], 644 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 645 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 646 | "keywords": [ 647 | "coverage", 648 | "testing", 649 | "xunit" 650 | ], 651 | "support": { 652 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 653 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6" 654 | }, 655 | "funding": [ 656 | { 657 | "url": "https://github.com/sebastianbergmann", 658 | "type": "github" 659 | } 660 | ], 661 | "time": "2021-03-28T07:26:59+00:00" 662 | }, 663 | { 664 | "name": "phpunit/php-file-iterator", 665 | "version": "3.0.5", 666 | "source": { 667 | "type": "git", 668 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 669 | "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" 670 | }, 671 | "dist": { 672 | "type": "zip", 673 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", 674 | "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", 675 | "shasum": "" 676 | }, 677 | "require": { 678 | "php": ">=7.3" 679 | }, 680 | "require-dev": { 681 | "phpunit/phpunit": "^9.3" 682 | }, 683 | "type": "library", 684 | "extra": { 685 | "branch-alias": { 686 | "dev-master": "3.0-dev" 687 | } 688 | }, 689 | "autoload": { 690 | "classmap": [ 691 | "src/" 692 | ] 693 | }, 694 | "notification-url": "https://packagist.org/downloads/", 695 | "license": [ 696 | "BSD-3-Clause" 697 | ], 698 | "authors": [ 699 | { 700 | "name": "Sebastian Bergmann", 701 | "email": "sebastian@phpunit.de", 702 | "role": "lead" 703 | } 704 | ], 705 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 706 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 707 | "keywords": [ 708 | "filesystem", 709 | "iterator" 710 | ], 711 | "support": { 712 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 713 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5" 714 | }, 715 | "funding": [ 716 | { 717 | "url": "https://github.com/sebastianbergmann", 718 | "type": "github" 719 | } 720 | ], 721 | "time": "2020-09-28T05:57:25+00:00" 722 | }, 723 | { 724 | "name": "phpunit/php-invoker", 725 | "version": "3.1.1", 726 | "source": { 727 | "type": "git", 728 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 729 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" 730 | }, 731 | "dist": { 732 | "type": "zip", 733 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 734 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 735 | "shasum": "" 736 | }, 737 | "require": { 738 | "php": ">=7.3" 739 | }, 740 | "require-dev": { 741 | "ext-pcntl": "*", 742 | "phpunit/phpunit": "^9.3" 743 | }, 744 | "suggest": { 745 | "ext-pcntl": "*" 746 | }, 747 | "type": "library", 748 | "extra": { 749 | "branch-alias": { 750 | "dev-master": "3.1-dev" 751 | } 752 | }, 753 | "autoload": { 754 | "classmap": [ 755 | "src/" 756 | ] 757 | }, 758 | "notification-url": "https://packagist.org/downloads/", 759 | "license": [ 760 | "BSD-3-Clause" 761 | ], 762 | "authors": [ 763 | { 764 | "name": "Sebastian Bergmann", 765 | "email": "sebastian@phpunit.de", 766 | "role": "lead" 767 | } 768 | ], 769 | "description": "Invoke callables with a timeout", 770 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 771 | "keywords": [ 772 | "process" 773 | ], 774 | "support": { 775 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 776 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" 777 | }, 778 | "funding": [ 779 | { 780 | "url": "https://github.com/sebastianbergmann", 781 | "type": "github" 782 | } 783 | ], 784 | "time": "2020-09-28T05:58:55+00:00" 785 | }, 786 | { 787 | "name": "phpunit/php-text-template", 788 | "version": "2.0.4", 789 | "source": { 790 | "type": "git", 791 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 792 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" 793 | }, 794 | "dist": { 795 | "type": "zip", 796 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 797 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 798 | "shasum": "" 799 | }, 800 | "require": { 801 | "php": ">=7.3" 802 | }, 803 | "require-dev": { 804 | "phpunit/phpunit": "^9.3" 805 | }, 806 | "type": "library", 807 | "extra": { 808 | "branch-alias": { 809 | "dev-master": "2.0-dev" 810 | } 811 | }, 812 | "autoload": { 813 | "classmap": [ 814 | "src/" 815 | ] 816 | }, 817 | "notification-url": "https://packagist.org/downloads/", 818 | "license": [ 819 | "BSD-3-Clause" 820 | ], 821 | "authors": [ 822 | { 823 | "name": "Sebastian Bergmann", 824 | "email": "sebastian@phpunit.de", 825 | "role": "lead" 826 | } 827 | ], 828 | "description": "Simple template engine.", 829 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 830 | "keywords": [ 831 | "template" 832 | ], 833 | "support": { 834 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 835 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" 836 | }, 837 | "funding": [ 838 | { 839 | "url": "https://github.com/sebastianbergmann", 840 | "type": "github" 841 | } 842 | ], 843 | "time": "2020-10-26T05:33:50+00:00" 844 | }, 845 | { 846 | "name": "phpunit/php-timer", 847 | "version": "5.0.3", 848 | "source": { 849 | "type": "git", 850 | "url": "https://github.com/sebastianbergmann/php-timer.git", 851 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" 852 | }, 853 | "dist": { 854 | "type": "zip", 855 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 856 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 857 | "shasum": "" 858 | }, 859 | "require": { 860 | "php": ">=7.3" 861 | }, 862 | "require-dev": { 863 | "phpunit/phpunit": "^9.3" 864 | }, 865 | "type": "library", 866 | "extra": { 867 | "branch-alias": { 868 | "dev-master": "5.0-dev" 869 | } 870 | }, 871 | "autoload": { 872 | "classmap": [ 873 | "src/" 874 | ] 875 | }, 876 | "notification-url": "https://packagist.org/downloads/", 877 | "license": [ 878 | "BSD-3-Clause" 879 | ], 880 | "authors": [ 881 | { 882 | "name": "Sebastian Bergmann", 883 | "email": "sebastian@phpunit.de", 884 | "role": "lead" 885 | } 886 | ], 887 | "description": "Utility class for timing", 888 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 889 | "keywords": [ 890 | "timer" 891 | ], 892 | "support": { 893 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 894 | "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" 895 | }, 896 | "funding": [ 897 | { 898 | "url": "https://github.com/sebastianbergmann", 899 | "type": "github" 900 | } 901 | ], 902 | "time": "2020-10-26T13:16:10+00:00" 903 | }, 904 | { 905 | "name": "phpunit/phpunit", 906 | "version": "9.5.6", 907 | "source": { 908 | "type": "git", 909 | "url": "https://github.com/sebastianbergmann/phpunit.git", 910 | "reference": "fb9b8333f14e3dce976a60ef6a7e05c7c7ed8bfb" 911 | }, 912 | "dist": { 913 | "type": "zip", 914 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fb9b8333f14e3dce976a60ef6a7e05c7c7ed8bfb", 915 | "reference": "fb9b8333f14e3dce976a60ef6a7e05c7c7ed8bfb", 916 | "shasum": "" 917 | }, 918 | "require": { 919 | "doctrine/instantiator": "^1.3.1", 920 | "ext-dom": "*", 921 | "ext-json": "*", 922 | "ext-libxml": "*", 923 | "ext-mbstring": "*", 924 | "ext-xml": "*", 925 | "ext-xmlwriter": "*", 926 | "myclabs/deep-copy": "^1.10.1", 927 | "phar-io/manifest": "^2.0.1", 928 | "phar-io/version": "^3.0.2", 929 | "php": ">=7.3", 930 | "phpspec/prophecy": "^1.12.1", 931 | "phpunit/php-code-coverage": "^9.2.3", 932 | "phpunit/php-file-iterator": "^3.0.5", 933 | "phpunit/php-invoker": "^3.1.1", 934 | "phpunit/php-text-template": "^2.0.3", 935 | "phpunit/php-timer": "^5.0.2", 936 | "sebastian/cli-parser": "^1.0.1", 937 | "sebastian/code-unit": "^1.0.6", 938 | "sebastian/comparator": "^4.0.5", 939 | "sebastian/diff": "^4.0.3", 940 | "sebastian/environment": "^5.1.3", 941 | "sebastian/exporter": "^4.0.3", 942 | "sebastian/global-state": "^5.0.1", 943 | "sebastian/object-enumerator": "^4.0.3", 944 | "sebastian/resource-operations": "^3.0.3", 945 | "sebastian/type": "^2.3.4", 946 | "sebastian/version": "^3.0.2" 947 | }, 948 | "require-dev": { 949 | "ext-pdo": "*", 950 | "phpspec/prophecy-phpunit": "^2.0.1" 951 | }, 952 | "suggest": { 953 | "ext-soap": "*", 954 | "ext-xdebug": "*" 955 | }, 956 | "bin": [ 957 | "phpunit" 958 | ], 959 | "type": "library", 960 | "extra": { 961 | "branch-alias": { 962 | "dev-master": "9.5-dev" 963 | } 964 | }, 965 | "autoload": { 966 | "classmap": [ 967 | "src/" 968 | ], 969 | "files": [ 970 | "src/Framework/Assert/Functions.php" 971 | ] 972 | }, 973 | "notification-url": "https://packagist.org/downloads/", 974 | "license": [ 975 | "BSD-3-Clause" 976 | ], 977 | "authors": [ 978 | { 979 | "name": "Sebastian Bergmann", 980 | "email": "sebastian@phpunit.de", 981 | "role": "lead" 982 | } 983 | ], 984 | "description": "The PHP Unit Testing framework.", 985 | "homepage": "https://phpunit.de/", 986 | "keywords": [ 987 | "phpunit", 988 | "testing", 989 | "xunit" 990 | ], 991 | "support": { 992 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 993 | "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.6" 994 | }, 995 | "funding": [ 996 | { 997 | "url": "https://phpunit.de/donate.html", 998 | "type": "custom" 999 | }, 1000 | { 1001 | "url": "https://github.com/sebastianbergmann", 1002 | "type": "github" 1003 | } 1004 | ], 1005 | "time": "2021-06-23T05:14:38+00:00" 1006 | }, 1007 | { 1008 | "name": "sebastian/cli-parser", 1009 | "version": "1.0.1", 1010 | "source": { 1011 | "type": "git", 1012 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 1013 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" 1014 | }, 1015 | "dist": { 1016 | "type": "zip", 1017 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", 1018 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", 1019 | "shasum": "" 1020 | }, 1021 | "require": { 1022 | "php": ">=7.3" 1023 | }, 1024 | "require-dev": { 1025 | "phpunit/phpunit": "^9.3" 1026 | }, 1027 | "type": "library", 1028 | "extra": { 1029 | "branch-alias": { 1030 | "dev-master": "1.0-dev" 1031 | } 1032 | }, 1033 | "autoload": { 1034 | "classmap": [ 1035 | "src/" 1036 | ] 1037 | }, 1038 | "notification-url": "https://packagist.org/downloads/", 1039 | "license": [ 1040 | "BSD-3-Clause" 1041 | ], 1042 | "authors": [ 1043 | { 1044 | "name": "Sebastian Bergmann", 1045 | "email": "sebastian@phpunit.de", 1046 | "role": "lead" 1047 | } 1048 | ], 1049 | "description": "Library for parsing CLI options", 1050 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 1051 | "support": { 1052 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 1053 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" 1054 | }, 1055 | "funding": [ 1056 | { 1057 | "url": "https://github.com/sebastianbergmann", 1058 | "type": "github" 1059 | } 1060 | ], 1061 | "time": "2020-09-28T06:08:49+00:00" 1062 | }, 1063 | { 1064 | "name": "sebastian/code-unit", 1065 | "version": "1.0.8", 1066 | "source": { 1067 | "type": "git", 1068 | "url": "https://github.com/sebastianbergmann/code-unit.git", 1069 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" 1070 | }, 1071 | "dist": { 1072 | "type": "zip", 1073 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", 1074 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", 1075 | "shasum": "" 1076 | }, 1077 | "require": { 1078 | "php": ">=7.3" 1079 | }, 1080 | "require-dev": { 1081 | "phpunit/phpunit": "^9.3" 1082 | }, 1083 | "type": "library", 1084 | "extra": { 1085 | "branch-alias": { 1086 | "dev-master": "1.0-dev" 1087 | } 1088 | }, 1089 | "autoload": { 1090 | "classmap": [ 1091 | "src/" 1092 | ] 1093 | }, 1094 | "notification-url": "https://packagist.org/downloads/", 1095 | "license": [ 1096 | "BSD-3-Clause" 1097 | ], 1098 | "authors": [ 1099 | { 1100 | "name": "Sebastian Bergmann", 1101 | "email": "sebastian@phpunit.de", 1102 | "role": "lead" 1103 | } 1104 | ], 1105 | "description": "Collection of value objects that represent the PHP code units", 1106 | "homepage": "https://github.com/sebastianbergmann/code-unit", 1107 | "support": { 1108 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 1109 | "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" 1110 | }, 1111 | "funding": [ 1112 | { 1113 | "url": "https://github.com/sebastianbergmann", 1114 | "type": "github" 1115 | } 1116 | ], 1117 | "time": "2020-10-26T13:08:54+00:00" 1118 | }, 1119 | { 1120 | "name": "sebastian/code-unit-reverse-lookup", 1121 | "version": "2.0.3", 1122 | "source": { 1123 | "type": "git", 1124 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1125 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" 1126 | }, 1127 | "dist": { 1128 | "type": "zip", 1129 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1130 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1131 | "shasum": "" 1132 | }, 1133 | "require": { 1134 | "php": ">=7.3" 1135 | }, 1136 | "require-dev": { 1137 | "phpunit/phpunit": "^9.3" 1138 | }, 1139 | "type": "library", 1140 | "extra": { 1141 | "branch-alias": { 1142 | "dev-master": "2.0-dev" 1143 | } 1144 | }, 1145 | "autoload": { 1146 | "classmap": [ 1147 | "src/" 1148 | ] 1149 | }, 1150 | "notification-url": "https://packagist.org/downloads/", 1151 | "license": [ 1152 | "BSD-3-Clause" 1153 | ], 1154 | "authors": [ 1155 | { 1156 | "name": "Sebastian Bergmann", 1157 | "email": "sebastian@phpunit.de" 1158 | } 1159 | ], 1160 | "description": "Looks up which function or method a line of code belongs to", 1161 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1162 | "support": { 1163 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 1164 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" 1165 | }, 1166 | "funding": [ 1167 | { 1168 | "url": "https://github.com/sebastianbergmann", 1169 | "type": "github" 1170 | } 1171 | ], 1172 | "time": "2020-09-28T05:30:19+00:00" 1173 | }, 1174 | { 1175 | "name": "sebastian/comparator", 1176 | "version": "4.0.6", 1177 | "source": { 1178 | "type": "git", 1179 | "url": "https://github.com/sebastianbergmann/comparator.git", 1180 | "reference": "55f4261989e546dc112258c7a75935a81a7ce382" 1181 | }, 1182 | "dist": { 1183 | "type": "zip", 1184 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", 1185 | "reference": "55f4261989e546dc112258c7a75935a81a7ce382", 1186 | "shasum": "" 1187 | }, 1188 | "require": { 1189 | "php": ">=7.3", 1190 | "sebastian/diff": "^4.0", 1191 | "sebastian/exporter": "^4.0" 1192 | }, 1193 | "require-dev": { 1194 | "phpunit/phpunit": "^9.3" 1195 | }, 1196 | "type": "library", 1197 | "extra": { 1198 | "branch-alias": { 1199 | "dev-master": "4.0-dev" 1200 | } 1201 | }, 1202 | "autoload": { 1203 | "classmap": [ 1204 | "src/" 1205 | ] 1206 | }, 1207 | "notification-url": "https://packagist.org/downloads/", 1208 | "license": [ 1209 | "BSD-3-Clause" 1210 | ], 1211 | "authors": [ 1212 | { 1213 | "name": "Sebastian Bergmann", 1214 | "email": "sebastian@phpunit.de" 1215 | }, 1216 | { 1217 | "name": "Jeff Welch", 1218 | "email": "whatthejeff@gmail.com" 1219 | }, 1220 | { 1221 | "name": "Volker Dusch", 1222 | "email": "github@wallbash.com" 1223 | }, 1224 | { 1225 | "name": "Bernhard Schussek", 1226 | "email": "bschussek@2bepublished.at" 1227 | } 1228 | ], 1229 | "description": "Provides the functionality to compare PHP values for equality", 1230 | "homepage": "https://github.com/sebastianbergmann/comparator", 1231 | "keywords": [ 1232 | "comparator", 1233 | "compare", 1234 | "equality" 1235 | ], 1236 | "support": { 1237 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 1238 | "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" 1239 | }, 1240 | "funding": [ 1241 | { 1242 | "url": "https://github.com/sebastianbergmann", 1243 | "type": "github" 1244 | } 1245 | ], 1246 | "time": "2020-10-26T15:49:45+00:00" 1247 | }, 1248 | { 1249 | "name": "sebastian/complexity", 1250 | "version": "2.0.2", 1251 | "source": { 1252 | "type": "git", 1253 | "url": "https://github.com/sebastianbergmann/complexity.git", 1254 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" 1255 | }, 1256 | "dist": { 1257 | "type": "zip", 1258 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", 1259 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", 1260 | "shasum": "" 1261 | }, 1262 | "require": { 1263 | "nikic/php-parser": "^4.7", 1264 | "php": ">=7.3" 1265 | }, 1266 | "require-dev": { 1267 | "phpunit/phpunit": "^9.3" 1268 | }, 1269 | "type": "library", 1270 | "extra": { 1271 | "branch-alias": { 1272 | "dev-master": "2.0-dev" 1273 | } 1274 | }, 1275 | "autoload": { 1276 | "classmap": [ 1277 | "src/" 1278 | ] 1279 | }, 1280 | "notification-url": "https://packagist.org/downloads/", 1281 | "license": [ 1282 | "BSD-3-Clause" 1283 | ], 1284 | "authors": [ 1285 | { 1286 | "name": "Sebastian Bergmann", 1287 | "email": "sebastian@phpunit.de", 1288 | "role": "lead" 1289 | } 1290 | ], 1291 | "description": "Library for calculating the complexity of PHP code units", 1292 | "homepage": "https://github.com/sebastianbergmann/complexity", 1293 | "support": { 1294 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 1295 | "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" 1296 | }, 1297 | "funding": [ 1298 | { 1299 | "url": "https://github.com/sebastianbergmann", 1300 | "type": "github" 1301 | } 1302 | ], 1303 | "time": "2020-10-26T15:52:27+00:00" 1304 | }, 1305 | { 1306 | "name": "sebastian/diff", 1307 | "version": "4.0.4", 1308 | "source": { 1309 | "type": "git", 1310 | "url": "https://github.com/sebastianbergmann/diff.git", 1311 | "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" 1312 | }, 1313 | "dist": { 1314 | "type": "zip", 1315 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", 1316 | "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", 1317 | "shasum": "" 1318 | }, 1319 | "require": { 1320 | "php": ">=7.3" 1321 | }, 1322 | "require-dev": { 1323 | "phpunit/phpunit": "^9.3", 1324 | "symfony/process": "^4.2 || ^5" 1325 | }, 1326 | "type": "library", 1327 | "extra": { 1328 | "branch-alias": { 1329 | "dev-master": "4.0-dev" 1330 | } 1331 | }, 1332 | "autoload": { 1333 | "classmap": [ 1334 | "src/" 1335 | ] 1336 | }, 1337 | "notification-url": "https://packagist.org/downloads/", 1338 | "license": [ 1339 | "BSD-3-Clause" 1340 | ], 1341 | "authors": [ 1342 | { 1343 | "name": "Sebastian Bergmann", 1344 | "email": "sebastian@phpunit.de" 1345 | }, 1346 | { 1347 | "name": "Kore Nordmann", 1348 | "email": "mail@kore-nordmann.de" 1349 | } 1350 | ], 1351 | "description": "Diff implementation", 1352 | "homepage": "https://github.com/sebastianbergmann/diff", 1353 | "keywords": [ 1354 | "diff", 1355 | "udiff", 1356 | "unidiff", 1357 | "unified diff" 1358 | ], 1359 | "support": { 1360 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1361 | "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" 1362 | }, 1363 | "funding": [ 1364 | { 1365 | "url": "https://github.com/sebastianbergmann", 1366 | "type": "github" 1367 | } 1368 | ], 1369 | "time": "2020-10-26T13:10:38+00:00" 1370 | }, 1371 | { 1372 | "name": "sebastian/environment", 1373 | "version": "5.1.3", 1374 | "source": { 1375 | "type": "git", 1376 | "url": "https://github.com/sebastianbergmann/environment.git", 1377 | "reference": "388b6ced16caa751030f6a69e588299fa09200ac" 1378 | }, 1379 | "dist": { 1380 | "type": "zip", 1381 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", 1382 | "reference": "388b6ced16caa751030f6a69e588299fa09200ac", 1383 | "shasum": "" 1384 | }, 1385 | "require": { 1386 | "php": ">=7.3" 1387 | }, 1388 | "require-dev": { 1389 | "phpunit/phpunit": "^9.3" 1390 | }, 1391 | "suggest": { 1392 | "ext-posix": "*" 1393 | }, 1394 | "type": "library", 1395 | "extra": { 1396 | "branch-alias": { 1397 | "dev-master": "5.1-dev" 1398 | } 1399 | }, 1400 | "autoload": { 1401 | "classmap": [ 1402 | "src/" 1403 | ] 1404 | }, 1405 | "notification-url": "https://packagist.org/downloads/", 1406 | "license": [ 1407 | "BSD-3-Clause" 1408 | ], 1409 | "authors": [ 1410 | { 1411 | "name": "Sebastian Bergmann", 1412 | "email": "sebastian@phpunit.de" 1413 | } 1414 | ], 1415 | "description": "Provides functionality to handle HHVM/PHP environments", 1416 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1417 | "keywords": [ 1418 | "Xdebug", 1419 | "environment", 1420 | "hhvm" 1421 | ], 1422 | "support": { 1423 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1424 | "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" 1425 | }, 1426 | "funding": [ 1427 | { 1428 | "url": "https://github.com/sebastianbergmann", 1429 | "type": "github" 1430 | } 1431 | ], 1432 | "time": "2020-09-28T05:52:38+00:00" 1433 | }, 1434 | { 1435 | "name": "sebastian/exporter", 1436 | "version": "4.0.3", 1437 | "source": { 1438 | "type": "git", 1439 | "url": "https://github.com/sebastianbergmann/exporter.git", 1440 | "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" 1441 | }, 1442 | "dist": { 1443 | "type": "zip", 1444 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", 1445 | "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", 1446 | "shasum": "" 1447 | }, 1448 | "require": { 1449 | "php": ">=7.3", 1450 | "sebastian/recursion-context": "^4.0" 1451 | }, 1452 | "require-dev": { 1453 | "ext-mbstring": "*", 1454 | "phpunit/phpunit": "^9.3" 1455 | }, 1456 | "type": "library", 1457 | "extra": { 1458 | "branch-alias": { 1459 | "dev-master": "4.0-dev" 1460 | } 1461 | }, 1462 | "autoload": { 1463 | "classmap": [ 1464 | "src/" 1465 | ] 1466 | }, 1467 | "notification-url": "https://packagist.org/downloads/", 1468 | "license": [ 1469 | "BSD-3-Clause" 1470 | ], 1471 | "authors": [ 1472 | { 1473 | "name": "Sebastian Bergmann", 1474 | "email": "sebastian@phpunit.de" 1475 | }, 1476 | { 1477 | "name": "Jeff Welch", 1478 | "email": "whatthejeff@gmail.com" 1479 | }, 1480 | { 1481 | "name": "Volker Dusch", 1482 | "email": "github@wallbash.com" 1483 | }, 1484 | { 1485 | "name": "Adam Harvey", 1486 | "email": "aharvey@php.net" 1487 | }, 1488 | { 1489 | "name": "Bernhard Schussek", 1490 | "email": "bschussek@gmail.com" 1491 | } 1492 | ], 1493 | "description": "Provides the functionality to export PHP variables for visualization", 1494 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1495 | "keywords": [ 1496 | "export", 1497 | "exporter" 1498 | ], 1499 | "support": { 1500 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1501 | "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.3" 1502 | }, 1503 | "funding": [ 1504 | { 1505 | "url": "https://github.com/sebastianbergmann", 1506 | "type": "github" 1507 | } 1508 | ], 1509 | "time": "2020-09-28T05:24:23+00:00" 1510 | }, 1511 | { 1512 | "name": "sebastian/global-state", 1513 | "version": "5.0.3", 1514 | "source": { 1515 | "type": "git", 1516 | "url": "https://github.com/sebastianbergmann/global-state.git", 1517 | "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49" 1518 | }, 1519 | "dist": { 1520 | "type": "zip", 1521 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49", 1522 | "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49", 1523 | "shasum": "" 1524 | }, 1525 | "require": { 1526 | "php": ">=7.3", 1527 | "sebastian/object-reflector": "^2.0", 1528 | "sebastian/recursion-context": "^4.0" 1529 | }, 1530 | "require-dev": { 1531 | "ext-dom": "*", 1532 | "phpunit/phpunit": "^9.3" 1533 | }, 1534 | "suggest": { 1535 | "ext-uopz": "*" 1536 | }, 1537 | "type": "library", 1538 | "extra": { 1539 | "branch-alias": { 1540 | "dev-master": "5.0-dev" 1541 | } 1542 | }, 1543 | "autoload": { 1544 | "classmap": [ 1545 | "src/" 1546 | ] 1547 | }, 1548 | "notification-url": "https://packagist.org/downloads/", 1549 | "license": [ 1550 | "BSD-3-Clause" 1551 | ], 1552 | "authors": [ 1553 | { 1554 | "name": "Sebastian Bergmann", 1555 | "email": "sebastian@phpunit.de" 1556 | } 1557 | ], 1558 | "description": "Snapshotting of global state", 1559 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1560 | "keywords": [ 1561 | "global state" 1562 | ], 1563 | "support": { 1564 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1565 | "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3" 1566 | }, 1567 | "funding": [ 1568 | { 1569 | "url": "https://github.com/sebastianbergmann", 1570 | "type": "github" 1571 | } 1572 | ], 1573 | "time": "2021-06-11T13:31:12+00:00" 1574 | }, 1575 | { 1576 | "name": "sebastian/lines-of-code", 1577 | "version": "1.0.3", 1578 | "source": { 1579 | "type": "git", 1580 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 1581 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" 1582 | }, 1583 | "dist": { 1584 | "type": "zip", 1585 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", 1586 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", 1587 | "shasum": "" 1588 | }, 1589 | "require": { 1590 | "nikic/php-parser": "^4.6", 1591 | "php": ">=7.3" 1592 | }, 1593 | "require-dev": { 1594 | "phpunit/phpunit": "^9.3" 1595 | }, 1596 | "type": "library", 1597 | "extra": { 1598 | "branch-alias": { 1599 | "dev-master": "1.0-dev" 1600 | } 1601 | }, 1602 | "autoload": { 1603 | "classmap": [ 1604 | "src/" 1605 | ] 1606 | }, 1607 | "notification-url": "https://packagist.org/downloads/", 1608 | "license": [ 1609 | "BSD-3-Clause" 1610 | ], 1611 | "authors": [ 1612 | { 1613 | "name": "Sebastian Bergmann", 1614 | "email": "sebastian@phpunit.de", 1615 | "role": "lead" 1616 | } 1617 | ], 1618 | "description": "Library for counting the lines of code in PHP source code", 1619 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 1620 | "support": { 1621 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 1622 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" 1623 | }, 1624 | "funding": [ 1625 | { 1626 | "url": "https://github.com/sebastianbergmann", 1627 | "type": "github" 1628 | } 1629 | ], 1630 | "time": "2020-11-28T06:42:11+00:00" 1631 | }, 1632 | { 1633 | "name": "sebastian/object-enumerator", 1634 | "version": "4.0.4", 1635 | "source": { 1636 | "type": "git", 1637 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1638 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" 1639 | }, 1640 | "dist": { 1641 | "type": "zip", 1642 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", 1643 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", 1644 | "shasum": "" 1645 | }, 1646 | "require": { 1647 | "php": ">=7.3", 1648 | "sebastian/object-reflector": "^2.0", 1649 | "sebastian/recursion-context": "^4.0" 1650 | }, 1651 | "require-dev": { 1652 | "phpunit/phpunit": "^9.3" 1653 | }, 1654 | "type": "library", 1655 | "extra": { 1656 | "branch-alias": { 1657 | "dev-master": "4.0-dev" 1658 | } 1659 | }, 1660 | "autoload": { 1661 | "classmap": [ 1662 | "src/" 1663 | ] 1664 | }, 1665 | "notification-url": "https://packagist.org/downloads/", 1666 | "license": [ 1667 | "BSD-3-Clause" 1668 | ], 1669 | "authors": [ 1670 | { 1671 | "name": "Sebastian Bergmann", 1672 | "email": "sebastian@phpunit.de" 1673 | } 1674 | ], 1675 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1676 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1677 | "support": { 1678 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1679 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" 1680 | }, 1681 | "funding": [ 1682 | { 1683 | "url": "https://github.com/sebastianbergmann", 1684 | "type": "github" 1685 | } 1686 | ], 1687 | "time": "2020-10-26T13:12:34+00:00" 1688 | }, 1689 | { 1690 | "name": "sebastian/object-reflector", 1691 | "version": "2.0.4", 1692 | "source": { 1693 | "type": "git", 1694 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1695 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" 1696 | }, 1697 | "dist": { 1698 | "type": "zip", 1699 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 1700 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 1701 | "shasum": "" 1702 | }, 1703 | "require": { 1704 | "php": ">=7.3" 1705 | }, 1706 | "require-dev": { 1707 | "phpunit/phpunit": "^9.3" 1708 | }, 1709 | "type": "library", 1710 | "extra": { 1711 | "branch-alias": { 1712 | "dev-master": "2.0-dev" 1713 | } 1714 | }, 1715 | "autoload": { 1716 | "classmap": [ 1717 | "src/" 1718 | ] 1719 | }, 1720 | "notification-url": "https://packagist.org/downloads/", 1721 | "license": [ 1722 | "BSD-3-Clause" 1723 | ], 1724 | "authors": [ 1725 | { 1726 | "name": "Sebastian Bergmann", 1727 | "email": "sebastian@phpunit.de" 1728 | } 1729 | ], 1730 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1731 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1732 | "support": { 1733 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 1734 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" 1735 | }, 1736 | "funding": [ 1737 | { 1738 | "url": "https://github.com/sebastianbergmann", 1739 | "type": "github" 1740 | } 1741 | ], 1742 | "time": "2020-10-26T13:14:26+00:00" 1743 | }, 1744 | { 1745 | "name": "sebastian/recursion-context", 1746 | "version": "4.0.4", 1747 | "source": { 1748 | "type": "git", 1749 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1750 | "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" 1751 | }, 1752 | "dist": { 1753 | "type": "zip", 1754 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", 1755 | "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", 1756 | "shasum": "" 1757 | }, 1758 | "require": { 1759 | "php": ">=7.3" 1760 | }, 1761 | "require-dev": { 1762 | "phpunit/phpunit": "^9.3" 1763 | }, 1764 | "type": "library", 1765 | "extra": { 1766 | "branch-alias": { 1767 | "dev-master": "4.0-dev" 1768 | } 1769 | }, 1770 | "autoload": { 1771 | "classmap": [ 1772 | "src/" 1773 | ] 1774 | }, 1775 | "notification-url": "https://packagist.org/downloads/", 1776 | "license": [ 1777 | "BSD-3-Clause" 1778 | ], 1779 | "authors": [ 1780 | { 1781 | "name": "Sebastian Bergmann", 1782 | "email": "sebastian@phpunit.de" 1783 | }, 1784 | { 1785 | "name": "Jeff Welch", 1786 | "email": "whatthejeff@gmail.com" 1787 | }, 1788 | { 1789 | "name": "Adam Harvey", 1790 | "email": "aharvey@php.net" 1791 | } 1792 | ], 1793 | "description": "Provides functionality to recursively process PHP variables", 1794 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1795 | "support": { 1796 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1797 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" 1798 | }, 1799 | "funding": [ 1800 | { 1801 | "url": "https://github.com/sebastianbergmann", 1802 | "type": "github" 1803 | } 1804 | ], 1805 | "time": "2020-10-26T13:17:30+00:00" 1806 | }, 1807 | { 1808 | "name": "sebastian/resource-operations", 1809 | "version": "3.0.3", 1810 | "source": { 1811 | "type": "git", 1812 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1813 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" 1814 | }, 1815 | "dist": { 1816 | "type": "zip", 1817 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 1818 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 1819 | "shasum": "" 1820 | }, 1821 | "require": { 1822 | "php": ">=7.3" 1823 | }, 1824 | "require-dev": { 1825 | "phpunit/phpunit": "^9.0" 1826 | }, 1827 | "type": "library", 1828 | "extra": { 1829 | "branch-alias": { 1830 | "dev-master": "3.0-dev" 1831 | } 1832 | }, 1833 | "autoload": { 1834 | "classmap": [ 1835 | "src/" 1836 | ] 1837 | }, 1838 | "notification-url": "https://packagist.org/downloads/", 1839 | "license": [ 1840 | "BSD-3-Clause" 1841 | ], 1842 | "authors": [ 1843 | { 1844 | "name": "Sebastian Bergmann", 1845 | "email": "sebastian@phpunit.de" 1846 | } 1847 | ], 1848 | "description": "Provides a list of PHP built-in functions that operate on resources", 1849 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1850 | "support": { 1851 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues", 1852 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" 1853 | }, 1854 | "funding": [ 1855 | { 1856 | "url": "https://github.com/sebastianbergmann", 1857 | "type": "github" 1858 | } 1859 | ], 1860 | "time": "2020-09-28T06:45:17+00:00" 1861 | }, 1862 | { 1863 | "name": "sebastian/type", 1864 | "version": "2.3.4", 1865 | "source": { 1866 | "type": "git", 1867 | "url": "https://github.com/sebastianbergmann/type.git", 1868 | "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914" 1869 | }, 1870 | "dist": { 1871 | "type": "zip", 1872 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914", 1873 | "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914", 1874 | "shasum": "" 1875 | }, 1876 | "require": { 1877 | "php": ">=7.3" 1878 | }, 1879 | "require-dev": { 1880 | "phpunit/phpunit": "^9.3" 1881 | }, 1882 | "type": "library", 1883 | "extra": { 1884 | "branch-alias": { 1885 | "dev-master": "2.3-dev" 1886 | } 1887 | }, 1888 | "autoload": { 1889 | "classmap": [ 1890 | "src/" 1891 | ] 1892 | }, 1893 | "notification-url": "https://packagist.org/downloads/", 1894 | "license": [ 1895 | "BSD-3-Clause" 1896 | ], 1897 | "authors": [ 1898 | { 1899 | "name": "Sebastian Bergmann", 1900 | "email": "sebastian@phpunit.de", 1901 | "role": "lead" 1902 | } 1903 | ], 1904 | "description": "Collection of value objects that represent the types of the PHP type system", 1905 | "homepage": "https://github.com/sebastianbergmann/type", 1906 | "support": { 1907 | "issues": "https://github.com/sebastianbergmann/type/issues", 1908 | "source": "https://github.com/sebastianbergmann/type/tree/2.3.4" 1909 | }, 1910 | "funding": [ 1911 | { 1912 | "url": "https://github.com/sebastianbergmann", 1913 | "type": "github" 1914 | } 1915 | ], 1916 | "time": "2021-06-15T12:49:02+00:00" 1917 | }, 1918 | { 1919 | "name": "sebastian/version", 1920 | "version": "3.0.2", 1921 | "source": { 1922 | "type": "git", 1923 | "url": "https://github.com/sebastianbergmann/version.git", 1924 | "reference": "c6c1022351a901512170118436c764e473f6de8c" 1925 | }, 1926 | "dist": { 1927 | "type": "zip", 1928 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", 1929 | "reference": "c6c1022351a901512170118436c764e473f6de8c", 1930 | "shasum": "" 1931 | }, 1932 | "require": { 1933 | "php": ">=7.3" 1934 | }, 1935 | "type": "library", 1936 | "extra": { 1937 | "branch-alias": { 1938 | "dev-master": "3.0-dev" 1939 | } 1940 | }, 1941 | "autoload": { 1942 | "classmap": [ 1943 | "src/" 1944 | ] 1945 | }, 1946 | "notification-url": "https://packagist.org/downloads/", 1947 | "license": [ 1948 | "BSD-3-Clause" 1949 | ], 1950 | "authors": [ 1951 | { 1952 | "name": "Sebastian Bergmann", 1953 | "email": "sebastian@phpunit.de", 1954 | "role": "lead" 1955 | } 1956 | ], 1957 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1958 | "homepage": "https://github.com/sebastianbergmann/version", 1959 | "support": { 1960 | "issues": "https://github.com/sebastianbergmann/version/issues", 1961 | "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" 1962 | }, 1963 | "funding": [ 1964 | { 1965 | "url": "https://github.com/sebastianbergmann", 1966 | "type": "github" 1967 | } 1968 | ], 1969 | "time": "2020-09-28T06:39:44+00:00" 1970 | }, 1971 | { 1972 | "name": "squizlabs/php_codesniffer", 1973 | "version": "3.6.0", 1974 | "source": { 1975 | "type": "git", 1976 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 1977 | "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625" 1978 | }, 1979 | "dist": { 1980 | "type": "zip", 1981 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625", 1982 | "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625", 1983 | "shasum": "" 1984 | }, 1985 | "require": { 1986 | "ext-simplexml": "*", 1987 | "ext-tokenizer": "*", 1988 | "ext-xmlwriter": "*", 1989 | "php": ">=5.4.0" 1990 | }, 1991 | "require-dev": { 1992 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" 1993 | }, 1994 | "bin": [ 1995 | "bin/phpcs", 1996 | "bin/phpcbf" 1997 | ], 1998 | "type": "library", 1999 | "extra": { 2000 | "branch-alias": { 2001 | "dev-master": "3.x-dev" 2002 | } 2003 | }, 2004 | "notification-url": "https://packagist.org/downloads/", 2005 | "license": [ 2006 | "BSD-3-Clause" 2007 | ], 2008 | "authors": [ 2009 | { 2010 | "name": "Greg Sherwood", 2011 | "role": "lead" 2012 | } 2013 | ], 2014 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 2015 | "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", 2016 | "keywords": [ 2017 | "phpcs", 2018 | "standards" 2019 | ], 2020 | "support": { 2021 | "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", 2022 | "source": "https://github.com/squizlabs/PHP_CodeSniffer", 2023 | "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" 2024 | }, 2025 | "time": "2021-04-09T00:54:41+00:00" 2026 | }, 2027 | { 2028 | "name": "symfony/polyfill-ctype", 2029 | "version": "v1.23.0", 2030 | "source": { 2031 | "type": "git", 2032 | "url": "https://github.com/symfony/polyfill-ctype.git", 2033 | "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" 2034 | }, 2035 | "dist": { 2036 | "type": "zip", 2037 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", 2038 | "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", 2039 | "shasum": "" 2040 | }, 2041 | "require": { 2042 | "php": ">=7.1" 2043 | }, 2044 | "suggest": { 2045 | "ext-ctype": "For best performance" 2046 | }, 2047 | "type": "library", 2048 | "extra": { 2049 | "branch-alias": { 2050 | "dev-main": "1.23-dev" 2051 | }, 2052 | "thanks": { 2053 | "name": "symfony/polyfill", 2054 | "url": "https://github.com/symfony/polyfill" 2055 | } 2056 | }, 2057 | "autoload": { 2058 | "psr-4": { 2059 | "Symfony\\Polyfill\\Ctype\\": "" 2060 | }, 2061 | "files": [ 2062 | "bootstrap.php" 2063 | ] 2064 | }, 2065 | "notification-url": "https://packagist.org/downloads/", 2066 | "license": [ 2067 | "MIT" 2068 | ], 2069 | "authors": [ 2070 | { 2071 | "name": "Gert de Pagter", 2072 | "email": "BackEndTea@gmail.com" 2073 | }, 2074 | { 2075 | "name": "Symfony Community", 2076 | "homepage": "https://symfony.com/contributors" 2077 | } 2078 | ], 2079 | "description": "Symfony polyfill for ctype functions", 2080 | "homepage": "https://symfony.com", 2081 | "keywords": [ 2082 | "compatibility", 2083 | "ctype", 2084 | "polyfill", 2085 | "portable" 2086 | ], 2087 | "support": { 2088 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0" 2089 | }, 2090 | "funding": [ 2091 | { 2092 | "url": "https://symfony.com/sponsor", 2093 | "type": "custom" 2094 | }, 2095 | { 2096 | "url": "https://github.com/fabpot", 2097 | "type": "github" 2098 | }, 2099 | { 2100 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2101 | "type": "tidelift" 2102 | } 2103 | ], 2104 | "time": "2021-02-19T12:13:01+00:00" 2105 | }, 2106 | { 2107 | "name": "theseer/tokenizer", 2108 | "version": "1.2.0", 2109 | "source": { 2110 | "type": "git", 2111 | "url": "https://github.com/theseer/tokenizer.git", 2112 | "reference": "75a63c33a8577608444246075ea0af0d052e452a" 2113 | }, 2114 | "dist": { 2115 | "type": "zip", 2116 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", 2117 | "reference": "75a63c33a8577608444246075ea0af0d052e452a", 2118 | "shasum": "" 2119 | }, 2120 | "require": { 2121 | "ext-dom": "*", 2122 | "ext-tokenizer": "*", 2123 | "ext-xmlwriter": "*", 2124 | "php": "^7.2 || ^8.0" 2125 | }, 2126 | "type": "library", 2127 | "autoload": { 2128 | "classmap": [ 2129 | "src/" 2130 | ] 2131 | }, 2132 | "notification-url": "https://packagist.org/downloads/", 2133 | "license": [ 2134 | "BSD-3-Clause" 2135 | ], 2136 | "authors": [ 2137 | { 2138 | "name": "Arne Blankerts", 2139 | "email": "arne@blankerts.de", 2140 | "role": "Developer" 2141 | } 2142 | ], 2143 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 2144 | "support": { 2145 | "issues": "https://github.com/theseer/tokenizer/issues", 2146 | "source": "https://github.com/theseer/tokenizer/tree/master" 2147 | }, 2148 | "funding": [ 2149 | { 2150 | "url": "https://github.com/theseer", 2151 | "type": "github" 2152 | } 2153 | ], 2154 | "time": "2020-07-12T23:59:07+00:00" 2155 | }, 2156 | { 2157 | "name": "webmozart/assert", 2158 | "version": "1.10.0", 2159 | "source": { 2160 | "type": "git", 2161 | "url": "https://github.com/webmozarts/assert.git", 2162 | "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" 2163 | }, 2164 | "dist": { 2165 | "type": "zip", 2166 | "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", 2167 | "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", 2168 | "shasum": "" 2169 | }, 2170 | "require": { 2171 | "php": "^7.2 || ^8.0", 2172 | "symfony/polyfill-ctype": "^1.8" 2173 | }, 2174 | "conflict": { 2175 | "phpstan/phpstan": "<0.12.20", 2176 | "vimeo/psalm": "<4.6.1 || 4.6.2" 2177 | }, 2178 | "require-dev": { 2179 | "phpunit/phpunit": "^8.5.13" 2180 | }, 2181 | "type": "library", 2182 | "extra": { 2183 | "branch-alias": { 2184 | "dev-master": "1.10-dev" 2185 | } 2186 | }, 2187 | "autoload": { 2188 | "psr-4": { 2189 | "Webmozart\\Assert\\": "src/" 2190 | } 2191 | }, 2192 | "notification-url": "https://packagist.org/downloads/", 2193 | "license": [ 2194 | "MIT" 2195 | ], 2196 | "authors": [ 2197 | { 2198 | "name": "Bernhard Schussek", 2199 | "email": "bschussek@gmail.com" 2200 | } 2201 | ], 2202 | "description": "Assertions to validate method input/output with nice error messages.", 2203 | "keywords": [ 2204 | "assert", 2205 | "check", 2206 | "validate" 2207 | ], 2208 | "support": { 2209 | "issues": "https://github.com/webmozarts/assert/issues", 2210 | "source": "https://github.com/webmozarts/assert/tree/1.10.0" 2211 | }, 2212 | "time": "2021-03-09T10:59:23+00:00" 2213 | } 2214 | ], 2215 | "aliases": [], 2216 | "minimum-stability": "stable", 2217 | "stability-flags": [], 2218 | "prefer-stable": false, 2219 | "prefer-lowest": false, 2220 | "platform": { 2221 | "php": "^7.4|^8.0" 2222 | }, 2223 | "platform-dev": [], 2224 | "plugin-api-version": "2.1.0" 2225 | } 2226 | -------------------------------------------------------------------------------- /phpcs.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP Code Sniffer 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | src/ 13 | tests/ 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./src 6 | 7 | 8 | ./src/Exception 9 | 10 | 11 | 12 | 13 | ./tests 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Exceptions/InlineKeyboardPaginationException.php: -------------------------------------------------------------------------------- 1 | '%d', 23 | 'first' => '« %d', 24 | 'previous' => '‹ %d', 25 | 'current' => '· %d ·', 26 | 'next' => '%d ›', 27 | 'last' => '%d »', 28 | ]; 29 | 30 | /** 31 | * @param int $maxButtons 32 | * @param bool $forceButtonCount 33 | * 34 | * @return self 35 | * @throws InlineKeyboardPaginationException 36 | */ 37 | public function setMaxButtons(int $maxButtons = 5, bool $forceButtonCount = false): self 38 | { 39 | if ($maxButtons < 5 || $maxButtons > 8) { 40 | throw InlineKeyboardPaginationException::invalidMaxButtons(); 41 | } 42 | 43 | $this->maxButtons = $maxButtons; 44 | $this->forceButtonCount = $forceButtonCount; 45 | 46 | return $this; 47 | } 48 | 49 | /** 50 | * Get the current callback format. 51 | * 52 | * @return string 53 | */ 54 | public function getCallbackDataFormat(): string 55 | { 56 | return $this->callbackDataFormat; 57 | } 58 | 59 | /** 60 | * Set the callback_data format. 61 | * 62 | * @param string $callbackDataFormat 63 | * 64 | * @return self 65 | */ 66 | public function setCallbackDataFormat(string $callbackDataFormat): self 67 | { 68 | $this->callbackDataFormat = $callbackDataFormat; 69 | 70 | return $this; 71 | } 72 | 73 | /** 74 | * Return list of keyboard button labels. 75 | * 76 | * @return array 77 | */ 78 | public function getLabels(): array 79 | { 80 | return $this->labels; 81 | } 82 | 83 | /** 84 | * Set the keyboard button labels. 85 | * 86 | * @param array $labels 87 | * 88 | * @return self 89 | */ 90 | public function setLabels(array $labels): self 91 | { 92 | $this->labels = $labels; 93 | 94 | return $this; 95 | } 96 | 97 | /** 98 | * @inheritdoc 99 | */ 100 | public function setCommand(string $command = 'pagination'): self 101 | { 102 | $this->command = $command; 103 | 104 | return $this; 105 | } 106 | 107 | /** 108 | * @inheritdoc 109 | * @throws InlineKeyboardPaginationException 110 | */ 111 | public function setSelectedPage(int $selectedPage): self 112 | { 113 | $numberOfPages = $this->getNumberOfPages(); 114 | if ($selectedPage < 1 || $selectedPage > $numberOfPages) { 115 | throw InlineKeyboardPaginationException::pageMustBeBetween(1, $numberOfPages); 116 | } 117 | 118 | $this->selectedPage = $selectedPage; 119 | 120 | return $this; 121 | } 122 | 123 | /** 124 | * Get the number of items shown per page. 125 | * 126 | * @return int 127 | */ 128 | public function getItemsPerPage(): int 129 | { 130 | return $this->itemsPerPage; 131 | } 132 | 133 | /** 134 | * Set how many items should be shown per page. 135 | * 136 | * @param int $itemsPerPage 137 | * 138 | * @return self 139 | * @throws InlineKeyboardPaginationException 140 | */ 141 | public function setItemsPerPage(int $itemsPerPage): self 142 | { 143 | if ($itemsPerPage <= 0) { 144 | throw InlineKeyboardPaginationException::invalidItemsPerPage(); 145 | } 146 | 147 | $this->itemsPerPage = $itemsPerPage; 148 | 149 | return $this; 150 | } 151 | 152 | /** 153 | * Set the items for the pagination. 154 | * 155 | * @param array $items 156 | * 157 | * @return self 158 | * @throws InlineKeyboardPaginationException 159 | */ 160 | public function setItems(array $items): self 161 | { 162 | if (empty($items)) { 163 | throw InlineKeyboardPaginationException::noItems(); 164 | } 165 | 166 | $this->items = $items; 167 | 168 | return $this; 169 | } 170 | 171 | /** 172 | * Calculate and return the number of pages. 173 | * 174 | * @return int 175 | */ 176 | public function getNumberOfPages(): int 177 | { 178 | return (int) ceil(count($this->items) / $this->itemsPerPage); 179 | } 180 | 181 | /** 182 | * TelegramBotPagination constructor. 183 | * 184 | * @inheritdoc 185 | * @throws InlineKeyboardPaginationException 186 | */ 187 | public function __construct( 188 | array $items, 189 | string $command = 'pagination', 190 | int $selectedPage = 1, 191 | int $itemsPerPage = 5 192 | ) { 193 | $this->setCommand($command); 194 | $this->setItemsPerPage($itemsPerPage); 195 | $this->setItems($items); 196 | $this->setSelectedPage($selectedPage); 197 | } 198 | 199 | /** 200 | * @inheritdoc 201 | * @throws InlineKeyboardPaginationException 202 | */ 203 | public function getPagination(int $selectedPage = null): array 204 | { 205 | if ($selectedPage !== null) { 206 | $this->setSelectedPage($selectedPage); 207 | } 208 | 209 | return [ 210 | 'items' => $this->getPreparedItems(), 211 | 'keyboard' => $this->generateKeyboard(), 212 | ]; 213 | } 214 | 215 | /** 216 | * Generate the keyboard with the correctly labelled buttons. 217 | * 218 | * @return array 219 | */ 220 | protected function generateKeyboard(): array 221 | { 222 | $buttons = $this->generateButtons(); 223 | $buttons = $this->applyButtonLabels($buttons); 224 | 225 | return array_values(array_filter($buttons)); 226 | } 227 | 228 | /** 229 | * Generate all buttons for this inline keyboard. 230 | * 231 | * @return array 232 | */ 233 | protected function generateButtons(): array 234 | { 235 | $numberOfPages = $this->getNumberOfPages(); 236 | 237 | $range = ['from' => 2, 'to' => $numberOfPages - 1]; 238 | 239 | if ($numberOfPages > $this->maxButtons) { 240 | $range = $this->generateRange(); 241 | } 242 | 243 | $buttons[1] = $this->generateButton(1); 244 | for ($i = $range['from']; $i <= $range['to']; $i++) { 245 | $buttons[$i] = $this->generateButton($i); 246 | } 247 | $buttons[$numberOfPages] = $this->generateButton($numberOfPages); 248 | 249 | return $buttons; 250 | } 251 | 252 | /** 253 | * Apply correct text labels to the keyboard buttons. 254 | * 255 | * @param array $buttons 256 | * 257 | * @return array 258 | */ 259 | protected function applyButtonLabels(array $buttons): array 260 | { 261 | $numberOfPages = $this->getNumberOfPages(); 262 | 263 | foreach ($buttons as $page => &$button) { 264 | $inFirstBlock = max($this->selectedPage, $page) <= 3; 265 | $inLastBlock = min($this->selectedPage, $page) >= $numberOfPages - 2; 266 | 267 | $labelKey = 'next'; 268 | if ($page === $this->selectedPage) { 269 | $labelKey = 'current'; 270 | } elseif ($inFirstBlock || $inLastBlock) { 271 | $labelKey = 'default'; 272 | } elseif ($page === 1) { 273 | $labelKey = 'first'; 274 | } elseif ($page === $numberOfPages) { 275 | $labelKey = 'last'; 276 | } elseif ($page < $this->selectedPage) { 277 | $labelKey = 'previous'; 278 | } 279 | 280 | $label = $this->labels[$labelKey] ?? ''; 281 | 282 | // Remove button for undefined labels. 283 | if ($label === '') { 284 | $button = null; 285 | continue; 286 | } 287 | 288 | $button['text'] = sprintf($label, $page); 289 | } 290 | 291 | return $buttons; 292 | } 293 | 294 | /** 295 | * Get the range of intermediate buttons for the keyboard. 296 | * 297 | * @return array 298 | */ 299 | protected function generateRange(): array 300 | { 301 | $numberOfIntermediateButtons = $this->maxButtons - 2; // Minus first and last buttons. 302 | $numberOfPages = $this->getNumberOfPages(); 303 | 304 | $from = $this->selectedPage - 1; 305 | $to = $this->selectedPage + 1; 306 | 307 | if ($this->selectedPage === 1) { 308 | $from = 2; 309 | $to = $this->maxButtons - 1; 310 | } elseif ($this->selectedPage === $numberOfPages) { 311 | $from = $numberOfPages - $numberOfIntermediateButtons; 312 | $to = $numberOfPages - 1; 313 | } elseif ($this->selectedPage === 3) { 314 | // Special case because this button is in the center of a flexible pagination. 315 | $to += $numberOfIntermediateButtons - 3; 316 | } elseif ($this->selectedPage < 3) { 317 | // First half. 318 | $from = $this->selectedPage; 319 | $to = $this->selectedPage + $numberOfIntermediateButtons - 1; 320 | } elseif (($numberOfPages - $this->selectedPage) < 3) { 321 | // Last half. 322 | $from = $numberOfPages - $numberOfIntermediateButtons; 323 | $to = $numberOfPages - 1; 324 | } elseif ($this->forceButtonCount) { 325 | $from = (int) max(2, $this->selectedPage - floor($numberOfIntermediateButtons / 2)); 326 | $to = $from + $numberOfIntermediateButtons - 1; 327 | } 328 | 329 | return compact('from', 'to'); 330 | } 331 | 332 | /** 333 | * Generate the button for the passed page. 334 | * 335 | * @param int $page 336 | * 337 | * @return array 338 | */ 339 | protected function generateButton(int $page): array 340 | { 341 | return [ 342 | 'text' => $page, 343 | 'callback_data' => $this->generateCallbackData($page), 344 | ]; 345 | } 346 | 347 | /** 348 | * Generate the callback data for the passed page. 349 | * 350 | * @param int $page 351 | * 352 | * @return string 353 | */ 354 | protected function generateCallbackData(int $page): string 355 | { 356 | return str_replace( 357 | ['{COMMAND}', '{OLD_PAGE}', '{NEW_PAGE}'], 358 | [$this->command, $this->selectedPage, $page], 359 | $this->callbackDataFormat 360 | ); 361 | } 362 | 363 | /** 364 | * Get the prepared items for the selected page. 365 | * 366 | * @return array 367 | */ 368 | protected function getPreparedItems(): array 369 | { 370 | return array_slice($this->items, $this->getOffset(), $this->itemsPerPage); 371 | } 372 | 373 | /** 374 | * Get the items offset for the selected page. 375 | * 376 | * @return int 377 | */ 378 | protected function getOffset(): int 379 | { 380 | return $this->itemsPerPage * ($this->selectedPage - 1); 381 | } 382 | 383 | /** 384 | * Get the parameters from the callback query. 385 | * 386 | * @todo Possibly make it work for custom formats too? 387 | * 388 | * @param string $data 389 | * 390 | * @return array 391 | */ 392 | public static function getParametersFromCallbackData(string $data): array 393 | { 394 | parse_str($data, $params); 395 | 396 | return $params; 397 | } 398 | } 399 | -------------------------------------------------------------------------------- /src/InlineKeyboardPaginator.php: -------------------------------------------------------------------------------- 1 | ikp = new InlineKeyboardPagination($this->items, $this->command, $this->selectedPage, $this->itemsPerPage); 24 | } 25 | 26 | public function testValidConstructor(): void 27 | { 28 | $data = $this->ikp->getPagination(); 29 | 30 | self::assertCount($this->itemsPerPage, $data['items']); 31 | self::assertStringStartsWith("command={$this->command}", $data['keyboard'][0]['callback_data']); 32 | } 33 | 34 | public function testInvalidConstructor(): void 35 | { 36 | $this->expectException(InlineKeyboardPaginationException::class); 37 | $this->expectExceptionMessage('Invalid page selected, must be between 1 and 10.'); 38 | 39 | new InlineKeyboardPagination(range(1, 10), 'command', 10000, 1); 40 | } 41 | 42 | public function testEmptyItemsConstructor(): void 43 | { 44 | $this->expectException(InlineKeyboardPaginationException::class); 45 | $this->expectExceptionMessage('Items list empty.'); 46 | 47 | new InlineKeyboardPagination([]); 48 | } 49 | 50 | public function testCallbackDataFormat(): void 51 | { 52 | $ikp = new InlineKeyboardPagination(range(1, 10), 'cmd', 2, 5); 53 | 54 | self::assertAllButtonPropertiesEqual([ 55 | [ 56 | 'command=cmd&oldPage=2&newPage=1', 57 | 'command=cmd&oldPage=2&newPage=2', 58 | ], 59 | ], 'callback_data', [$ikp->getPagination()['keyboard']]); 60 | 61 | $ikp->setCallbackDataFormat('{COMMAND};{OLD_PAGE};{NEW_PAGE}'); 62 | 63 | self::assertAllButtonPropertiesEqual([ 64 | [ 65 | 'cmd;2;1', 66 | 'cmd;2;2', 67 | ], 68 | ], 'callback_data', [$ikp->getPagination()['keyboard']]); 69 | } 70 | 71 | public function testCallbackDataParser(): void 72 | { 73 | $data = $this->ikp->getPagination(); 74 | 75 | $callback_data = $this->ikp::getParametersFromCallbackData($data['keyboard'][0]['callback_data']); 76 | 77 | self::assertSame([ 78 | 'command' => $this->command, 79 | 'oldPage' => (string) $this->selectedPage, 80 | 'newPage' => '1', // because we're getting the button at position 0, which is page 1 81 | ], $callback_data); 82 | } 83 | 84 | public function testValidPagination(): void 85 | { 86 | $length = (int) ceil(count($this->items) / $this->itemsPerPage); 87 | 88 | for ($i = 1; $i < $length; $i++) { 89 | $this->ikp->getPagination($i); 90 | } 91 | 92 | $this->assertSame($length, $this->ikp->getNumberOfPages()); 93 | } 94 | 95 | public function testInvalidPagination(): void 96 | { 97 | $this->expectException(InlineKeyboardPaginationException::class); 98 | $this->expectExceptionMessage('Invalid page selected, must be between 1 and 20.'); 99 | 100 | $ikp = new InlineKeyboardPagination(range(1, 20), 'command', 1, 1); 101 | $ikp->getPagination($ikp->getNumberOfPages() + 1); 102 | } 103 | 104 | public function testSetMaxButtons(): void 105 | { 106 | $this->ikp->setMaxButtons(5); 107 | $this->ikp->setMaxButtons(6); 108 | $this->ikp->setMaxButtons(7); 109 | $this->ikp->setMaxButtons(8); 110 | 111 | self::assertTrue(true); 112 | } 113 | 114 | public function testMaxButtonsTooSmall(): void 115 | { 116 | $this->expectException(InlineKeyboardPaginationException::class); 117 | $this->expectExceptionMessage('Invalid max buttons, must be between 5 and 8.'); 118 | 119 | $this->ikp->setMaxButtons(4); 120 | } 121 | 122 | public function testMaxButtonsTooBig(): void 123 | { 124 | $this->expectException(InlineKeyboardPaginationException::class); 125 | $this->expectExceptionMessage('Invalid max buttons, must be between 5 and 8.'); 126 | 127 | $this->ikp->setMaxButtons(9); 128 | } 129 | 130 | public function testForceButtonsCountWith10Pages(): void 131 | { 132 | $datas = [ 133 | [8, 1, ['· 1 ·', '2', '3', '4 ›', '5 ›', '6 ›', '7 ›', '10 »']], 134 | [8, 2, ['1', '· 2 ·', '3', '4 ›', '5 ›', '6 ›', '7 ›', '10 »']], 135 | [8, 3, ['1', '2', '· 3 ·', '4 ›', '5 ›', '6 ›', '7 ›', '10 »']], 136 | [8, 4, ['« 1', '‹ 2', '‹ 3', '· 4 ·', '5 ›', '6 ›', '7 ›', '10 »']], 137 | [8, 5, ['« 1', '‹ 2', '‹ 3', '‹ 4', '· 5 ·', '6 ›', '7 ›', '10 »']], 138 | [8, 6, ['« 1', '‹ 3', '‹ 4', '‹ 5', '· 6 ·', '7 ›', '8 ›', '10 »']], 139 | [8, 7, ['« 1', '‹ 4', '‹ 5', '‹ 6', '· 7 ·', '8 ›', '9 ›', '10 »']], 140 | [8, 8, ['« 1', '‹ 4', '‹ 5', '‹ 6', '‹ 7', '· 8 ·', '9', '10']], 141 | [8, 9, ['« 1', '‹ 4', '‹ 5', '‹ 6', '‹ 7', '8', '· 9 ·', '10']], 142 | [8, 10, ['« 1', '‹ 4', '‹ 5', '‹ 6', '‹ 7', '8', '9', '· 10 ·']], 143 | [7, 1, ['· 1 ·', '2', '3', '4 ›', '5 ›', '6 ›', '10 »']], 144 | [7, 2, ['1', '· 2 ·', '3', '4 ›', '5 ›', '6 ›', '10 »']], 145 | [7, 3, ['1', '2', '· 3 ·', '4 ›', '5 ›', '6 ›', '10 »']], 146 | [7, 4, ['« 1', '‹ 2', '‹ 3', '· 4 ·', '5 ›', '6 ›', '10 »']], 147 | [7, 5, ['« 1', '‹ 3', '‹ 4', '· 5 ·', '6 ›', '7 ›', '10 »']], 148 | [7, 6, ['« 1', '‹ 4', '‹ 5', '· 6 ·', '7 ›', '8 ›', '10 »']], 149 | [7, 7, ['« 1', '‹ 5', '‹ 6', '· 7 ·', '8 ›', '9 ›', '10 »']], 150 | [7, 8, ['« 1', '‹ 5', '‹ 6', '‹ 7', '· 8 ·', '9', '10']], 151 | [7, 9, ['« 1', '‹ 5', '‹ 6', '‹ 7', '8', '· 9 ·', '10']], 152 | [7, 10, ['« 1', '‹ 5', '‹ 6', '‹ 7', '8', '9', '· 10 ·']], 153 | [6, 1, ['· 1 ·', '2', '3', '4 ›', '5 ›', '10 »']], 154 | [6, 2, ['1', '· 2 ·', '3', '4 ›', '5 ›', '10 »']], 155 | [6, 3, ['1', '2', '· 3 ·', '4 ›', '5 ›', '10 »']], 156 | [6, 4, ['« 1', '‹ 2', '‹ 3', '· 4 ·', '5 ›', '10 »']], 157 | [6, 5, ['« 1', '‹ 3', '‹ 4', '· 5 ·', '6 ›', '10 »']], 158 | [6, 6, ['« 1', '‹ 4', '‹ 5', '· 6 ·', '7 ›', '10 »']], 159 | [6, 7, ['« 1', '‹ 5', '‹ 6', '· 7 ·', '8 ›', '10 »']], 160 | [6, 8, ['« 1', '‹ 6', '‹ 7', '· 8 ·', '9', '10']], 161 | [6, 9, ['« 1', '‹ 6', '‹ 7', '8', '· 9 ·', '10']], 162 | [6, 10, ['« 1', '‹ 6', '‹ 7', '8', '9', '· 10 ·']], 163 | [5, 1, ['· 1 ·', '2', '3', '4 ›', '10 »']], 164 | [5, 2, ['1', '· 2 ·', '3', '4 ›', '10 »']], 165 | [5, 3, ['1', '2', '· 3 ·', '4 ›', '10 »']], 166 | [5, 4, ['« 1', '‹ 3', '· 4 ·', '5 ›', '10 »']], 167 | [5, 5, ['« 1', '‹ 4', '· 5 ·', '6 ›', '10 »']], 168 | [5, 6, ['« 1', '‹ 5', '· 6 ·', '7 ›', '10 »']], 169 | [5, 7, ['« 1', '‹ 6', '· 7 ·', '8 ›', '10 »']], 170 | [5, 8, ['« 1', '‹ 7', '· 8 ·', '9', '10']], 171 | [5, 9, ['« 1', '‹ 7', '8', '· 9 ·', '10']], 172 | [5, 10, ['« 1', '‹ 7', '8', '9', '· 10 ·']], 173 | ]; 174 | 175 | $ikp = new InlineKeyboardPagination(range(1, 10), 'cbdata', 1, 1); 176 | 177 | foreach ($datas as $data) { 178 | [$max_buttons, $page, $buttons] = $data; 179 | 180 | $ikp->setMaxButtons($max_buttons, true); 181 | self::assertAllButtonPropertiesEqual( 182 | [$buttons], 183 | 'text', 184 | [$ikp->getPagination($page)['keyboard']], 185 | "MaxButtons: {$max_buttons}, Page: {$page}" 186 | ); 187 | } 188 | } 189 | 190 | public function testForceButtonsCountWith3Pages(): void 191 | { 192 | $datas = [ 193 | [8, 1, ['· 1 ·', '2', '3']], 194 | [8, 2, ['1', '· 2 ·', '3']], 195 | [8, 3, ['1', '2', '· 3 ·']], 196 | [7, 1, ['· 1 ·', '2', '3']], 197 | [7, 2, ['1', '· 2 ·', '3']], 198 | [7, 3, ['1', '2', '· 3 ·']], 199 | [6, 1, ['· 1 ·', '2', '3']], 200 | [6, 2, ['1', '· 2 ·', '3']], 201 | [6, 3, ['1', '2', '· 3 ·']], 202 | [5, 1, ['· 1 ·', '2', '3']], 203 | [5, 2, ['1', '· 2 ·', '3']], 204 | [5, 3, ['1', '2', '· 3 ·']], 205 | ]; 206 | 207 | $ikp = new InlineKeyboardPagination(range(1, 3), 'cbdata', 1, 1); 208 | 209 | foreach ($datas as $data) { 210 | [$max_buttons, $page, $buttons] = $data; 211 | 212 | $ikp->setMaxButtons($max_buttons, true); 213 | self::assertAllButtonPropertiesEqual( 214 | [$buttons], 215 | 'text', 216 | [$ikp->getPagination($page)['keyboard']], 217 | "MaxButtons: {$max_buttons}, Page: {$page}" 218 | ); 219 | } 220 | } 221 | 222 | public function testFlexibleButtonsCount(): void 223 | { 224 | $datas = [ 225 | [8, 1, ['· 1 ·', '2', '3', '4 ›', '5 ›', '6 ›', '7 ›', '10 »']], 226 | [8, 2, ['1', '· 2 ·', '3', '4 ›', '5 ›', '6 ›', '7 ›', '10 »']], 227 | [8, 3, ['1', '2', '· 3 ·', '4 ›', '5 ›', '6 ›', '7 ›', '10 »']], 228 | [8, 4, ['« 1', '‹ 3', '· 4 ·', '5 ›', '10 »']], 229 | [8, 5, ['« 1', '‹ 4', '· 5 ·', '6 ›', '10 »']], 230 | [8, 6, ['« 1', '‹ 5', '· 6 ·', '7 ›', '10 »']], 231 | [8, 7, ['« 1', '‹ 6', '· 7 ·', '8 ›', '10 »']], 232 | [8, 8, ['« 1', '‹ 4', '‹ 5', '‹ 6', '‹ 7', '· 8 ·', '9', '10']], 233 | [8, 9, ['« 1', '‹ 4', '‹ 5', '‹ 6', '‹ 7', '8', '· 9 ·', '10']], 234 | [8, 10, ['« 1', '‹ 4', '‹ 5', '‹ 6', '‹ 7', '8', '9', '· 10 ·']], 235 | [7, 1, ['· 1 ·', '2', '3', '4 ›', '5 ›', '6 ›', '10 »']], 236 | [7, 2, ['1', '· 2 ·', '3', '4 ›', '5 ›', '6 ›', '10 »']], 237 | [7, 3, ['1', '2', '· 3 ·', '4 ›', '5 ›', '6 ›', '10 »']], 238 | [7, 4, ['« 1', '‹ 3', '· 4 ·', '5 ›', '10 »']], 239 | [7, 5, ['« 1', '‹ 4', '· 5 ·', '6 ›', '10 »']], 240 | [7, 6, ['« 1', '‹ 5', '· 6 ·', '7 ›', '10 »']], 241 | [7, 7, ['« 1', '‹ 6', '· 7 ·', '8 ›', '10 »']], 242 | [7, 8, ['« 1', '‹ 5', '‹ 6', '‹ 7', '· 8 ·', '9', '10']], 243 | [7, 9, ['« 1', '‹ 5', '‹ 6', '‹ 7', '8', '· 9 ·', '10']], 244 | [7, 10, ['« 1', '‹ 5', '‹ 6', '‹ 7', '8', '9', '· 10 ·']], 245 | [6, 1, ['· 1 ·', '2', '3', '4 ›', '5 ›', '10 »']], 246 | [6, 2, ['1', '· 2 ·', '3', '4 ›', '5 ›', '10 »']], 247 | [6, 3, ['1', '2', '· 3 ·', '4 ›', '5 ›', '10 »']], 248 | [6, 4, ['« 1', '‹ 3', '· 4 ·', '5 ›', '10 »']], 249 | [6, 5, ['« 1', '‹ 4', '· 5 ·', '6 ›', '10 »']], 250 | [6, 6, ['« 1', '‹ 5', '· 6 ·', '7 ›', '10 »']], 251 | [6, 7, ['« 1', '‹ 6', '· 7 ·', '8 ›', '10 »']], 252 | [6, 8, ['« 1', '‹ 6', '‹ 7', '· 8 ·', '9', '10']], 253 | [6, 9, ['« 1', '‹ 6', '‹ 7', '8', '· 9 ·', '10']], 254 | [6, 10, ['« 1', '‹ 6', '‹ 7', '8', '9', '· 10 ·']], 255 | [5, 1, ['· 1 ·', '2', '3', '4 ›', '10 »']], 256 | [5, 2, ['1', '· 2 ·', '3', '4 ›', '10 »']], 257 | [5, 3, ['1', '2', '· 3 ·', '4 ›', '10 »']], 258 | [5, 4, ['« 1', '‹ 3', '· 4 ·', '5 ›', '10 »']], 259 | [5, 5, ['« 1', '‹ 4', '· 5 ·', '6 ›', '10 »']], 260 | [5, 6, ['« 1', '‹ 5', '· 6 ·', '7 ›', '10 »']], 261 | [5, 7, ['« 1', '‹ 6', '· 7 ·', '8 ›', '10 »']], 262 | [5, 8, ['« 1', '‹ 7', '· 8 ·', '9', '10']], 263 | [5, 9, ['« 1', '‹ 7', '8', '· 9 ·', '10']], 264 | [5, 10, ['« 1', '‹ 7', '8', '9', '· 10 ·']], 265 | ]; 266 | 267 | $ikp = new InlineKeyboardPagination(range(1, 10), 'cbdata', 1, 1); 268 | 269 | foreach ($datas as $data) { 270 | [$max_buttons, $page, $buttons] = $data; 271 | 272 | $ikp->setMaxButtons($max_buttons, false); 273 | self::assertAllButtonPropertiesEqual( 274 | [$buttons], 275 | 'text', 276 | [$ikp->getPagination($page)['keyboard']], 277 | "MaxButtons: {$max_buttons}, Page: {$page}" 278 | ); 279 | } 280 | } 281 | 282 | public function testGetCallbackDataFormat(): void 283 | { 284 | // Test default value. 285 | self::assertSame( 286 | 'command={COMMAND}&oldPage={OLD_PAGE}&newPage={NEW_PAGE}', 287 | $this->ikp->getCallbackDataFormat() 288 | ); 289 | 290 | // Test custom value. 291 | $customCallbackDataFormat = 'c={COMMAND}&op={OLD_PAGE}&np={NEW_PAGE}'; 292 | $this->ikp->setCallbackDataFormat($customCallbackDataFormat); 293 | self::assertSame( 294 | $customCallbackDataFormat, 295 | $this->ikp->getCallbackDataFormat() 296 | ); 297 | } 298 | 299 | public function testSelectedPageTooLow(): void 300 | { 301 | $this->expectException(InlineKeyboardPaginationException::class); 302 | $this->expectExceptionMessage('Invalid page selected, must be between 1 and 10.'); 303 | 304 | $ikp = new InlineKeyboardPagination(range(1, 10), 'command', 1, 1); 305 | $ikp->setSelectedPage(0); 306 | } 307 | 308 | public function testSelectedPageTooHigh(): void 309 | { 310 | $this->expectException(InlineKeyboardPaginationException::class); 311 | $this->expectExceptionMessage('Invalid page selected, must be between 1 and 10.'); 312 | 313 | $ikp = new InlineKeyboardPagination(range(1, 10), 'command', 1, 1); 314 | $ikp->setSelectedPage(11); 315 | } 316 | 317 | public function testGetItemsPerPage(): void 318 | { 319 | $ikp = new InlineKeyboardPagination(range(1, 10), 'command', 1, 4); 320 | 321 | self::assertEquals(4, $ikp->getItemsPerPage()); 322 | 323 | $ikp->setItemsPerPage(2); 324 | 325 | self::assertEquals(2, $ikp->getItemsPerPage()); 326 | } 327 | 328 | public function testInvalidItemsPerPage(): void 329 | { 330 | $this->expectException(InlineKeyboardPaginationException::class); 331 | $this->expectExceptionMessage('Invalid number of items per page, must be at least 1.'); 332 | 333 | $this->ikp->setItemsPerPage(0); 334 | } 335 | 336 | public function testButtonLabels(): void 337 | { 338 | $cbdata = 'command=%s&oldPage=%d&newPage=%d'; 339 | $command = 'cbdata'; 340 | $ikp1 = new InlineKeyboardPagination(range(1, 1), $command, 1, $this->itemsPerPage); 341 | $ikp10 = new InlineKeyboardPagination(range(1, $this->itemsPerPage * 10), $command, 1, $this->itemsPerPage); 342 | 343 | // current 344 | $keyboard = [$ikp1->getPagination(1)['keyboard']]; 345 | self::assertAllButtonPropertiesEqual([ 346 | ['· 1 ·'], 347 | ], 'text', $keyboard); 348 | self::assertAllButtonPropertiesEqual([ 349 | [ 350 | sprintf($cbdata, $command, 1, 1), 351 | ], 352 | ], 'callback_data', $keyboard); 353 | 354 | // first, previous, current, next, last 355 | $keyboard = [$ikp10->getPagination(5)['keyboard']]; 356 | self::assertAllButtonPropertiesEqual([ 357 | ['« 1', '‹ 4', '· 5 ·', '6 ›', '10 »'], 358 | ], 'text', $keyboard); 359 | self::assertAllButtonPropertiesEqual([ 360 | [ 361 | sprintf($cbdata, $command, 5, 1), 362 | sprintf($cbdata, $command, 5, 4), 363 | sprintf($cbdata, $command, 5, 5), 364 | sprintf($cbdata, $command, 5, 6), 365 | sprintf($cbdata, $command, 5, 10), 366 | ], 367 | ], 'callback_data', $keyboard); 368 | 369 | // first, previous, current, last 370 | $keyboard = [$ikp10->getPagination(9)['keyboard']]; 371 | self::assertAllButtonPropertiesEqual([ 372 | ['« 1', '‹ 7', '8', '· 9 ·', '10'], 373 | ], 'text', $keyboard); 374 | self::assertAllButtonPropertiesEqual([ 375 | [ 376 | sprintf($cbdata, $command, 9, 1), 377 | sprintf($cbdata, $command, 9, 7), 378 | sprintf($cbdata, $command, 9, 8), 379 | sprintf($cbdata, $command, 9, 9), 380 | sprintf($cbdata, $command, 9, 10), 381 | ], 382 | ], 'callback_data', $keyboard); 383 | 384 | // first, previous, current 385 | $keyboard = [$ikp10->getPagination(10)['keyboard']]; 386 | self::assertAllButtonPropertiesEqual([ 387 | ['« 1', '‹ 7', '8', '9', '· 10 ·'], 388 | ], 'text', $keyboard); 389 | self::assertAllButtonPropertiesEqual([ 390 | [ 391 | sprintf($cbdata, $command, 10, 1), 392 | sprintf($cbdata, $command, 10, 7), 393 | sprintf($cbdata, $command, 10, 8), 394 | sprintf($cbdata, $command, 10, 9), 395 | sprintf($cbdata, $command, 10, 10), 396 | ], 397 | ], 'callback_data', $keyboard); 398 | 399 | // custom labels, skipping some buttons 400 | // first, previous, current, next, last 401 | $labels = [ 402 | 'first' => '', 403 | 'previous' => 'previous %d', 404 | 'current' => null, 405 | 'next' => '%d next', 406 | 'last' => 'last', 407 | ]; 408 | $ikp10->setLabels($labels); 409 | self::assertEquals($labels, $ikp10->getLabels()); 410 | 411 | $keyboard = [$ikp10->getPagination(5)['keyboard']]; 412 | self::assertAllButtonPropertiesEqual([ 413 | ['previous 4', '6 next', 'last'], 414 | ], 'text', $keyboard); 415 | self::assertAllButtonPropertiesEqual([ 416 | [ 417 | sprintf($cbdata, $command, 5, 4), 418 | sprintf($cbdata, $command, 5, 6), 419 | sprintf($cbdata, $command, 5, 10), 420 | ], 421 | ], 'callback_data', $keyboard); 422 | } 423 | 424 | public static function assertButtonPropertiesEqual($value, $property, $keyboard, $row, $column, $message = ''): void 425 | { 426 | $row_raw = array_values($keyboard)[$row]; 427 | $column_raw = array_values($row_raw)[$column]; 428 | 429 | self::assertSame($value, $column_raw[$property], $message); 430 | } 431 | 432 | public static function assertRowButtonPropertiesEqual(array $values, $property, $keyboard, $row, $message = ''): void 433 | { 434 | $column = 0; 435 | foreach ($values as $value) { 436 | self::assertButtonPropertiesEqual($value, $property, $keyboard, $row, $column++, $message); 437 | } 438 | self::assertCount(count(array_values($keyboard)[$row]), $values); 439 | } 440 | 441 | public static function assertAllButtonPropertiesEqual(array $all_values, $property, $keyboard, $message = ''): void 442 | { 443 | $row = 0; 444 | foreach ($all_values as $values) { 445 | self::assertRowButtonPropertiesEqual($values, $property, $keyboard, $row++, $message); 446 | } 447 | self::assertCount(count($keyboard), $all_values); 448 | } 449 | } 450 | --------------------------------------------------------------------------------