Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit eeff198

Browse files
VincentLangletondrejmirtes
authored andcommitted
Improve EntityColumnRule for enums
1 parent cb37e28 commit eeff198

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

‎src/Rules/Doctrine/ORM/EntityColumnRule.php‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PHPStan\Rules\Rule;
1010
use PHPStan\Rules\RuleErrorBuilder;
1111
use PHPStan\Type\ArrayType;
12+
use PHPStan\Type\Constant\ConstantStringType;
1213
use PHPStan\Type\Doctrine\DescriptorNotRegisteredException;
1314
use PHPStan\Type\Doctrine\DescriptorRegistry;
1415
use PHPStan\Type\Doctrine\ObjectMetadataResolver;
@@ -21,10 +22,14 @@
2122
use PHPStan\Type\TypehintHelper;
2223
use PHPStan\Type\TypeTraverser;
2324
use PHPStan\Type\TypeUtils;
25+
use PHPStan\Type\UnionType;
2426
use PHPStan\Type\VerbosityLevel;
2527
use Throwable;
28+
use function count;
2629
use function get_class;
2730
use function in_array;
31+
use function is_array;
32+
use function is_string;
2833
use function sprintf;
2934

3035
/**
@@ -100,6 +105,26 @@ public function processNode(Node $node, Scope $scope): array
100105
$writableToPropertyType = $descriptor->getWritableToPropertyType();
101106
$writableToDatabaseType = $descriptor->getWritableToDatabaseType();
102107

108+
if ($fieldMapping['type'] === 'enum') {
109+
$values = $fieldMapping['options']['values'] ?? null;
110+
if (is_array($values)) {
111+
$enumTypes = [];
112+
foreach ($values as $value) {
113+
if (!is_string($value)) {
114+
$enumTypes = [];
115+
break;
116+
}
117+
118+
$enumTypes[] = new ConstantStringType($value);
119+
}
120+
121+
if (count($enumTypes) > 0) {
122+
$writableToPropertyType = new UnionType($enumTypes);
123+
$writableToDatabaseType = new UnionType($enumTypes);
124+
}
125+
}
126+
}
127+
103128
$enumTypeString = $fieldMapping['enumType'] ?? null;
104129
if ($enumTypeString !== null) {
105130
if ($writableToDatabaseType->isArray()->no() && $writableToPropertyType->isArray()->no()) {

‎tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use PHPStan\Type\Doctrine\Descriptors\DateTimeType;
1919
use PHPStan\Type\Doctrine\Descriptors\DateType;
2020
use PHPStan\Type\Doctrine\Descriptors\DecimalType;
21+
use PHPStan\Type\Doctrine\Descriptors\EnumType;
2122
use PHPStan\Type\Doctrine\Descriptors\IntegerType;
2223
use PHPStan\Type\Doctrine\Descriptors\JsonType;
2324
use PHPStan\Type\Doctrine\Descriptors\Ramsey\UuidTypeDescriptor;
@@ -26,6 +27,7 @@
2627
use PHPStan\Type\Doctrine\Descriptors\StringType;
2728
use PHPStan\Type\Doctrine\ObjectMetadataResolver;
2829
use function array_unshift;
30+
use function class_exists;
2931
use function strpos;
3032
use const PHP_VERSION_ID;
3133

@@ -75,6 +77,7 @@ protected function getRule(): Rule
7577
new StringType(),
7678
new SimpleArrayType(),
7779
new UuidTypeDescriptor(FakeTestingUuidType::class),
80+
new EnumType(),
7881
new ReflectionDescriptor(CarbonImmutableType::class, $this->createReflectionProvider(), self::getContainer()),
7982
new ReflectionDescriptor(CarbonType::class, $this->createReflectionProvider(), self::getContainer()),
8083
new ReflectionDescriptor(CustomType::class, $this->createReflectionProvider(), self::getContainer()),
@@ -441,4 +444,21 @@ public function testBug306(?string $objectManagerLoader): void
441444
]);
442445
}
443446

447+
/**
448+
* @dataProvider dataObjectManagerLoader
449+
*/
450+
public function testBug677(?string $objectManagerLoader): void
451+
{
452+
if (PHP_VERSION_ID < 80100) {
453+
self::markTestSkipped('Test requires PHP 8.1');
454+
}
455+
if (!class_exists(\Doctrine\DBAL\Types\EnumType::class)) {
456+
self::markTestSkipped('Test requires EnumType.');
457+
}
458+
459+
$this->allowNullablePropertyForRequiredField = false;
460+
$this->objectManagerLoader = $objectManagerLoader;
461+
$this->analyse([__DIR__ . '/data/bug-677.php'], []);
462+
}
463+
444464
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php // lint >= 8.1
2+
3+
namespace PHPStan\Rules\Doctrine\ORM\Bug677;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
#[ORM\Entity]
8+
class MyBrokenEntity
9+
{
10+
public const LOGIN_METHOD_BASIC_AUTH = 'BasicAuth';
11+
public const LOGIN_METHOD_SSO = 'SSO';
12+
public const LOGIN_METHOD_SAML = 'SAML';
13+
14+
public const LOGIN_METHODS = [
15+
self::LOGIN_METHOD_BASIC_AUTH,
16+
self::LOGIN_METHOD_SSO,
17+
self::LOGIN_METHOD_SAML,
18+
];
19+
20+
/**
21+
* @var int|null
22+
*/
23+
#[ORM\Id]
24+
#[ORM\GeneratedValue]
25+
#[ORM\Column(type: 'integer')]
26+
private $id;
27+
28+
/**
29+
* @var self::LOGIN_METHOD_*
30+
*/
31+
#[ORM\Column(name: 'login_method', type: 'enum', options: ['default' => self::LOGIN_METHOD_BASIC_AUTH, 'values' => self::LOGIN_METHODS])]
32+
private string $loginMethod = self::LOGIN_METHOD_BASIC_AUTH;
33+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /