diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 97b5955..dc7615a 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -131,10 +131,9 @@ jobs: fail-fast: false matrix: php: - - "7.4" - - "8.0" - "8.1" - "8.2" + - "8.3" composer-deps: ["lowest", "highest"] steps: diff --git a/composer.json b/composer.json index b763343..94ba9a2 100644 --- a/composer.json +++ b/composer.json @@ -18,18 +18,18 @@ } ], "require": { - "php": "^7.4 || ^8.0", - "doctrine/dbal": "^2.8 || ^3.0", + "php": "^8.1", + "doctrine/dbal": "^2.8 || ^3.0 || ^4.0", "ramsey/uuid": "^3.9.7 || ^4.0" }, "require-dev": { "captainhook/plugin-composer": "^5.3", - "doctrine/orm": "^2.5", + "doctrine/orm": "^2.5 || ^3.0", "ergebnis/composer-normalize": "^2.28.3", "mockery/mockery": "^1.5", "php-parallel-lint/php-console-highlighter": "^1.0", "php-parallel-lint/php-parallel-lint": "^1.3", - "phpcsstandards/phpcsutils": "^1.0.0-alpha4", + "phpcsstandards/phpcsutils": "^1.0", "phpstan/extension-installer": "^1.2", "phpstan/phpstan": "^1.9", "phpstan/phpstan-mockery": "^1.1", @@ -55,11 +55,11 @@ }, "config": { "allow-plugins": { + "captainhook/plugin-composer": true, "composer/package-versions-deprecated": true, "dealerdirect/phpcodesniffer-composer-installer": true, "ergebnis/composer-normalize": true, - "phpstan/extension-installer": true, - "captainhook/plugin-composer": true + "phpstan/extension-installer": true }, "sort-packages": true }, diff --git a/phpcs.xml.dist b/phpcs.xml.dist index f76cd66..4d58ebf 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -10,4 +10,8 @@ + + src/GetBindingTypeImplementation.php + + diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 007d517..1eb68ba 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -5,3 +5,13 @@ parameters: paths: - ./src - ./tests + ignoreErrors: + # That class no longer holds methods in DBAL 4, but needs to be called with DBAL 3 + - message: '#Call to an undefined static method Doctrine\\DBAL\\Types\\ConversionException::.*#' + reportUnmatched: false + + # Necessary type hint for testing methods that no longer exist in the parent class with DBAL 4 + - message: '#Method.*getBindingType.*should return .*#' + reportUnmatched: false + - message: '#Return type.*getBindingType.*should be compatible .*#' + reportUnmatched: false diff --git a/psalm.xml b/psalm.xml index b6e7fdd..ae94f8a 100644 --- a/psalm.xml +++ b/psalm.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" errorLevel="1" - findUnusedPsalmSuppress="true" + findUnusedPsalmSuppress="false" cacheDirectory="./build/cache/psalm" errorBaseline="./psalm-baseline.xml"> @@ -20,4 +20,13 @@ + + + + + + + + + diff --git a/src/GetBindingTypeImplementation.php b/src/GetBindingTypeImplementation.php new file mode 100644 index 0000000..76a4107 --- /dev/null +++ b/src/GetBindingTypeImplementation.php @@ -0,0 +1,48 @@ + + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Doctrine; + +use Doctrine\DBAL\ParameterType; + +use function enum_exists; +use function function_exists; + +if (function_exists('enum_exists') && enum_exists(ParameterType::class)) { + /** + * @internal + */ + trait GetBindingTypeImplementation + { + /** + * @psalm-suppress InvalidReturnType + * @psalm-suppress ImplementedReturnTypeMismatch + */ + public function getBindingType(): ParameterType + { + return ParameterType::BINARY; + } + } +} else { + /** + * @internal + */ + trait GetBindingTypeImplementation + { + public function getBindingType(): int + { + return ParameterType::BINARY; + } + } +} diff --git a/src/UuidBinaryOrderedTimeType.php b/src/UuidBinaryOrderedTimeType.php index e6e54ce..d377924 100644 --- a/src/UuidBinaryOrderedTimeType.php +++ b/src/UuidBinaryOrderedTimeType.php @@ -14,9 +14,10 @@ namespace Ramsey\Uuid\Doctrine; -use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\ConversionException; +use Doctrine\DBAL\Types\Exception\InvalidFormat; +use Doctrine\DBAL\Types\Exception\ValueNotConvertible; use Doctrine\DBAL\Types\Type; use Ramsey\Uuid\Codec\OrderedTimeCodec; use Ramsey\Uuid\Exception\UnsupportedOperationException; @@ -25,6 +26,7 @@ use Throwable; use function bin2hex; +use function class_exists; use function is_object; use function is_string; use function method_exists; @@ -37,6 +39,8 @@ */ class UuidBinaryOrderedTimeType extends Type { + use GetBindingTypeImplementation; + public const NAME = 'uuid_binary_ordered_time'; public const ASSERT_FORMAT = 'UuidV1'; @@ -52,7 +56,7 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform): st { return $platform->getBinaryTypeDeclarationSQL( [ - 'length' => '16', + 'length' => 16, 'fixed' => true, ], ); @@ -76,7 +80,9 @@ public function convertToPHPValue($value, AbstractPlatform $platform): ?UuidInte try { return $this->decode($value); } catch (Throwable $e) { - throw ConversionException::conversionFailed($value, self::NAME); + throw class_exists(ValueNotConvertible::class) ? + ValueNotConvertible::new($value, self::NAME) : + ConversionException::conversionFailed($value, self::NAME); } } @@ -105,24 +111,31 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?str // Ignore the exception and pass through. } - throw ConversionException::conversionFailed($value, self::NAME); + throw class_exists(ValueNotConvertible::class) ? + ValueNotConvertible::new($value, self::NAME) : + ConversionException::conversionFailed($value, self::NAME); } + /** + * {@inheritDoc} + * + * @deprecated this method is deprecated and will be removed in Uuid-Doctrine 3.0 + */ public function getName(): string { return self::NAME; } + /** + * {@inheritDoc} + * + * @deprecated this method is deprecated and will be removed in Uuid-Doctrine 3.0 + */ public function requiresSQLCommentHint(AbstractPlatform $platform): bool { return true; } - public function getBindingType(): int - { - return ParameterType::BINARY; - } - /** * Creates/returns a UuidFactory instance that uses a specific codec * that creates a binary that can be time-ordered @@ -158,11 +171,18 @@ private function assertUuidV1(UuidInterface $value): void { /** @psalm-suppress DeprecatedMethod */ if ($value->getVersion() !== 1) { - throw ConversionException::conversionFailedFormat( - $value->toString(), - self::NAME, - self::ASSERT_FORMAT, - ); + throw class_exists(InvalidFormat::class) ? + InvalidFormat::new( + $value->toString(), + self::NAME, + self::ASSERT_FORMAT, + ) : + /** @psalm-suppress DeprecatedMethod */ + ConversionException::conversionFailedFormat( + $value->toString(), + self::NAME, + self::ASSERT_FORMAT, + ); } } @@ -184,11 +204,17 @@ private function decode(string $bytes): UuidInterface try { $decoded = $this->getCodec()->decodeBytes($bytes); } catch (UnsupportedOperationException $e) { - throw ConversionException::conversionFailedFormat( - bin2hex($bytes), - self::NAME, - self::ASSERT_FORMAT, - ); + throw class_exists(InvalidFormat::class) ? + InvalidFormat::new( + bin2hex($bytes), + self::NAME, + self::ASSERT_FORMAT, + ) : + ConversionException::conversionFailedFormat( + bin2hex($bytes), + self::NAME, + self::ASSERT_FORMAT, + ); } $this->assertUuidV1($decoded); diff --git a/src/UuidBinaryType.php b/src/UuidBinaryType.php index 3f66f32..adf9a4b 100644 --- a/src/UuidBinaryType.php +++ b/src/UuidBinaryType.php @@ -14,14 +14,15 @@ namespace Ramsey\Uuid\Doctrine; -use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\ConversionException; +use Doctrine\DBAL\Types\Exception\ValueNotConvertible; use Doctrine\DBAL\Types\Type; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; use Throwable; +use function class_exists; use function is_object; use function is_string; use function method_exists; @@ -34,6 +35,8 @@ */ class UuidBinaryType extends Type { + use GetBindingTypeImplementation; + public const NAME = 'uuid_binary'; /** @@ -43,7 +46,7 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform): st { return $platform->getBinaryTypeDeclarationSQL( [ - 'length' => '16', + 'length' => 16, 'fixed' => true, ], ); @@ -67,7 +70,9 @@ public function convertToPHPValue($value, AbstractPlatform $platform): ?UuidInte try { $uuid = Uuid::fromBytes($value); } catch (Throwable $e) { - throw ConversionException::conversionFailed($value, self::NAME); + throw class_exists(ValueNotConvertible::class) + ? ValueNotConvertible::new($value, self::NAME) + : ConversionException::conversionFailed($value, self::NAME); } return $uuid; @@ -96,21 +101,28 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?str // Ignore the exception and pass through. } - throw ConversionException::conversionFailed($value, self::NAME); + throw class_exists(ValueNotConvertible::class) + ? ValueNotConvertible::new($value, self::NAME) + : ConversionException::conversionFailed($value, self::NAME); } + /** + * {@inheritDoc} + * + * @deprecated this method is deprecated and will be removed in Uuid-Doctrine 3.0 + */ public function getName(): string { return self::NAME; } + /** + * {@inheritDoc} + * + * @deprecated this method is deprecated and will be removed in Uuid-Doctrine 3.0 + */ public function requiresSQLCommentHint(AbstractPlatform $platform): bool { return true; } - - public function getBindingType(): int - { - return ParameterType::BINARY; - } } diff --git a/src/UuidType.php b/src/UuidType.php index 3ae95d2..efeba1b 100644 --- a/src/UuidType.php +++ b/src/UuidType.php @@ -16,11 +16,13 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\ConversionException; +use Doctrine\DBAL\Types\Exception\ValueNotConvertible; use Doctrine\DBAL\Types\GuidType; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; use Throwable; +use function class_exists; use function is_object; use function is_string; use function method_exists; @@ -53,7 +55,9 @@ public function convertToPHPValue($value, AbstractPlatform $platform): ?UuidInte try { $uuid = Uuid::fromString($value); } catch (Throwable $e) { - throw ConversionException::conversionFailed($value, self::NAME); + throw class_exists(ValueNotConvertible::class) + ? ValueNotConvertible::new($value, self::NAME) + : ConversionException::conversionFailed($value, self::NAME); } return $uuid; @@ -81,22 +85,32 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?str return (string) $value; } - throw ConversionException::conversionFailed($value, self::NAME); + throw class_exists(ValueNotConvertible::class) + ? ValueNotConvertible::new($value, self::NAME) + : ConversionException::conversionFailed($value, self::NAME); } + /** + * {@inheritDoc} + * + * @deprecated this method is deprecated and will be removed in Uuid-Doctrine 3.0 + */ public function getName(): string { return self::NAME; } + /** + * {@inheritDoc} + * + * @deprecated this method is deprecated and will be removed in Uuid-Doctrine 3.0 + */ public function requiresSQLCommentHint(AbstractPlatform $platform): bool { return true; } - /** - * @return string[] - */ + /** {@inheritDoc} */ public function getMappedDatabaseTypes(AbstractPlatform $platform): array { return [self::NAME]; diff --git a/src/UuidV7Generator.php b/src/UuidV7Generator.php index 210edfb..76ae8f9 100644 --- a/src/UuidV7Generator.php +++ b/src/UuidV7Generator.php @@ -45,6 +45,8 @@ public function __construct() * @param object | null $entity* * * @throws Exception + * + * @psalm-suppress MissingParamType method deprecated */ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint public function generate(EntityManagerInterface $em, $entity): UuidInterface diff --git a/tests/UuidBinaryOrderedTimeTypeTest.php b/tests/UuidBinaryOrderedTimeTypeTest.php index 78b3e7e..ed11c73 100644 --- a/tests/UuidBinaryOrderedTimeTypeTest.php +++ b/tests/UuidBinaryOrderedTimeTypeTest.php @@ -4,6 +4,7 @@ namespace Ramsey\Uuid\Doctrine; +use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\Type; @@ -46,7 +47,7 @@ private function getType(): Type public function testGetName(): void { - $this->assertSame('uuid_binary_ordered_time', $this->getType()->getName()); + $this->assertSame('uuid_binary_ordered_time', $this->getType()::lookupName($this->getType())); } public function testUuidConvertsToDatabaseValue(): void @@ -135,13 +136,8 @@ public function testGetGuidTypeDeclarationSQL(): void ); } - public function testRequiresSQLCommentHint(): void - { - $this->assertTrue($this->getType()->requiresSQLCommentHint($this->getPlatform())); - } - public function testItReturnsAppropriateBindingType(): void { - $this->assertEquals(16, $this->getType()->getBindingType()); + $this->assertEquals(ParameterType::BINARY, $this->getType()->getBindingType()); } } diff --git a/tests/UuidBinaryTypeTest.php b/tests/UuidBinaryTypeTest.php index 2439722..4c8dc20 100644 --- a/tests/UuidBinaryTypeTest.php +++ b/tests/UuidBinaryTypeTest.php @@ -4,6 +4,7 @@ namespace Ramsey\Uuid\Doctrine; +use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\Type; @@ -122,7 +123,7 @@ public function testReturnValueIfUuid7ForPHPValue(): void public function testGetName(): void { - $this->assertSame('uuid_binary', $this->getType()->getName()); + $this->assertSame('uuid_binary', $this->getType()::lookupName($this->getType())); } public function testGetGuidTypeDeclarationSQL(): void @@ -133,13 +134,8 @@ public function testGetGuidTypeDeclarationSQL(): void ); } - public function testRequiresSQLCommentHint(): void - { - $this->assertTrue($this->getType()->requiresSQLCommentHint($this->getPlatform())); - } - public function testItReturnsAppropriateBindingType(): void { - $this->assertEquals(16, $this->getType()->getBindingType()); + $this->assertEquals(ParameterType::BINARY, $this->getType()->getBindingType()); } } diff --git a/tests/UuidTypeTest.php b/tests/UuidTypeTest.php index d66160d..3f4548f 100644 --- a/tests/UuidTypeTest.php +++ b/tests/UuidTypeTest.php @@ -127,7 +127,7 @@ public function testReturnValueIfUuidForPHPValue(): void public function testGetName(): void { - $this->assertSame('uuid', $this->getType()->getName()); + $this->assertSame('uuid', $this->getType()::lookupName($this->getType())); } public function testGetGuidTypeDeclarationSQL(): void @@ -138,11 +138,6 @@ public function testGetGuidTypeDeclarationSQL(): void ); } - public function testRequiresSQLCommentHint(): void - { - $this->assertTrue($this->getType()->requiresSQLCommentHint($this->getPlatform())); - } - public function testGetMappedDatabaseTypes(): void { $this->assertSame(['uuid'], $this->getType()->getMappedDatabaseTypes($this->getPlatform()));