diff --git a/composer.json b/composer.json index 155f933a..c929d687 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "phpstan/phpstan-phpunit": "^0.12", "phpstan/phpstan-strict-rules": "^0.12", "phpunit/phpunit": "^7.0", + "ramsey/uuid-doctrine": "^1.5.0", "slevomat/coding-standard": "^4.5.2", "doctrine/common": "^2.7", "doctrine/orm": "^2.5", diff --git a/extension.neon b/extension.neon index c9be625e..e645a250 100644 --- a/extension.neon +++ b/extension.neon @@ -255,3 +255,20 @@ services: - class: PHPStan\Type\Doctrine\Descriptors\TimeType tags: [phpstan.doctrine.typeDescriptor] + + # 3rd party Type descriptors + - + class: PHPStan\Type\Doctrine\Descriptors\Ramsey\UuidTypeDescriptor + tags: [phpstan.doctrine.typeDescriptor] + arguments: + uuidTypeName: Ramsey\Uuid\Doctrine\UuidType + - + class: PHPStan\Type\Doctrine\Descriptors\Ramsey\UuidTypeDescriptor + tags: [phpstan.doctrine.typeDescriptor] + arguments: + uuidTypeName: Ramsey\Uuid\Doctrine\UuidBinaryType + - + class: PHPStan\Type\Doctrine\Descriptors\Ramsey\UuidTypeDescriptor + tags: [phpstan.doctrine.typeDescriptor] + arguments: + uuidTypeName: Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType diff --git a/src/Type/Doctrine/Descriptors/Ramsey/UuidTypeDescriptor.php b/src/Type/Doctrine/Descriptors/Ramsey/UuidTypeDescriptor.php new file mode 100644 index 00000000..f422e9c0 --- /dev/null +++ b/src/Type/Doctrine/Descriptors/Ramsey/UuidTypeDescriptor.php @@ -0,0 +1,57 @@ + + * @var string + */ + private $uuidTypeName; + + public function __construct( + string $uuidTypeName + ) + { + if (!in_array($uuidTypeName, self::SUPPORTED_UUID_TYPES, true)) { + throw new \PHPStan\ShouldNotHappenException(sprintf( + 'Unexpected UUID column type "%s" provided', + $uuidTypeName + )); + } + + $this->uuidTypeName = $uuidTypeName; + } + + public function getType(): string + { + return $this->uuidTypeName; + } + + public function getWritableToPropertyType(): Type + { + return new \PHPStan\Type\ObjectType(UuidInterface::class); + } + + public function getWritableToDatabaseType(): Type + { + return TypeCombinator::union( + new \PHPStan\Type\StringType(), + new \PHPStan\Type\ObjectType(UuidInterface::class) + ); + } + +} diff --git a/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php b/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php index 0e10fd7e..8e583847 100644 --- a/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php +++ b/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php @@ -13,9 +13,11 @@ use PHPStan\Type\Doctrine\Descriptors\DateTimeType; use PHPStan\Type\Doctrine\Descriptors\DateType; use PHPStan\Type\Doctrine\Descriptors\IntegerType; +use PHPStan\Type\Doctrine\Descriptors\Ramsey\UuidTypeDescriptor; use PHPStan\Type\Doctrine\Descriptors\ReflectionDescriptor; use PHPStan\Type\Doctrine\Descriptors\StringType; use PHPStan\Type\Doctrine\ObjectMetadataResolver; +use Ramsey\Uuid\Doctrine\UuidType; /** * @extends RuleTestCase @@ -28,6 +30,9 @@ protected function getRule(): Rule if (!Type::hasType(CustomType::NAME)) { Type::addType(CustomType::NAME, CustomType::class); } + if (!Type::hasType(UuidType::NAME)) { + Type::addType(UuidType::NAME, UuidType::class); + } return new EntityColumnRule( new ObjectMetadataResolver(__DIR__ . '/entity-manager.php', null), @@ -40,6 +45,7 @@ protected function getRule(): Rule new IntegerType(), new ReflectionDescriptor(CustomType::class, $this->createBroker()), new DateType(), + new UuidTypeDescriptor(UuidType::class), ]), true ); @@ -72,6 +78,14 @@ public function testRule(): void 'Property PHPStan\Rules\Doctrine\ORM\MyBrokenEntity::$four type mapping mismatch: property can contain DateTime but database expects DateTimeImmutable.', 43, ], + [ + 'Property PHPStan\Rules\Doctrine\ORM\MyBrokenEntity::$uuidInvalidType type mapping mismatch: database can contain Ramsey\Uuid\UuidInterface but property expects int.', + 72, + ], + [ + 'Property PHPStan\Rules\Doctrine\ORM\MyBrokenEntity::$uuidInvalidType type mapping mismatch: property can contain int but database expects Ramsey\Uuid\UuidInterface|string.', + 72, + ], ]); } diff --git a/tests/Rules/Doctrine/ORM/data/MyBrokenEntity.php b/tests/Rules/Doctrine/ORM/data/MyBrokenEntity.php index c4f054a2..ca1da105 100644 --- a/tests/Rules/Doctrine/ORM/data/MyBrokenEntity.php +++ b/tests/Rules/Doctrine/ORM/data/MyBrokenEntity.php @@ -59,4 +59,16 @@ class MyBrokenEntity extends MyBrokenSuperclass */ private $never; + /** + * @ORM\Column(type="uuid") + * @var \Ramsey\Uuid\UuidInterface + */ + private $uuid; + + /** + * @ORM\Column(type="uuid") + * @var int + */ + private $uuidInvalidType; + }