From 7613f25d577786621dcb05f2ebbcdcf0b1592d1c Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Fri, 3 Nov 2023 07:08:44 -0400 Subject: [PATCH] Adds metadata field type and enumType validation against Entity property type --- lib/Doctrine/ORM/Tools/SchemaValidator.php | 20 ++++++++ .../Functional/Ticket/GH11037/GH11037Test.php | 49 +++++++++++++++++++ .../Ticket/GH11037/IntEntityStatus.php | 11 +++++ .../GH11037/InvalidEntityWithTypedEnum.php | 31 ++++++++++++ .../Ticket/GH11037/StringEntityStatus.php | 11 +++++ .../GH11037/ValidEntityWithTypedEnum.php | 31 ++++++++++++ 6 files changed, 153 insertions(+) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/GH11037Test.php create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/IntEntityStatus.php create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/InvalidEntityWithTypedEnum.php create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/StringEntityStatus.php create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/ValidEntityWithTypedEnum.php diff --git a/lib/Doctrine/ORM/Tools/SchemaValidator.php b/lib/Doctrine/ORM/Tools/SchemaValidator.php index c6948aa85ff..3fd323c565a 100644 --- a/lib/Doctrine/ORM/Tools/SchemaValidator.php +++ b/lib/Doctrine/ORM/Tools/SchemaValidator.php @@ -4,6 +4,7 @@ namespace Doctrine\ORM\Tools; +use BackedEnum; use Doctrine\DBAL\Types\AsciiStringType; use Doctrine\DBAL\Types\BigIntType; use Doctrine\DBAL\Types\BooleanType; @@ -21,6 +22,7 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo; +use ReflectionEnum; use ReflectionNamedType; use function array_diff; @@ -37,6 +39,7 @@ use function get_class; use function implode; use function in_array; +use function is_a; use function sprintf; use const PHP_VERSION_ID; @@ -386,6 +389,23 @@ function (array $fieldMapping) use ($class): ?string { return null; } + if ( + is_a($propertyType, BackedEnum::class, true) + && $metadataFieldType === (string) (new ReflectionEnum($propertyType))->getBackingType() + ) { + if (! isset($fieldMapping['enumType']) || $propertyType === $fieldMapping['enumType']) { + return null; + } + + return sprintf( + "The field '%s#%s' has the property type '%s' that differs from the metadata enumType '%s'.", + $class->name, + $fieldName, + $propertyType, + $fieldMapping['enumType'] + ); + } + return sprintf( "The field '%s#%s' has the property type '%s' that differs from the metadata field type '%s' returned by the '%s' DBAL type.", $class->name, diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/GH11037Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/GH11037Test.php new file mode 100644 index 00000000000..bb173c2759c --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/GH11037Test.php @@ -0,0 +1,49 @@ += 8.1 + */ +final class GH11037Test extends OrmTestCase +{ + /** @var EntityManagerInterface */ + private $em; + + /** @var SchemaValidator */ + private $validator; + + protected function setUp(): void + { + $this->em = $this->getTestEntityManager(); + $this->validator = new SchemaValidator($this->em); + } + + public function testMetadataFieldTypeCoherentWithEntityPropertyType(): void + { + $class = $this->em->getClassMetadata(ValidEntityWithTypedEnum::class); + $ce = $this->validator->validateClass($class); + + self::assertEquals([], $ce); + } + + public function testMetadataFieldTypeNotCoherentWithEntityPropertyType(): void + { + $class = $this->em->getClassMetadata(InvalidEntityWithTypedEnum::class); + $ce = $this->validator->validateClass($class); + + self::assertEquals( + [ + "The field 'Doctrine\Tests\ORM\Functional\Ticket\GH11037\InvalidEntityWithTypedEnum#status1' has the property type 'Doctrine\Tests\ORM\Functional\Ticket\GH11037\StringEntityStatus' that differs from the metadata field type 'int' returned by the 'integer' DBAL type.", + "The field 'Doctrine\Tests\ORM\Functional\Ticket\GH11037\InvalidEntityWithTypedEnum#status2' has the property type 'Doctrine\Tests\ORM\Functional\Ticket\GH11037\IntEntityStatus' that differs from the metadata enumType 'Doctrine\Tests\ORM\Functional\Ticket\GH11037\StringEntityStatus'.", + ], + $ce + ); + } +} diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/IntEntityStatus.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/IntEntityStatus.php new file mode 100644 index 00000000000..c9ac6df5a83 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH11037/IntEntityStatus.php @@ -0,0 +1,11 @@ +