diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 127b445..df7eea1 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,11 +6,11 @@ on: jobs: phpstan: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 name: PHPStan steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: PHPStan uses: docker://oskarstark/phpstan-ga env: @@ -18,30 +18,22 @@ jobs: with: args: analyse cs-fixer: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 name: PHP-CS-Fixer steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Fix CS uses: docker://oskarstark/php-cs-fixer-ga tests: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 strategy: max-parallel: 1 matrix: include: - description: 'lowest' - php: '7.1' + php: '8.1' composer_option: '--prefer-lowest' - - description: '7.2' - php: '7.2' - - description: '7.3' - php: '7.3' - - description: '7.4' - php: '7.4' - - description: '8.0' - php: '8.0' - description: '8.1' php: '8.1' - description: '8.2' @@ -51,10 +43,10 @@ jobs: name: PHP ${{ matrix.php }} tests steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache - uses: actions/cache@v3 - with: + uses: actions/cache@v4 + with: path: ~/.composer/cache/files key: ${{ matrix.php }}-${{ matrix.composer_option }} - name: Setup PHP diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 44d3103..e4c5e4c 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -10,8 +10,9 @@ ->setRules([ '@Symfony' => true, '@Symfony:risky' => true, - '@PHP71Migration:risky' => true, - '@PHPUnit75Migration:risky' => true, + '@PHP80Migration:risky' => true, + '@PHP81Migration' => true, + '@PHPUnit100Migration:risky' => true, 'declare_strict_types' => false, 'native_function_invocation' => ['include' => ['@all']], 'final_class' => true, diff --git a/README.md b/README.md index d0b609b..530cb2c 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ $id = Shortid::generate(); For more control, you can customize the alphabet and length using the Factory class. -Default alphabet uses all letters (lowercase and uppercase), all numbers, underscore, and hypen. +The default alphabet uses all letters (lowercase and uppercase), all numbers, underscore, and hyphen. ``` php use PUGX\Shortid\Factory; @@ -52,14 +52,14 @@ $factory = new Factory(); // alphabet string must be 64 characters long $factory->setAlphabet('é123456789àbcdefghìjklmnòpqrstùvwxyzABCDEFGHIJKLMNOPQRSTUVWX.!@|'); // length must be between 2 and 20 (default is 7) -// of course, a lower length is increasing clashing probability +// of course, a lower length increases the clashing probability $factory->setLength(9); Shortid::setFactory($factory); $id = Shortid::generate(); ``` -As alternative, you can customize single generations: +As an alternative, you can customize single generations: ``` php use PUGX\Shortid\Shortid; @@ -104,7 +104,7 @@ $anotherFixedId = new Shortid('fooBarZ'); ## Doctrine -If you want to use ShortId with Doctrine ORM, take a look to [ShortId Doctrine type][2]. +If you want to use ShortId with Doctrine ORM, take a look at [ShortId Doctrine type][2]. ## Doctrine and Symfony @@ -121,7 +121,7 @@ native extension is not available. If, instead, your environment is offering that extension, you can avoid installing that polyfill by configuring a [replace][5] entry in your `composer.json`. -The same applies to the [randomLib][6] library: if you are using PHP 8.3 or higher, +The same applies to the [randomLib][6] library: if you are using PHP 8.3 or higher, you can replace it, since this library uses the native `Random` class instead. ## Contributing diff --git a/composer.json b/composer.json index 53d408e..4328aa4 100644 --- a/composer.json +++ b/composer.json @@ -20,21 +20,20 @@ } ], "require": { - "php": "^7.1 || ^8.0", - "ext-json": "*", + "php": "^8.1", "paragonie/random-lib": "^2.0", "symfony/polyfill-mbstring": "^1.19" }, "require-dev": { "dg/bypass-finals": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" + "phpunit/phpunit": "^9.6" }, "config": { "bin-dir": "bin" }, "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.x-dev" } }, "autoload": { diff --git a/src/Factory.php b/src/Factory.php index fef6151..cf6df50 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -8,33 +8,18 @@ final class Factory { - /** - * @var int - */ - private $length = 7; - - /** - * @var string - */ - private $alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-'; - - /** - * @var bool - */ - private $readable = false; - - /** - * @var RandomLibFactory - */ - private static $factory; + private int $length = 7; + private string $alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-'; + private bool $readable = false; + private static ?RandomLibFactory $factory = null; /** * @throws InvalidShortidException */ - public function generate(int $length = null, string $alphabet = null, bool $readable = null): Shortid + public function generate(?int $length = null, ?string $alphabet = null, ?bool $readable = null): Shortid { - $length = $length ?? $this->length; - $readable = $readable ?? $this->readable; + $length ??= $this->length; + $readable ??= $this->readable; if (null === $alphabet && $readable) { $alphabet = \str_replace(\str_split(Generator::AMBIGUOUS_CHARS), '', $this->alphabet); $alphabet .= \str_repeat('_', \strlen(Generator::AMBIGUOUS_CHARS) / 2); @@ -80,7 +65,7 @@ public static function getFactory(): RandomLibFactory return self::$factory; } - public function checkLength(int $length = null, bool $strict = false): void + public function checkLength(?int $length = null, bool $strict = false): void { if (null === $length && !$strict) { return; diff --git a/src/Shortid.php b/src/Shortid.php index 10d1415..33c7c6d 100644 --- a/src/Shortid.php +++ b/src/Shortid.php @@ -2,28 +2,18 @@ namespace PUGX\Shortid; -final class Shortid implements \JsonSerializable, \Serializable +final class Shortid implements \JsonSerializable, \Serializable, \Stringable { - /** - * @var string - */ - private $id; - - /** - * @var Factory|null - */ - private static $factory; + private static ?Factory $factory = null; /** * @throws InvalidShortidException */ - public function __construct(string $id, int $length = null, string $alphabet = null) + public function __construct(private string $id, ?int $length = null, ?string $alphabet = null) { if (!self::isValid($id, $length, $alphabet)) { throw new InvalidShortidException(\sprintf('Invalid shortid %s (length %d alphabet %s', $id, $length, $alphabet)); } - - $this->id = $id; } public function __toString(): string @@ -34,7 +24,7 @@ public function __toString(): string /** * @throws InvalidShortidException */ - public static function generate(int $length = null, string $alphabet = null, bool $readable = false): self + public static function generate(?int $length = null, ?string $alphabet = null, bool $readable = false): self { if (null === $length) { self::getFactory()->checkLength($length); @@ -53,14 +43,14 @@ public static function getFactory(): Factory return self::$factory; } - public static function setFactory(Factory $factory = null): void + public static function setFactory(?Factory $factory = null): void { self::$factory = $factory; } - public static function isValid(string $value, int $length = null, string $alphabet = null): bool + public static function isValid(string $value, ?int $length = null, ?string $alphabet = null): bool { - $length = $length ?? self::getFactory()->getLength(); + $length ??= self::getFactory()->getLength(); $alphabet = \preg_quote($alphabet ?: self::getFactory()->getAlphabet(), '/'); $matches = []; $ok = \preg_match('/^(['.$alphabet.']{'.$length.'})$/', $value, $matches); @@ -78,12 +68,9 @@ public function serialize(): string return $this->id; } - /** - * @param string $serialized - */ - public function unserialize($serialized): void + public function unserialize(string $data): void { - $this->id = $serialized; + $this->id = $data; } /** diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php index 5e584ed..aa57aa9 100644 --- a/tests/FactoryTest.php +++ b/tests/FactoryTest.php @@ -8,10 +8,7 @@ final class FactoryTest extends TestCase { - /** - * @var Factory - */ - private $factory; + private Factory $factory; protected function setUp(): void { @@ -25,14 +22,14 @@ public function testGenerate(): void if (\method_exists($this, 'assertMatchesRegularExpression')) { self::assertMatchesRegularExpression('/^[a-z0-9\_\-]{7}$/i', $generated->__toString()); } else { - self::assertRegExp('/^[a-z0-9\_\-]{7}$/i', $generated->__toString()); + self::assertMatchesRegularExpression('/^[a-z0-9\_\-]{7}$/i', $generated->__toString()); } } /** * @return string[][] */ - public function alphabetsProvider(): array + public static function alphabetsProvider(): array { $alphabets = []; $chars = []; @@ -77,7 +74,7 @@ public function testSetWrongAlphabet(string $alphabet): void /** * @return array{test: array{'test'}, rand: array{string}} */ - public function wrongAlphabetsProvider(): array + public static function wrongAlphabetsProvider(): array { return [ 'test' => ['test'], diff --git a/tests/ShortidTest.php b/tests/ShortidTest.php index 35fd53f..66f06c4 100644 --- a/tests/ShortidTest.php +++ b/tests/ShortidTest.php @@ -21,7 +21,7 @@ public function testGenerate(): void if (\method_exists($this, 'assertMatchesRegularExpression')) { self::assertMatchesRegularExpression('/^[a-z0-9\_\-]{7}$/i', $generated->__toString()); } else { - self::assertRegExp('/^[a-z0-9\_\-]{7}$/i', $generated->__toString()); + self::assertMatchesRegularExpression('/^[a-z0-9\_\-]{7}$/i', $generated->__toString()); } } @@ -32,7 +32,7 @@ public function testGenerateWithReadable(): void if (\method_exists($this, 'assertMatchesRegularExpression')) { self::assertMatchesRegularExpression('/^[a-z0-9\_\-]{7}$/i', $generated->__toString()); } else { - self::assertRegExp('/^[a-z0-9\_\-]{7}$/i', $generated->__toString()); + self::assertMatchesRegularExpression('/^[a-z0-9\_\-]{7}$/i', $generated->__toString()); } } @@ -43,7 +43,7 @@ public function testGenerateWithLength(): void if (\method_exists($this, 'assertMatchesRegularExpression')) { self::assertMatchesRegularExpression('/^[a-z0-9\_\-]{8}$/i', $generated->__toString()); } else { - self::assertRegExp('/^[a-z0-9\_\-]{8}$/i', $generated->__toString()); + self::assertMatchesRegularExpression('/^[a-z0-9\_\-]{8}$/i', $generated->__toString()); } }