├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── composer.json ├── config └── base62.php ├── phpunit.xml ├── src ├── Base62.php ├── Base62ServiceProvider.php ├── Drivers │ ├── BaseEncoder.php │ ├── BasicEncoder.php │ ├── BcmathEncoder.php │ ├── EncoderFactory.php │ ├── Exceptions │ │ └── DriverNotFoundException.php │ └── GmpEncoder.php └── Facades │ └── Base62.php └── tests ├── Base62LaravelTest.php ├── Base62Test.php ├── BcmathEncoderTest.php └── GmpEncoderTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /.metadata 3 | /.idea 4 | .DS_Store 5 | .project 6 | composer.phar 7 | phpunit.phar 8 | composer.lock 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Travis CI configuration 2 | sudo: true 3 | language: php 4 | 5 | php: 6 | - 7.1 7 | - 7.2 8 | - 7.3 9 | - 7.4 10 | 11 | before_script: 12 | - composer self-update 13 | - composer install 14 | 15 | script: vendor/bin/phpunit 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Siro Díaz Palazón 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | vendor/autoload.php: 2 | composer install --no-interaction --prefer-dist 3 | 4 | test: 5 | vendor/bin/phpunit --verbose 6 | 7 | sniff: 8 | vendor/bin/phpcs --standard=PSR2 src -n 9 | 10 | .PHONY: cbf 11 | cbf: 12 | vendor/bin/phpcbf -v -p --standard=PSR2 src 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Base62 2 | 3 | [![Build Status](https://travis-ci.org/SiroDiaz/Base62.svg?branch=develop)](https://travis-ci.org/SiroDiaz/Base62) 4 | [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3XKLA6VTYVSKW&source=url) 5 | 6 | Base62 encoder and decorder also for big numbers. Useful to short database numeric ids in URLs. 7 | 8 | ## requirements 9 | 10 | * requires PHP >= 7.1.0 or higher 11 | * Composer 12 | * GMP (preferred) or BCMath extensions enabled. 13 | 14 | ## Composer 15 | 16 | $ composer require base62/base62 17 | 18 | ## Laravel 5 19 | 20 | You just need to follow the composer command listed before and then you have to publish the base62.php config file into 21 | the config path of Laravel with the following command: 22 | 23 | $ php artisan vendor:publish --tag=base62/base62 24 | 25 | Then you can change in `config/base62.php` the default driver that is 'basic' (the PHP encoder implementation) for another supported 26 | by your host. It is recomended to use GMP extension because it is the most fast solution. 27 | Allowed encoders and decoders drivers are: 28 | - basic 29 | - gmp 30 | - bcmath 31 | 32 | ## Quick Start and Examples 33 | 34 | #### Methods 35 | 36 | encode and decode 37 | 38 | #### Encoders/Decoders drivers 39 | 40 | - basic 41 | - gmp 42 | - bcmath 43 | 44 | #### Examples 45 | 46 | Encoding and decoding litle numbers. 47 | 48 | ```php 49 | require 'vendor/autoload.php'; 50 | 51 | use Base62\Base62; 52 | 53 | $base62 = new Base62(); // by default use 'basic' driver. It is the default PHP encoder and decoder 54 | $encodedValue = $base62->encode(200000); // 'Q1O' 55 | $decodedValue = $base62->decode($encodedValue); // 200000 56 | ``` 57 | 58 | Encoding and decoding big numbers. An important thing you must take in count: your PHP can be 32 or 64 bit, 59 | this means that a representation of an integer can take a maximum or 32 or 64 bit. This is a important limitation 60 | when you work with big integers, but for solve this problem we have GMP and BCMath native extensions for PHP. 61 | 62 | 63 | ```php 64 | require 'vendor/autoload.php'; 65 | 66 | use Base62\Base62; 67 | 68 | // unsigned bigint (MySQL) 18446744073709551615 69 | $id = '214748364787898954454'; 70 | 71 | $base62 = new Base62('gmp'); 72 | // print encoded base62 number id 73 | $encodedValue = $base62->encode($id); // '47rhmv5JHMPe' 74 | $decodedValue = $base62->decode($base62->encode($id)); // '214748364787898954454' 75 | ``` 76 | 77 | Note that encode method uses strings as argument and not an integer. This is the best option by a simple reason. 78 | Imagine that you uses an integer that can not been represented by native PHP 32 or 64 bit interpreter, what would happen? 79 | Simple, the integer is truncated and can take negative values or a different positive number. 80 | 81 | ## License 82 | 83 | [MIT License](https://opensource.org/licenses/MIT) Copyright © 2014-present, Siro Díaz Palazón 84 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "base62/base62", 3 | "description": "base62 encoder and decoder also for big numbers with Laravel integration", 4 | "keywords": [ 5 | "base62", 6 | "Laravel", 7 | "encoder", 8 | "decoder", 9 | "url", 10 | "string", 11 | "BigInteger" 12 | ], 13 | "type": "library", 14 | "version": "3.1.1", 15 | "license": "MIT", 16 | "authors": [ 17 | { 18 | "name": "Siro Diaz Palazon", 19 | "email": "siro_diaz@yahoo.com" 20 | } 21 | ], 22 | "require": { 23 | "php": ">=7.1.0" 24 | }, 25 | "require-dev": { 26 | "phpunit/phpunit": "^7.0", 27 | "squizlabs/php_codesniffer": "3.*", 28 | "orchestra/testbench": "^3.5" 29 | }, 30 | "autoload": { 31 | "psr-4": { 32 | "Base62\\": "src" 33 | } 34 | }, 35 | "autoload-dev": { 36 | "psr-4": { 37 | "Base62\\Tests\\": "tests/" 38 | } 39 | }, 40 | "extra": { 41 | "laravel": { 42 | "providers": [ 43 | "Base62\\Base62ServiceProvider" 44 | ] 45 | } 46 | }, 47 | "suggest": { 48 | "ext-gmp": "This extension enables faster big integer encoding and decoding.", 49 | "ext-bcmath": "This extension enables arbitrary precision calculation encoding and decoding." 50 | }, 51 | "support": { 52 | "issues": "https://github.com/SiroDiaz/Base62/issues", 53 | "source": "https://github.com/SiroDiaz/Base62" 54 | }, 55 | "scripts": { 56 | "test": "phpunit" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /config/base62.php: -------------------------------------------------------------------------------- 1 | 'basic', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | ./tests/ 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Base62.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2018 Siro Diaz 6 | * @license MIT 7 | * @see https://github.com/SiroDiaz/Base62 8 | */ 9 | namespace Base62; 10 | 11 | use Base62\Drivers\BaseEncoder; 12 | use Base62\Drivers\EncoderFactory; 13 | 14 | /** 15 | * The entry point class that is used to choose a big integer driver 16 | * and also to bind the encode and decode methods. 17 | */ 18 | class Base62 19 | { 20 | /** 21 | * The list of characters availables for the standard base62 encoder/decoder. 22 | * 23 | * @var string CHARS constant contains all valid characters. 24 | */ 25 | const CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 26 | 27 | /** 28 | * Pre computed base 62 characters in reverse order for improve performance. 29 | * 30 | * @var string REVERSE_CHARS contains CHARS constant in reverse order. 31 | */ 32 | const REVERSE_CHARS = 'zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA9876543210'; 33 | 34 | /** 35 | * Pre computed base 62 string length. Better than strlen(Base62::CHARS). 36 | * 37 | * @var integer 38 | */ 39 | const BASE_LENGTH = 62; 40 | 41 | /** 42 | * The encoder used to perform the base 62 operations. 43 | * 44 | * @var BaseEncoder 45 | */ 46 | private $encoder; 47 | 48 | /** 49 | * Constructor method that recieves an instance of the encoder 50 | */ 51 | public function __construct($encoder = 'basic') 52 | { 53 | $encoderFactory = new EncoderFactory(); 54 | $this->encoder = $encoderFactory->getEncoder($encoder); 55 | } 56 | 57 | /** 58 | * Method to encode data to base62 59 | * 60 | * @param mixed $number the number to convert to base62 61 | * @return mixed if is a valid number will return a string 62 | * else returns false 63 | */ 64 | public function encode($number) 65 | { 66 | return $this->encoder->encode($number); 67 | } 68 | 69 | /** 70 | * Decode the string to obtain the number. 71 | * 72 | * @param string $base62 the base62 encoded number 73 | * @return mixed false if the base doesn't matches 74 | * or if the position is less than 0. 75 | * String the decoded string 76 | */ 77 | 78 | public function decode($base62) 79 | { 80 | return $this->encoder->decode($base62); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Base62ServiceProvider.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2018 Siro Diaz 6 | * @license MIT 7 | * @see https://github.com/SiroDiaz/Base62 8 | */ 9 | namespace Base62; 10 | 11 | use Illuminate\Support\ServiceProvider; 12 | 13 | /** 14 | * Base62ServiceProvider is a service provider for the Laravel 15 | * framework. 16 | */ 17 | class Base62ServiceProvider extends ServiceProvider 18 | { 19 | /** 20 | * Bootstrap the application services. 21 | * 22 | * @return void 23 | */ 24 | public function boot() 25 | { 26 | $this->registerConfigs(); 27 | } 28 | 29 | /** 30 | * Register the application services. 31 | * 32 | * @return void 33 | */ 34 | public function register() 35 | { 36 | $this->app->singleton(Base62::class, function ($app) { 37 | return new Base62($app['config']['base62.driver']); 38 | }); 39 | 40 | $this->app->alias(Base62::class, 'Base62'); 41 | $this->registerConfigs(); 42 | } 43 | 44 | /** 45 | * Register the publishable files. 46 | * 47 | * @return void 48 | */ 49 | private function registerPublishableResources() 50 | { 51 | /* 52 | $configPath = dirname(__DIR__).'/config'; 53 | $publishable = [ 54 | 'config' => [ 55 | "{$configPath}/base62.php" => config_path('base62.php'), 56 | ], 57 | ]; 58 | 59 | foreach ($publishable as $group => $paths) { 60 | $this->publishes($paths, $group); 61 | } 62 | */ 63 | } 64 | 65 | /** 66 | * Register the configuration file in the Laravel or Lumen app. 67 | * 68 | * @return void 69 | */ 70 | public function registerConfigs() 71 | { 72 | if ($this->app instanceof LaravelApplication && $this->app->runningInConsole()) { 73 | $this->registerPublishableResources(); 74 | } elseif ($this->app instanceof LumenApplication) { 75 | $this->app->configure('base62'); 76 | } 77 | 78 | $this->publishes([ 79 | __DIR__.'/../config/base62.php' => config_path('base62.php') 80 | ], 'base62/base62'); 81 | 82 | $this->mergeConfigFrom( 83 | dirname(__DIR__).'/config/base62.php', 'base62' 84 | ); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Drivers/BaseEncoder.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2018 Siro Diaz 6 | * @license MIT 7 | * @see https://github.com/SiroDiaz/Base62 8 | */ 9 | 10 | namespace Base62\Drivers; 11 | 12 | /** 13 | * BaseEncoder is the driver interface that must be implemented by 14 | * all drivers. 15 | */ 16 | interface BaseEncoder 17 | { 18 | /** 19 | * Encodes a positive number passed as a string. 20 | * 21 | * @param string $number The number passed as a string. 22 | */ 23 | public function encode($number); 24 | 25 | /** 26 | * Decodes a a base 62 string and returns a positive number as string. 27 | * 28 | * @param string $data The string passed as a string. 29 | */ 30 | public function decode($data); 31 | } 32 | -------------------------------------------------------------------------------- /src/Drivers/BasicEncoder.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2018 Siro Diaz 6 | * @license MIT 7 | * @see https://github.com/SiroDiaz/Base62 8 | */ 9 | namespace Base62\Drivers; 10 | 11 | use Base62\Base62; 12 | use Base62\Drivers\BaseEncoder; 13 | use InvalidArgumentException; 14 | 15 | /** 16 | * BasicEncoder is the native PHP driver. 17 | * It has two public methods, inherited from the BaseEncoder abstract class. 18 | */ 19 | class BasicEncoder implements BaseEncoder 20 | { 21 | /** 22 | * 23 | * @inheritdoc 24 | * 25 | * @return string $number The number decoded but as string 26 | */ 27 | public function encode($number) 28 | { 29 | if (!$this->isValidNumber($number)) { 30 | throw new InvalidArgumentException('Invalid number for BasicEncoder'); 31 | } 32 | if ($number === 0 || $number === '0') { 33 | return '0'; 34 | } 35 | 36 | $encodedNum = ''; 37 | 38 | while ($number > 0) { 39 | $encodedNum = Base62::CHARS[$number % Base62::BASE_LENGTH] . $encodedNum; 40 | $number = (int) (floor($number) / Base62::BASE_LENGTH); 41 | } 42 | 43 | return $encodedNum; 44 | } 45 | 46 | /** 47 | * 48 | * @inheritdoc 49 | * 50 | * @return string $number The number decoded but as string 51 | */ 52 | public function decode($data) 53 | { 54 | if (!is_string($data) || !preg_match("/^[a-zA-Z0-9]+$/", $data)) { 55 | throw new InvalidArgumentException('Must be a base 62 valid string'); 56 | } 57 | 58 | $val = 0; 59 | $base62Chars = array_reverse(str_split($data)); 60 | $chars = str_split(Base62::CHARS); 61 | foreach ($base62Chars as $index => &$character) { 62 | $val += array_search($character, $chars) * pow(Base62::BASE_LENGTH, $index); 63 | } 64 | 65 | return $val === 0 ? '0' : (string) $val; 66 | } 67 | 68 | /** 69 | * Checks if the number is positive and valid ([0-9]+), and then 70 | * checks if the number is lower or equal to the maximum integer 71 | * available in PHP. 72 | * 73 | * @param int $number 74 | * @return bool 75 | */ 76 | private function isValidNumber($number) 77 | { 78 | $number = (string) $number; 79 | 80 | return ctype_digit($number) && !$this->isBigInteger($number); 81 | } 82 | 83 | /** 84 | * Determines if is a big integer compared 85 | * 86 | * @param string $number 87 | * @return bool True if $number is greater than PHP_INT_MAX (maximum integer). 88 | */ 89 | private function isBigInteger($number) 90 | { 91 | if (function_exists('gmp_init')) { 92 | $gmpInt1 = gmp_init($number); 93 | $gmpInt2 = gmp_init((string) PHP_INT_MAX); 94 | 95 | return gmp_cmp($gmpInt1, $gmpInt2) >= 1; 96 | } else if (function_exists('bccomp')) { 97 | return bccomp($number, (string) PHP_INT_MAX) === 1; 98 | } 99 | 100 | return true; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Drivers/BcmathEncoder.php: -------------------------------------------------------------------------------- 1 | 14 | * @copyright 2018 Siro Díaz Palazón 15 | * @license http://www.opensource.org/licenses/MIT The MIT License 16 | */ 17 | class BcmathEncoder implements BaseEncoder 18 | { 19 | /** 20 | * 21 | * @inheritdoc 22 | * 23 | * @return string $number The number decoded but as string 24 | */ 25 | public function encode($number) 26 | { 27 | if (!preg_match("/^(\d)+$/", (string) $number)) { 28 | throw new InvalidArgumentException('The value can only accept numbers'); 29 | } 30 | if ($number === 0) { 31 | return '0'; 32 | } 33 | 34 | $number = (string) $number; 35 | $encodedNumber = ''; 36 | while (bccomp($number, '0') === 1) { 37 | $remainder = bcmod($number, '62'); 38 | $encodedNumber = Base62::CHARS[(int)$remainder] . $encodedNumber; 39 | $number = bcdiv($number, '62'); 40 | } 41 | 42 | return $encodedNumber; 43 | } 44 | 45 | /** 46 | * 47 | * @inheritdoc 48 | * 49 | * @return string $number The number encoded 50 | */ 51 | public function decode($data) 52 | { 53 | if (!is_string($data) || !preg_match("/^[a-zA-Z0-9]+$/", $data)) { 54 | throw new InvalidArgumentException('Must be a base 62 valid string'); 55 | } 56 | 57 | $val = 0; 58 | $base62Chars = array_reverse(str_split($data)); 59 | $chars = str_split(Base62::CHARS); 60 | 61 | foreach ($base62Chars as $index => &$character) { 62 | $val = bcadd($val, bcmul(array_search($character, $chars), bcpow(Base62::BASE_LENGTH, $index))); 63 | } 64 | 65 | return $val; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Drivers/EncoderFactory.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2018 Siro Diaz 6 | * @license MIT 7 | * @see https://github.com/SiroDiaz/Base62 8 | */ 9 | namespace Base62\Drivers; 10 | 11 | /** 12 | * Factory method implementation for generate a driver encoder by name. 13 | * Allowed drivers are 'gmp', 'basic', and 'bcmath'. 14 | */ 15 | class EncoderFactory 16 | { 17 | /** 18 | * Generates an encoder and returns the instance. 19 | * 20 | * @param string $type The type of encoder to instantiate. 21 | * Only availables "gmp", "basic" and "bcmath". 22 | * @throws Base62\Drivers\Exceptions\DriverNotFoundException 23 | * @return Base62\Drivers\BaseEncoder an instance of a avalilable driver. 24 | */ 25 | public function getEncoder($type) 26 | { 27 | $className = $this->generateClassName($type); 28 | if (!class_exists($className)) { 29 | throw new DriverNotFoundException('EncoderNotFound'); 30 | } 31 | 32 | return new $className(); 33 | } 34 | 35 | /** 36 | * Generate a string with the namespace and class name for a given 37 | * encoder name. 38 | * 39 | * @param string $encoderName The encoder name. 40 | * @return string The full namespace and class name concatenated. 41 | */ 42 | private function generateClassName($encoderName) 43 | { 44 | $classNamespace = 'Base62\\Drivers\\'; 45 | $driverName = ucfirst(strtolower($encoderName)) . 'Encoder'; 46 | return $classNamespace . $driverName; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Drivers/Exceptions/DriverNotFoundException.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2018 Siro Diaz 6 | * @license MIT 7 | * @see https://github.com/SiroDiaz/Base62 8 | */ 9 | namespace Base62\Drivers\Exceptions; 10 | 11 | use Exception; 12 | 13 | /** 14 | * The driver not found exception. 15 | */ 16 | class DriverNotFoundException extends Exception 17 | { 18 | } 19 | -------------------------------------------------------------------------------- /src/Drivers/GmpEncoder.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2018 Siro Diaz 6 | * @license MIT 7 | * @see https://github.com/SiroDiaz/Base62 8 | */ 9 | namespace Base62\Drivers; 10 | 11 | use Base62\Drivers\BaseEncoder; 12 | use InvalidArgumentException; 13 | 14 | /** 15 | * This class is the GMP driver for encode and decode integers or 16 | * base 62 strings. 17 | */ 18 | class GmpEncoder implements BaseEncoder 19 | { 20 | /** 21 | * 22 | * @inheritdoc 23 | * 24 | * @return string $number The number decoded but as string 25 | */ 26 | public function encode($number) 27 | { 28 | if (!preg_match("/^(\d)+$/", (string) $number)) { 29 | throw new InvalidArgumentException('The value can only accept numbers'); 30 | } 31 | if ($number === 0) { 32 | return '0'; 33 | } 34 | 35 | $base62 = gmp_strval(gmp_init($number, 10), 62); 36 | 37 | return $base62; 38 | } 39 | 40 | /** 41 | * @inheritdoc 42 | * 43 | * @return string $number The number decoded but as string 44 | */ 45 | public function decode($data) 46 | { 47 | if (!is_string($data)) { 48 | throw new InvalidArgumentException('Must be a base 62 valid string'); 49 | } 50 | 51 | $number = gmp_strval(gmp_init($data, 62), 10); 52 | 53 | return $number; 54 | } 55 | } -------------------------------------------------------------------------------- /src/Facades/Base62.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2018 Siro Diaz 6 | * @license MIT 7 | * @see https://github.com/SiroDiaz/Base62 8 | */ 9 | namespace Base62\Facades; 10 | 11 | use Illuminate\Support\Facades\Facade; 12 | 13 | /** 14 | * Base62 facade class for Laravel. 15 | */ 16 | class Base62 extends Facade 17 | { 18 | protected static function getFacadeAccessor() 19 | { 20 | return 'Base62'; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Base62LaravelTest.php: -------------------------------------------------------------------------------- 1 | Base62::class, 20 | ]; 21 | } 22 | 23 | /** 24 | * Define environment setup. 25 | * 26 | * @param \Illuminate\Foundation\Application $app 27 | * 28 | * @return void 29 | */ 30 | protected function getEnvironmentSetUp($app) 31 | { 32 | // Setup default driver to use base62 encoder 33 | $app['config']->set('base62.driver', 'gmp'); 34 | } 35 | 36 | public function testSimpleEncode() 37 | { 38 | $this->assertSame(Base62::encode('0'), '0'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/Base62Test.php: -------------------------------------------------------------------------------- 1 | base62 = new Base62('basic'); 17 | } 18 | 19 | public function encodeDataProvider() 20 | { 21 | return [ 22 | ['0', 0], 23 | ['G7', 999], 24 | ['14', 66], 25 | ]; 26 | } 27 | 28 | public function decodeDataProvider() 29 | { 30 | return [ 31 | ['0', '0'], 32 | ['999', 'G7'], 33 | ['66', '14'], 34 | ]; 35 | } 36 | 37 | public function encodeBigIntegerDataProvider() 38 | { 39 | return [ 40 | ['47rhmv5JHMPe', '214748364787898954454'], 41 | ]; 42 | } 43 | 44 | /** 45 | * @dataProvider encodeDataProvider 46 | */ 47 | public function testEncode($expectedString, $decodedString) 48 | { 49 | $this->assertEquals($expectedString, $this->base62->encode($decodedString)); 50 | } 51 | 52 | public function testEncodeWithNegativeNumber() 53 | { 54 | $this->expectException(InvalidArgumentException::class); 55 | $this->base62->encode(-1); 56 | } 57 | 58 | public function testWithInvalidString() 59 | { 60 | $this->expectException(InvalidArgumentException::class); 61 | $this->base62->encode('12asd'); 62 | } 63 | 64 | /** 65 | * 66 | * @dataProvider encodeBigIntegerDataProvider 67 | */ 68 | public function testEncodeBigInteger($expectedString, $decodedString) 69 | { 70 | $this->expectException(InvalidArgumentException::class); 71 | $this->assertNotEquals($expectedString, $this->base62->encode($decodedString)); 72 | } 73 | 74 | /** 75 | * 76 | * @dataProvider decodeDataProvider 77 | */ 78 | public function testDecode($expectedString, $decodedString) 79 | { 80 | $this->assertEquals($expectedString, $this->base62->decode($decodedString)); 81 | } 82 | 83 | public function testDecodeWithNegativeNumber() 84 | { 85 | $base62 = new Base62('basic'); 86 | $this->expectException(InvalidArgumentException::class); 87 | $base62->decode(-1); 88 | } 89 | 90 | public function testDecodeWithPositiveNumber() 91 | { 92 | $this->expectException(InvalidArgumentException::class); 93 | $this->base62->decode(123); 94 | } 95 | 96 | public function testDecodeWithBoolean() 97 | { 98 | $base62 = new Base62('basic'); 99 | $this->expectException(InvalidArgumentException::class); 100 | $base62->decode(false); 101 | } 102 | 103 | /** 104 | * 105 | * @dataProvider encodeBigIntegerDataProvider 106 | */ 107 | public function testDecodeBigInteger($encodedString, $decodedString) { 108 | $this->assertNotEquals($decodedString, $this->base62->decode($encodedString)); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /tests/BcmathEncoderTest.php: -------------------------------------------------------------------------------- 1 | base62 = new Base62('bcmath'); 17 | } 18 | 19 | public function encodeDataProvider() 20 | { 21 | return [ 22 | ['0', 0], 23 | ['G7', 999], 24 | ['14', 66], 25 | ]; 26 | } 27 | 28 | public function decodeDataProvider() { 29 | return [ 30 | ['0', '0'], 31 | ['999', 'G7'], 32 | ['66', '14'], 33 | ]; 34 | } 35 | 36 | public function encodeBigIntegerDataProvider() 37 | { 38 | return [ 39 | ['2LKcb1', '2147483647'], 40 | ['47rhmv5JHMPe', '214748364787898954454'], 41 | ]; 42 | } 43 | 44 | /** 45 | * 46 | * @dataProvider encodeDataProvider 47 | */ 48 | public function testEncode($expectedString, $number) 49 | { 50 | $this->assertEquals($expectedString, $this->base62->encode($number)); 51 | } 52 | 53 | public function testEncodeWithNegativeNumber() 54 | { 55 | $this->expectException(InvalidArgumentException::class); 56 | $this->base62->encode(-1); 57 | } 58 | 59 | public function testDecodeWithBoolean() 60 | { 61 | $this->expectException(InvalidArgumentException::class); 62 | $this->base62->decode(false); 63 | } 64 | 65 | public function testWithInvalidString() 66 | { 67 | $this->expectException(InvalidArgumentException::class); 68 | $this->base62->encode('12asd'); 69 | } 70 | 71 | /** 72 | * 73 | * @dataProvider encodeBigIntegerDataProvider 74 | */ 75 | public function testEncodeBigInteger($expectedString, $number) { 76 | $this->assertEquals($expectedString, $this->base62->encode($number)); 77 | } 78 | 79 | /** 80 | * 81 | * @dataProvider encodeBigIntegerDataProvider 82 | */ 83 | public function testDecodeBigInteger($encodedString, $decodedString) { 84 | $this->assertEquals($decodedString, $this->base62->decode($encodedString)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tests/GmpEncoderTest.php: -------------------------------------------------------------------------------- 1 | base62 = new Base62('gmp'); 17 | } 18 | 19 | public function encodeDataProvider() 20 | { 21 | return [ 22 | ['0', 0], 23 | ['G7', 999], 24 | ['14', 66], 25 | ]; 26 | } 27 | 28 | public function decodeDataProvider() { 29 | return [ 30 | ['0', '0'], 31 | ['999', 'G7'], 32 | ['66', '14'], 33 | ]; 34 | } 35 | 36 | public function encodeBigIntegerDataProvider() 37 | { 38 | return [ 39 | ['2LKcb1', '2147483647'], 40 | ['47rhmv5JHMPe', '214748364787898954454'], 41 | ]; 42 | } 43 | 44 | public function testEncode() 45 | { 46 | $this->assertEquals('0', $this->base62->encode(0)); 47 | $this->assertEquals('G7', $this->base62->encode(999)); 48 | $this->assertEquals('14', $this->base62->encode(66)); 49 | } 50 | 51 | public function testEncodeWithNegativeNumber() 52 | { 53 | $this->expectException(InvalidArgumentException::class); 54 | $this->base62->encode(-1); 55 | } 56 | 57 | public function testWithInvalidString() 58 | { 59 | $this->expectException(InvalidArgumentException::class); 60 | $this->base62->encode('12asd'); 61 | } 62 | 63 | /** 64 | * @dataProvider encodeBigIntegerDataProvider 65 | */ 66 | public function testEncodeBigInteger($expectedString, $number) { 67 | $this->assertEquals($expectedString, $this->base62->encode($number)); 68 | } 69 | 70 | public function testDecode() 71 | { 72 | $this->assertEquals('999', $this->base62->decode('G7')); 73 | $this->assertEquals(66, $this->base62->decode('14')); 74 | } 75 | 76 | public function testDecodeWithNegativeNumber() 77 | { 78 | $this->expectException(InvalidArgumentException::class); 79 | $this->base62->decode(-1); 80 | } 81 | 82 | public function testDecodeWithPositiveNumber() 83 | { 84 | $this->expectException(InvalidArgumentException::class); 85 | $this->base62->decode(123); 86 | } 87 | 88 | public function testDecodeWithBoolean() 89 | { 90 | $this->expectException(InvalidArgumentException::class); 91 | $this->base62->decode(false); 92 | } 93 | 94 | /** 95 | * 96 | * @dataProvider encodeBigIntegerDataProvider 97 | */ 98 | public function testDecodeBigInteger($encodedString, $decodedString) { 99 | $this->assertEquals($decodedString, $this->base62->decode($encodedString)); 100 | } 101 | } 102 | --------------------------------------------------------------------------------