Skip to content

Commit c056a39

Browse files
committed
EntityColumnRule - check backed Enum type against Column mapping type
1 parent 820606a commit c056a39

File tree

4 files changed

+32
-2
lines changed

4 files changed

+32
-2
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
],
88
"require": {
99
"php": "^7.1 || ^8.0",
10-
"phpstan/phpstan": "^1.3"
10+
"phpstan/phpstan": "^1.4.1"
1111
},
1212
"conflict": {
1313
"doctrine/collections": "<1.0",
@@ -46,7 +46,7 @@
4646
},
4747
"extra": {
4848
"branch-alias": {
49-
"dev-master": "1.0-dev"
49+
"dev-master": "1.1-dev"
5050
},
5151
"phpstan": {
5252
"includes": [

src/Rules/Doctrine/ORM/EntityColumnRule.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PhpParser\Node;
66
use PHPStan\Analyser\Scope;
77
use PHPStan\Reflection\MissingPropertyFromReflectionException;
8+
use PHPStan\Reflection\ReflectionProvider;
89
use PHPStan\Rules\Rule;
910
use PHPStan\Type\ArrayType;
1011
use PHPStan\Type\Doctrine\DescriptorNotRegisteredException;
@@ -35,6 +36,9 @@ class EntityColumnRule implements Rule
3536
/** @var \PHPStan\Type\Doctrine\DescriptorRegistry */
3637
private $descriptorRegistry;
3738

39+
/** @var ReflectionProvider */
40+
private $reflectionProvider;
41+
3842
/** @var bool */
3943
private $reportUnknownTypes;
4044

@@ -44,12 +48,14 @@ class EntityColumnRule implements Rule
4448
public function __construct(
4549
ObjectMetadataResolver $objectMetadataResolver,
4650
DescriptorRegistry $descriptorRegistry,
51+
ReflectionProvider $reflectionProvider,
4752
bool $reportUnknownTypes,
4853
bool $allowNullablePropertyForRequiredField
4954
)
5055
{
5156
$this->objectMetadataResolver = $objectMetadataResolver;
5257
$this->descriptorRegistry = $descriptorRegistry;
58+
$this->reflectionProvider = $reflectionProvider;
5359
$this->reportUnknownTypes = $reportUnknownTypes;
5460
$this->allowNullablePropertyForRequiredField = $allowNullablePropertyForRequiredField;
5561
}
@@ -122,6 +128,22 @@ public function processNode(Node $node, Scope $scope): array
122128

123129
$enumTypeString = $fieldMapping['enumType'] ?? null;
124130
if ($enumTypeString !== null) {
131+
if ($this->reflectionProvider->hasClass($enumTypeString)) {
132+
$enumReflection = $this->reflectionProvider->getClass($enumTypeString);
133+
$backedEnumType = $enumReflection->getBackedEnumType();
134+
if ($backedEnumType !== null) {
135+
if (!$backedEnumType->equals($writableToDatabaseType) || !$backedEnumType->equals($writableToPropertyType)) {
136+
$errors[] = sprintf(
137+
'Property %s::$%s type mapping mismatch: backing type %s of enum %s does not match database type %s.',
138+
$className,
139+
$propertyName,
140+
$backedEnumType->describe(VerbosityLevel::typeOnly()),
141+
$enumReflection->getDisplayName(),
142+
$writableToDatabaseType->describe(VerbosityLevel::typeOnly())
143+
);
144+
}
145+
}
146+
}
125147
$enumType = new ObjectType($enumTypeString);
126148
$writableToPropertyType = $enumType;
127149
$writableToDatabaseType = $enumType;

tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ protected function getRule(): Rule
7171
new ReflectionDescriptor(CustomType::class, $this->createBroker()),
7272
new ReflectionDescriptor(CustomNumericType::class, $this->createBroker()),
7373
]),
74+
$this->createReflectionProvider(),
7475
true,
7576
$this->allowNullablePropertyForRequiredField
7677
);
@@ -291,6 +292,10 @@ public function testEnumType(): void
291292
'Property PHPStan\Rules\Doctrine\ORMAttributes\Foo::$type2 type mapping mismatch: property can contain PHPStan\Rules\Doctrine\ORMAttributes\BarEnum but database expects PHPStan\Rules\Doctrine\ORMAttributes\FooEnum.',
292293
35,
293294
],
295+
[
296+
'Property PHPStan\Rules\Doctrine\ORMAttributes\Foo::$type3 type mapping mismatch: backing type string of enum PHPStan\Rules\Doctrine\ORMAttributes\FooEnum does not match database type int.',
297+
38,
298+
],
294299
]);
295300
}
296301

tests/Rules/Doctrine/ORM/data-attributes/enum-type.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,7 @@ class Foo
3434
#[ORM\Column(type: "string", enumType: FooEnum::class)]
3535
public BarEnum $type2;
3636

37+
#[ORM\Column(type: "integer", enumType: FooEnum::class)]
38+
public FooEnum $type3;
39+
3740
}

0 commit comments

Comments
 (0)