diff --git a/.gitattributes b/.gitattributes index c8f9f28..8d981ed 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,12 +1,12 @@ -/benchmark export-ignore -/static-analysis export-ignore -/tests export-ignore -.gitattributes export-ignore -.gitignore export-ignore -.php_cs export-ignore -.travis.yml export-ignore -composer.lock export-ignore -phpbench.json export-ignore -phpunit.xml.dist export-ignore -psalm.xml export-ignore -rector.php export-ignore +/benchmark export-ignore +/static-analysis export-ignore +/tests export-ignore +.gitattributes export-ignore +.gitignore export-ignore +.php-cs-fixer.php export-ignore +.travis.yml export-ignore +composer.lock export-ignore +phpbench.json export-ignore +phpunit.xml.dist export-ignore +psalm.xml export-ignore +rector.php export-ignore diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8160475..8dc3778 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -40,6 +40,10 @@ jobs: with: dependency-versions: "${{ matrix.dependencies }}" + - name: "Check code style" + if: ${{ matrix.dependencies == 'highest' && matrix.php == '8.1' }} + run: composer code-style:check + - name: "Run psalm" run: vendor/bin/psalm diff --git a/.gitignore b/.gitignore index 030990c..10d1207 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea .phpunit.result.cache +.php-cs-fixer.cache /phpunit.xml /vendor/ diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 0000000..b07cca6 --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,17 @@ +in(__DIR__) +; + +return (new \PhpCsFixer\Config())->setRiskyAllowed(true) + ->setRules([ + '@PHP81Migration' => true, + '@Symfony' => true, + 'yoda_style' => false, + + ]) + ->setFinder($finder) +; diff --git a/.php_cs b/.php_cs deleted file mode 100644 index 62bdf01..0000000 --- a/.php_cs +++ /dev/null @@ -1,15 +0,0 @@ -setRules([ - '@Symfony' => true, - '@PSR1' => true, - 'blank_line_before_return' => true, - ]) - ->setFinder( - PhpCsFixer\Finder::create() - ->in(__DIR__.DIRECTORY_SEPARATOR.'src') - ->in(__DIR__.DIRECTORY_SEPARATOR.'tests') - ) - ->setRiskyAllowed(true) - ->setUsingCache(true); diff --git a/benchmark/BaseShorteningBench.php b/benchmark/BaseShorteningBench.php index 22974f2..c4fa14e 100644 --- a/benchmark/BaseShorteningBench.php +++ b/benchmark/BaseShorteningBench.php @@ -5,7 +5,6 @@ namespace Benchmark\Keiko\Uuid\Shortener; use Keiko\Uuid\Shortener\Shortener; -use function array_map; abstract class BaseShorteningBench { @@ -145,7 +144,7 @@ public function benchShorteningOfHugeUuid(): void public function benchShorteningOfPromiscuousUuids(): void { - array_map($this->shortener->reduce(...), self::UUIDS_TO_BE_SHORTENED); + \array_map($this->shortener->reduce(...), self::UUIDS_TO_BE_SHORTENED); } public function benchExpandingOfTinyUuid(): void @@ -160,6 +159,6 @@ public function benchExpandingOfHugeUuid(): void public function benchExpandingOfPromiscuousUuids(): void { - array_map($this->shortener->expand(...), $this->shortenedPromoscuousUuids); + \array_map($this->shortener->expand(...), $this->shortenedPromoscuousUuids); } } diff --git a/benchmark/GMPShortenerBench.php b/benchmark/GMPShortenerBench.php index 1a8292e..0753cee 100644 --- a/benchmark/GMPShortenerBench.php +++ b/benchmark/GMPShortenerBench.php @@ -10,7 +10,7 @@ final class GMPShortenerBench extends BaseShorteningBench { - protected function newShortener() : Shortener + protected function newShortener(): Shortener { return new GMPShortener(Dictionary::createUnmistakable()); } diff --git a/benchmark/ShortenerBench.php b/benchmark/ShortenerBench.php index 31dfbbf..e70b369 100644 --- a/benchmark/ShortenerBench.php +++ b/benchmark/ShortenerBench.php @@ -10,7 +10,7 @@ final class ShortenerBench extends BaseShorteningBench { - protected function newShortener() : Shortener + protected function newShortener(): Shortener { return new Shortener(Dictionary::createUnmistakable(), new Converter()); } diff --git a/composer.json b/composer.json index 8f9455f..dc5031d 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ "phpunit/phpunit": "^8.5.26", "vimeo/psalm": "^4.3.1", "phpbench/phpbench": "^1.1.1", - "rector/rector": "^0.18.12" + "rector/rector": "^0.18.12", + "php-cs-fixer/shim": "^3.41" }, "suggest": { "ramsey/uuid": "A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID)", @@ -49,6 +50,8 @@ } }, "scripts": { + "code-style:check": "php-cs-fixer fix --dry-run --diff --ansi", + "code-style:fix": "php-cs-fixer fix --diff --ansi", "rector:check": "rector --dry-run --ansi", "rector:fix": "rector --ansi" } diff --git a/composer.lock b/composer.lock index 4159efd..19d6beb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ef4e44e777a7c7a30a3c907cde2e411a", + "content-hash": "9381d119d8758e179bf31e6bb8d8e6ec", "packages": [ { "name": "brick/math", @@ -1264,6 +1264,58 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-cs-fixer/shim", + "version": "v3.41.1", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/shim.git", + "reference": "01cea2dca727100537bd63e28e06e49a475b54e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/01cea2dca727100537bd63e28e06e49a475b54e9", + "reference": "01cea2dca727100537bd63e28e06e49a475b54e9", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "replace": { + "friendsofphp/php-cs-fixer": "self.version" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer", + "php-cs-fixer.phar" + ], + "type": "application", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "support": { + "issues": "https://github.com/PHP-CS-Fixer/shim/issues", + "source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.41.1" + }, + "time": "2023-12-10T19:59:57+00:00" + }, { "name": "phpbench/container", "version": "2.2.2", diff --git a/src/Dictionary.php b/src/Dictionary.php index 6e9745a..2cf006d 100644 --- a/src/Dictionary.php +++ b/src/Dictionary.php @@ -5,10 +5,6 @@ namespace Keiko\Uuid\Shortener; use Keiko\Uuid\Shortener\Exception\DictionaryException; -use function array_flip; -use function count_chars; -use function str_split; -use function strlen; /** @psalm-immutable */ final class Dictionary @@ -34,25 +30,23 @@ final class Dictionary */ public function __construct(string $charsSet) { - $length = strlen($charsSet); + $length = \strlen($charsSet); if ($length <= 16) { throw DictionaryException::charsSetTooShort(); } - $uniqueChars = count_chars($charsSet, 3); - if (strlen($uniqueChars) !== $length) { + $uniqueChars = \count_chars($charsSet, 3); + if (\strlen($uniqueChars) !== $length) { throw DictionaryException::nonUniqueChars(); } $this->charsSet = $charsSet; $this->length = $length; - $this->charIndexes = array_flip(str_split($charsSet)); + $this->charIndexes = \array_flip(\str_split($charsSet)); } /** - * @return Dictionary - * * @psalm-pure */ public static function createUnmistakable(): Dictionary @@ -61,8 +55,6 @@ public static function createUnmistakable(): Dictionary } /** - * @return Dictionary - * * @psalm-pure */ public static function createAlphanumeric(): Dictionary @@ -70,9 +62,6 @@ public static function createAlphanumeric(): Dictionary return new self(self::DICTIONARY_ALPHANUMERIC); } - /** - * @return int - */ public function getLength(): int { return $this->length; @@ -80,8 +69,6 @@ public function getLength(): int /** * @throws DictionaryException - * - * @return string */ public function getCharAt(int $index): string { @@ -94,8 +81,6 @@ public function getCharAt(int $index): string /** * @throws DictionaryException - * - * @return int */ public function getCharIndex(string $char): int { diff --git a/src/GMPShortener.php b/src/GMPShortener.php index d11bd0d..46fcafd 100644 --- a/src/GMPShortener.php +++ b/src/GMPShortener.php @@ -5,24 +5,13 @@ namespace Keiko\Uuid\Shortener; use Keiko\Uuid\Shortener\Exception\DictionaryException; -use function array_flip; -use function gmp_init; -use function gmp_strval; -use function preg_match; -use function preg_quote; -use function str_pad; -use function str_replace; -use function strrev; -use function strtr; -use function substr; -use const STR_PAD_LEFT; /** @psalm-immutable */ final class GMPShortener extends Shortener { /** * @var string[] a map of character replacements to be used when translating a number that is - * in base(length(Dictionary)) (keys) to the dictionary characters (values). + * in base(length(Dictionary)) (keys) to the dictionary characters (values) * * @psalm-var non-empty-array */ @@ -35,48 +24,48 @@ public function __construct(private readonly Dictionary $dictionary) $replacements = []; foreach (range(0, $dictionary->length - 1) as $characterIndex) { - $replacements[gmp_strval(gmp_init((string) $characterIndex, 10), $dictionary->length)] = $dictionary->charsSet[$characterIndex]; + $replacements[\gmp_strval(\gmp_init((string) $characterIndex, 10), $dictionary->length)] = $dictionary->charsSet[$characterIndex]; } $this->baseReplacements = $replacements; - $this->allowedCharactersMatcher = '/^['. preg_quote($dictionary->charsSet, '/').']+$/'; + $this->allowedCharactersMatcher = '/^['.\preg_quote($dictionary->charsSet, '/').']+$/'; } public function reduce(string $uuid): string { - return strrev(strtr( - gmp_strval(gmp_init(str_replace('-', '', $uuid), 16), $this->dictionary->length), + return \strrev(\strtr( + \gmp_strval(\gmp_init(\str_replace('-', '', $uuid), 16), $this->dictionary->length), $this->baseReplacements )); } public function expand(string $shortUuid): string { - if (1 !== preg_match($this->allowedCharactersMatcher, $shortUuid)) { + if (1 !== \preg_match($this->allowedCharactersMatcher, $shortUuid)) { throw DictionaryException::indexOutOfBounds(); } - $base16Uuid = str_pad( - gmp_strval( - gmp_init( - strtr(strrev($shortUuid), array_flip($this->baseReplacements)), + $base16Uuid = \str_pad( + \gmp_strval( + \gmp_init( + \strtr(\strrev($shortUuid), \array_flip($this->baseReplacements)), $this->dictionary->length ), 16 ), 32, '0', - STR_PAD_LEFT + \STR_PAD_LEFT ); - return substr($base16Uuid,0, 8) - . '-' - . substr($base16Uuid, 8, 4) - . '-' - . substr($base16Uuid, 12, 4) - . '-' - . substr($base16Uuid, 16, 4) - . '-' - . substr($base16Uuid, 20, 12); + return \substr($base16Uuid, 0, 8) + .'-' + .\substr($base16Uuid, 8, 4) + .'-' + .\substr($base16Uuid, 12, 4) + .'-' + .\substr($base16Uuid, 16, 4) + .'-' + .\substr($base16Uuid, 20, 12); } } diff --git a/src/Shortener.php b/src/Shortener.php index dc2aa5d..e238960 100644 --- a/src/Shortener.php +++ b/src/Shortener.php @@ -9,28 +9,19 @@ use Keiko\Uuid\Shortener\Exception\DictionaryException; use Keiko\Uuid\Shortener\Number\BigInt\Converter; use Keiko\Uuid\Shortener\Number\BigInt\ConverterInterface; -use function extension_loaded; -use function str_pad; -use function str_split; -use function strrev; -use function substr; /** @psalm-immutable */ class Shortener { - /** - * @param Dictionary $dictionary - * @param ConverterInterface $converter - */ public function __construct( private readonly Dictionary $dictionary, private readonly ConverterInterface $converter, ) { } - public static function make(Dictionary $dictionary) : self + public static function make(Dictionary $dictionary): self { - if (extension_loaded('gmp')) { + if (\extension_loaded('gmp')) { return new GMPShortener($dictionary); } @@ -57,26 +48,26 @@ public function reduce(string $uuid): string public function expand(string $shortUuid): string { $number = BigInteger::zero(); - foreach (str_split(strrev($shortUuid)) as $char) { + foreach (\str_split(\strrev($shortUuid)) as $char) { $number = $number ->multipliedBy($this->dictionary->length) ->plus( - $this->dictionary->charIndexes[$char] ?? (static function () : string { + $this->dictionary->charIndexes[$char] ?? (static function (): string { throw DictionaryException::indexOutOfBounds(); })() ); } - $base16Uuid = str_pad($this->converter->toHex($number), 32, '0', STR_PAD_LEFT); + $base16Uuid = \str_pad($this->converter->toHex($number), 32, '0', STR_PAD_LEFT); - return substr($base16Uuid,0, 8) - . '-' - . substr($base16Uuid, 8, 4) - . '-' - . substr($base16Uuid, 12, 4) - . '-' - . substr($base16Uuid, 16, 4) - . '-' - . substr($base16Uuid, 20, 12); + return \substr($base16Uuid, 0, 8) + .'-' + .\substr($base16Uuid, 8, 4) + .'-' + .\substr($base16Uuid, 12, 4) + .'-' + .\substr($base16Uuid, 16, 4) + .'-' + .\substr($base16Uuid, 20, 12); } } diff --git a/tests/DictionaryTest.php b/tests/DictionaryTest.php index b63f3f4..6a245d5 100644 --- a/tests/DictionaryTest.php +++ b/tests/DictionaryTest.php @@ -26,14 +26,14 @@ public function testInitialDictionaryState(): void self::assertSame(57, $this->dictionary->length); self::assertSame( [ - 2 => 0, - 3 => 1, - 4 => 2, - 5 => 3, - 6 => 4, - 7 => 5, - 8 => 6, - 9 => 7, + 2 => 0, + 3 => 1, + 4 => 2, + 5 => 3, + 6 => 4, + 7 => 5, + 8 => 6, + 9 => 7, 'A' => 8, 'B' => 9, 'C' => 10, @@ -133,6 +133,7 @@ public function testThrowExceptonWhenGettingNonExistentCharsIndex(): void $this->dictionary->getCharIndex('Ć'); } + public function testCreateUnmistakableDictionary(): void { $dictionary = Dictionary::createUnmistakable(); diff --git a/tests/GMPShortenerTest.php b/tests/GMPShortenerTest.php index a85d91f..2a81f17 100644 --- a/tests/GMPShortenerTest.php +++ b/tests/GMPShortenerTest.php @@ -10,7 +10,7 @@ final class GMPShortenerTest extends ShortenerTestCase { - protected function shortener(Dictionary $dictionary = null) : Shortener + protected function shortener(Dictionary $dictionary = null): Shortener { return new GMPShortener($dictionary ?? Dictionary::createUnmistakable()); } diff --git a/tests/ShortenerTest.php b/tests/ShortenerTest.php index b5a4de3..3d7e615 100644 --- a/tests/ShortenerTest.php +++ b/tests/ShortenerTest.php @@ -10,7 +10,7 @@ final class ShortenerTest extends ShortenerTestCase { - protected function shortener(Dictionary $dictionary = null) : Shortener + protected function shortener(Dictionary $dictionary = null): Shortener { return new Shortener( $dictionary ?? Dictionary::createUnmistakable(), diff --git a/tests/ShortenerTestCase.php b/tests/ShortenerTestCase.php index 7114420..1d359b7 100644 --- a/tests/ShortenerTestCase.php +++ b/tests/ShortenerTestCase.php @@ -6,7 +6,6 @@ use Keiko\Uuid\Shortener\Dictionary; use Keiko\Uuid\Shortener\Exception\DictionaryException; -use Keiko\Uuid\Shortener\Number\BigInt\Converter; use Keiko\Uuid\Shortener\Shortener; use PHPUnit\Framework\TestCase; @@ -74,12 +73,12 @@ public function uuidShortenedUnmistakable(): array ['806d0969-95b3-433b-976f-774611fdacbb', 'mavTAjNm4NVztDwh4gdSrQ'], ['0c5873e8-7fea-4570-9487-ffe96ec30257', 'LpGtrrQFCbneY2GtQiXDD4'], ['ffffffff-ffff-ffff-ffff-ffffffffffff', '5B8cwPMGnU6qLbRvo7qEZo'], - 'One leading zero' => ['07fe2146-0a94-4a4a-9956-4cfd0d3560d9', 'rcPMmyWuaewoF8EM3JK5S3'], - '2 Leading zeroes' => ['00fe2146-0a94-4a4a-9956-4cfd0d3560d9', 'qgXznd8uPVbCJg5tB5r5C'], + 'One leading zero' => ['07fe2146-0a94-4a4a-9956-4cfd0d3560d9', 'rcPMmyWuaewoF8EM3JK5S3'], + '2 Leading zeroes' => ['00fe2146-0a94-4a4a-9956-4cfd0d3560d9', 'qgXznd8uPVbCJg5tB5r5C'], 'Smallest UUID, max leading zeroes' => ['00000000-0000-0000-0000-000000000001', '3'], - 'Small UUID, many leading zeroes' => ['00000000-0000-0000-0000-0000000000aa', 'z4'], - 'Large UUID, many trailing zeroes' => ['aa000000-0000-0000-0000-000000000000', 'ABitJoXBZDBeRvbiWuB5GY'], - 'Random UUID with trailing zeroes' => ['a7fe2146-0a94-4a4a-9956-4cfd0d3560d0', 'Fbab7rU5aCkhaybY3jphtX'], + 'Small UUID, many leading zeroes' => ['00000000-0000-0000-0000-0000000000aa', 'z4'], + 'Large UUID, many trailing zeroes' => ['aa000000-0000-0000-0000-000000000000', 'ABitJoXBZDBeRvbiWuB5GY'], + 'Random UUID with trailing zeroes' => ['a7fe2146-0a94-4a4a-9956-4cfd0d3560d0', 'Fbab7rU5aCkhaybY3jphtX'], ]; } }