Skip to content

Commit 820606a

Browse files
committed
Support for enumType in Column mapping
1 parent d94857f commit 820606a

File tree

7 files changed

+89
-10
lines changed

7 files changed

+89
-10
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"doctrine/dbal": "^2.13.7",
2424
"doctrine/lexer": "^1.2.1",
2525
"doctrine/mongodb-odm": "^1.3 || ^2.1",
26-
"doctrine/orm": "^2.9.1",
26+
"doctrine/orm": "^2.11.0",
2727
"doctrine/persistence": "^1.1 || ^2.0",
2828
"nesbot/carbon": "^2.49",
2929
"nikic/php-parser": "^4.13.2",

phpcs.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,5 @@
6565
</rule>
6666
<exclude-pattern>tests/tmp</exclude-pattern>
6767
<exclude-pattern>tests/*/data</exclude-pattern>
68+
<exclude-pattern>tests/*/data-attributes</exclude-pattern>
6869
</ruleset>

phpstan.neon

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ includes:
99
parameters:
1010
excludePaths:
1111
- tests/*/data/*
12+
- tests/*/data-attributes/*
1213
- tests/*/data-php-*/*
14+
- tests/Rules/Doctrine/ORM/entity-manager.php
1315

1416
ignoreErrors:
1517
-

src/Rules/Doctrine/ORM/EntityColumnRule.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use PHPStan\Type\ErrorType;
1414
use PHPStan\Type\MixedType;
1515
use PHPStan\Type\NeverType;
16+
use PHPStan\Type\ObjectType;
1617
use PHPStan\Type\Type;
1718
use PHPStan\Type\TypeCombinator;
1819
use PHPStan\Type\TypeTraverser;
@@ -101,7 +102,7 @@ public function processNode(Node $node, Scope $scope): array
101102
return [];
102103
}
103104

104-
/** @var array{type: string, fieldName: string, columnName?: string, inherited?: class-string, nullable?: bool} $fieldMapping */
105+
/** @var array{type: string, fieldName: string, columnName?: string, inherited?: class-string, nullable?: bool, enumType?: ?string} $fieldMapping */
105106
$fieldMapping = $metadata->fieldMappings[$propertyName];
106107

107108
$errors = [];
@@ -116,6 +117,16 @@ public function processNode(Node $node, Scope $scope): array
116117
)] : [];
117118
}
118119

120+
$writableToPropertyType = $descriptor->getWritableToPropertyType();
121+
$writableToDatabaseType = $descriptor->getWritableToDatabaseType();
122+
123+
$enumTypeString = $fieldMapping['enumType'] ?? null;
124+
if ($enumTypeString !== null) {
125+
$enumType = new ObjectType($enumTypeString);
126+
$writableToPropertyType = $enumType;
127+
$writableToDatabaseType = $enumType;
128+
}
129+
119130
$identifiers = [];
120131
if ($metadata->generatorType !== 5) { // ClassMetadataInfo::GENERATOR_TYPE_NONE
121132
try {
@@ -128,8 +139,6 @@ public function processNode(Node $node, Scope $scope): array
128139
}
129140
}
130141

131-
$writableToPropertyType = $descriptor->getWritableToPropertyType();
132-
$writableToDatabaseType = $descriptor->getWritableToDatabaseType();
133142
$nullable = isset($fieldMapping['nullable']) ? $fieldMapping['nullable'] === true : false;
134143
if ($nullable) {
135144
$writableToPropertyType = TypeCombinator::addNull($writableToPropertyType);

tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use PHPStan\Type\Doctrine\Descriptors\StringType;
2424
use PHPStan\Type\Doctrine\ObjectMetadataResolver;
2525
use Ramsey\Uuid\Doctrine\UuidType;
26+
use const PHP_VERSION_ID;
2627

2728
/**
2829
* @extends RuleTestCase<EntityColumnRule>
@@ -274,4 +275,23 @@ public function testUnknownType(): void
274275
]);
275276
}
276277

278+
public function testEnumType(): void
279+
{
280+
if (PHP_VERSION_ID < 80100) {
281+
self::markTestSkipped('Test requires PHP 8.1.');
282+
}
283+
284+
$this->allowNullablePropertyForRequiredField = false;
285+
$this->analyse([__DIR__ . '/data-attributes/enum-type.php'], [
286+
[
287+
'Property PHPStan\Rules\Doctrine\ORMAttributes\Foo::$type2 type mapping mismatch: database can contain PHPStan\Rules\Doctrine\ORMAttributes\FooEnum but property expects PHPStan\Rules\Doctrine\ORMAttributes\BarEnum.',
288+
35,
289+
],
290+
[
291+
'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.',
292+
35,
293+
],
294+
]);
295+
}
296+
277297
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php // lint >= 8.1
2+
3+
namespace PHPStan\Rules\Doctrine\ORMAttributes;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
enum FooEnum: string {
8+
9+
case ONE = 'one';
10+
case TWO = 'two';
11+
12+
}
13+
14+
enum BarEnum: string {
15+
16+
case ONE = 'one';
17+
case TWO = 'two';
18+
19+
}
20+
21+
#[ORM\Entity]
22+
class Foo
23+
{
24+
25+
26+
#[ORM\Column(nullable: false)]
27+
#[ORM\Id]
28+
#[ORM\GeneratedValue]
29+
private ?int $id = null;
30+
31+
#[ORM\Column(type: "string", enumType: FooEnum::class)]
32+
public FooEnum $type1;
33+
34+
#[ORM\Column(type: "string", enumType: FooEnum::class)]
35+
public BarEnum $type2;
36+
37+
}

tests/Rules/Doctrine/ORM/entity-manager.php

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
use Doctrine\ORM\Configuration;
55
use Doctrine\ORM\EntityManager;
66
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
7+
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
8+
use Doctrine\Persistence\Mapping\Driver\MappingDriverChain;
79
use Symfony\Component\Cache\Adapter\ArrayAdapter;
810
use Symfony\Component\Cache\DoctrineProvider;
911

@@ -12,12 +14,20 @@
1214
$config->setProxyNamespace('PHPstan\Doctrine\OrmProxies');
1315
$config->setMetadataCacheImpl(new DoctrineProvider(new ArrayAdapter()));
1416

15-
$config->setMetadataDriverImpl(
16-
new AnnotationDriver(
17-
new AnnotationReader(),
18-
[__DIR__ . '/data']
19-
)
20-
);
17+
$metadataDriver = new MappingDriverChain();
18+
$metadataDriver->addDriver(new AnnotationDriver(
19+
new AnnotationReader(),
20+
[__DIR__ . '/data']
21+
), 'PHPStan\\Rules\\Doctrine\\ORM\\');
22+
23+
if (PHP_VERSION_ID >= 80100) {
24+
$metadataDriver->addDriver(
25+
new AttributeDriver([__DIR__ . '/data-attributes']),
26+
'PHPStan\\Rules\\Doctrine\\ORMAttributes\\'
27+
);
28+
}
29+
30+
$config->setMetadataDriverImpl($metadataDriver);
2131

2232
\Doctrine\DBAL\Types\Type::overrideType(
2333
'date',

0 commit comments

Comments
 (0)