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 ec67d0c

Browse files
Improve EntityColumnRule for enums
1 parent 6fe9e9d commit ec67d0c

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-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: 18 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;
@@ -59,6 +60,9 @@ protected function getRule(): Rule
5960
if (!Type::hasType('array')) {
6061
Type::addType('array', \Doctrine\DBAL\Types\ArrayType::class);
6162
}
63+
if (!Type::hasType('enum')) {
64+
Type::addType('enum', \Doctrine\DBAL\Types\EnumType::class);
65+
}
6266

6367
return new EntityColumnRule(
6468
new ObjectMetadataResolver($this->objectManagerLoader, __DIR__ . '/../../../../tmp'),
@@ -75,6 +79,7 @@ protected function getRule(): Rule
7579
new StringType(),
7680
new SimpleArrayType(),
7781
new UuidTypeDescriptor(FakeTestingUuidType::class),
82+
new EnumType(),
7883
new ReflectionDescriptor(CarbonImmutableType::class, $this->createReflectionProvider(), self::getContainer()),
7984
new ReflectionDescriptor(CarbonType::class, $this->createReflectionProvider(), self::getContainer()),
8085
new ReflectionDescriptor(CustomType::class, $this->createReflectionProvider(), self::getContainer()),
@@ -441,4 +446,17 @@ public function testBug306(?string $objectManagerLoader): void
441446
]);
442447
}
443448

449+
/**
450+
* @dataProvider dataObjectManagerLoader
451+
*/
452+
public function testBug677(?string $objectManagerLoader): void
453+
{
454+
if (PHP_VERSION_ID < 80100) {
455+
self::markTestSkipped('Test requires PHP 8.1');
456+
}
457+
$this->allowNullablePropertyForRequiredField = false;
458+
$this->objectManagerLoader = $objectManagerLoader;
459+
$this->analyse([__DIR__ . '/data/bug-677.php'], []);
460+
}
461+
444462
}
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 によって変換されたページ (->オリジナル) /