Skip to content

Commit accc3fd

Browse files
Add support for symfony uuid
1 parent 934f573 commit accc3fd

File tree

10 files changed

+448
-26
lines changed

10 files changed

+448
-26
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
"phpstan/phpstan-strict-rules": "^2.0",
3737
"phpunit/phpunit": "^9.6.20",
3838
"ramsey/uuid": "^4.2",
39-
"symfony/cache": "^5.4"
39+
"symfony/cache": "^5.4",
40+
"symfony/uid": "^7.3"
4041
},
4142
"config": {
4243
"sort-packages": true,

extension.neon

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,16 @@ services:
418418
tags: [phpstan.doctrine.typeDescriptor]
419419
arguments:
420420
uuidTypeName: Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType
421+
-
422+
class: PHPStan\Type\Doctrine\Descriptors\Symfony\UuidTypeDescriptor
423+
tags: [phpstan.doctrine.typeDescriptor]
424+
arguments:
425+
uuidTypeName: Symfony\Bridge\Doctrine\Types\UuidType
426+
-
427+
class: PHPStan\Type\Doctrine\Descriptors\Symfony\UlidTypeDescriptor
428+
tags: [phpstan.doctrine.typeDescriptor]
429+
arguments:
430+
uuidTypeName: Symfony\Bridge\Doctrine\Types\UlidType
421431

422432
# Doctrine Collection
423433
-

src/Type/Doctrine/Descriptors/Ramsey/UuidTypeDescriptor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace PHPStan\Type\Doctrine\Descriptors\Ramsey;
44

5-
use PHPStan\Rules\Doctrine\ORM\FakeTestingUuidType;
5+
use PHPStan\Rules\Doctrine\ORM\FakeTestingRamseyUuidType;
66
use PHPStan\ShouldNotHappenException;
77
use PHPStan\Type\Doctrine\Descriptors\DoctrineTypeDescriptor;
88
use PHPStan\Type\ObjectType;
@@ -20,7 +20,7 @@ class UuidTypeDescriptor implements DoctrineTypeDescriptor
2020
'Ramsey\Uuid\Doctrine\UuidType',
2121
'Ramsey\Uuid\Doctrine\UuidBinaryType',
2222
'Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType',
23-
FakeTestingUuidType::class,
23+
FakeTestingRamseyUuidType::class,
2424
];
2525

2626
private string $uuidTypeName;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Doctrine\Descriptors\Symfony;
4+
5+
use PHPStan\ShouldNotHappenException;
6+
use PHPStan\Type\Doctrine\Descriptors\DoctrineTypeDescriptor;
7+
use PHPStan\Type\ObjectType;
8+
use PHPStan\Type\StringType;
9+
use PHPStan\Type\Type;
10+
use PHPStan\Type\TypeCombinator;
11+
use Rules\Doctrine\ORM\FakeTestingSymfonyUlidType;
12+
use Symfony\Component\Uid\Ulid;
13+
use function in_array;
14+
use function sprintf;
15+
16+
class UlidTypeDescriptor implements DoctrineTypeDescriptor
17+
{
18+
19+
private const SUPPORTED_UUID_TYPES = [
20+
'Symfony\Bridge\Doctrine\Types\UlidType',
21+
FakeTestingSymfonyUlidType::class,
22+
];
23+
24+
private string $uuidTypeName;
25+
26+
public function __construct(
27+
string $uuidTypeName
28+
)
29+
{
30+
if (!in_array($uuidTypeName, self::SUPPORTED_UUID_TYPES, true)) {
31+
throw new ShouldNotHappenException(sprintf(
32+
'Unexpected UUID column type "%s" provided',
33+
$uuidTypeName,
34+
));
35+
}
36+
37+
$this->uuidTypeName = $uuidTypeName;
38+
}
39+
40+
public function getType(): string
41+
{
42+
/** @var class-string<\Doctrine\DBAL\Types\Type> */
43+
return $this->uuidTypeName;
44+
}
45+
46+
public function getWritableToPropertyType(): Type
47+
{
48+
return new ObjectType(Ulid::class);
49+
}
50+
51+
public function getWritableToDatabaseType(): Type
52+
{
53+
return TypeCombinator::union(
54+
new StringType(),
55+
new ObjectType(Ulid::class),
56+
);
57+
}
58+
59+
public function getDatabaseInternalType(): Type
60+
{
61+
return new StringType();
62+
}
63+
64+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Doctrine\Descriptors\Symfony;
4+
5+
use PHPStan\ShouldNotHappenException;
6+
use PHPStan\Type\Doctrine\Descriptors\DoctrineTypeDescriptor;
7+
use PHPStan\Type\ObjectType;
8+
use PHPStan\Type\StringType;
9+
use PHPStan\Type\Type;
10+
use PHPStan\Type\TypeCombinator;
11+
use Rules\Doctrine\ORM\FakeTestingSymfonyUuidType;
12+
use Symfony\Component\Uid\Uuid;
13+
use function in_array;
14+
use function sprintf;
15+
16+
class UuidTypeDescriptor implements DoctrineTypeDescriptor
17+
{
18+
19+
private const SUPPORTED_UUID_TYPES = [
20+
'Symfony\Bridge\Doctrine\Types\UuidType',
21+
FakeTestingSymfonyUuidType::class,
22+
];
23+
24+
private string $uuidTypeName;
25+
26+
public function __construct(
27+
string $uuidTypeName
28+
)
29+
{
30+
if (!in_array($uuidTypeName, self::SUPPORTED_UUID_TYPES, true)) {
31+
throw new ShouldNotHappenException(sprintf(
32+
'Unexpected UUID column type "%s" provided',
33+
$uuidTypeName,
34+
));
35+
}
36+
37+
$this->uuidTypeName = $uuidTypeName;
38+
}
39+
40+
public function getType(): string
41+
{
42+
/** @var class-string<\Doctrine\DBAL\Types\Type> */
43+
return $this->uuidTypeName;
44+
}
45+
46+
public function getWritableToPropertyType(): Type
47+
{
48+
return new ObjectType(Uuid::class);
49+
}
50+
51+
public function getWritableToDatabaseType(): Type
52+
{
53+
return TypeCombinator::union(
54+
new StringType(),
55+
new ObjectType(Uuid::class),
56+
);
57+
}
58+
59+
public function getDatabaseInternalType(): Type
60+
{
61+
return new StringType();
62+
}
63+
64+
}

tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,16 @@
2121
use PHPStan\Type\Doctrine\Descriptors\EnumType;
2222
use PHPStan\Type\Doctrine\Descriptors\IntegerType;
2323
use PHPStan\Type\Doctrine\Descriptors\JsonType;
24-
use PHPStan\Type\Doctrine\Descriptors\Ramsey\UuidTypeDescriptor;
24+
use PHPStan\Type\Doctrine\Descriptors\Ramsey\UuidTypeDescriptor as RamseyUuidTypeDescriptor;
25+
use PHPStan\Type\Doctrine\Descriptors\Symfony\UuidTypeDescriptor as SymfonyUuidTypeDescriptor;
26+
use PHPStan\Type\Doctrine\Descriptors\Symfony\UlidTypeDescriptor as SymfonyUlidTypeDescriptor;
2527
use PHPStan\Type\Doctrine\Descriptors\ReflectionDescriptor;
2628
use PHPStan\Type\Doctrine\Descriptors\SimpleArrayType;
2729
use PHPStan\Type\Doctrine\Descriptors\StringType;
2830
use PHPStan\Type\Doctrine\ObjectMetadataResolver;
31+
use Rules\Doctrine\ORM\FakeTestingSymfonyUlidType;
32+
use Rules\Doctrine\ORM\FakeTestingSymfonyUuidType;
33+
2934
use function array_unshift;
3035
use function class_exists;
3136
use function strpos;
@@ -41,16 +46,51 @@ class EntityColumnRuleTest extends RuleTestCase
4146

4247
private ?string $objectManagerLoader = null;
4348

49+
private bool $useSymfonyUuid = true;
50+
4451
protected function getRule(): Rule
4552
{
53+
$descriptors = [
54+
new ArrayType(),
55+
new BigIntType(),
56+
new BinaryType(),
57+
new DateTimeImmutableType(),
58+
new DateTimeType(),
59+
new DateType(),
60+
new DecimalType(new DriverDetector()),
61+
new JsonType(),
62+
new IntegerType(),
63+
new StringType(),
64+
new SimpleArrayType(),
65+
new EnumType(),
66+
new ReflectionDescriptor(CarbonImmutableType::class, $this->createReflectionProvider(), self::getContainer()),
67+
new ReflectionDescriptor(CarbonType::class, $this->createReflectionProvider(), self::getContainer()),
68+
new ReflectionDescriptor(CustomType::class, $this->createReflectionProvider(), self::getContainer()),
69+
new ReflectionDescriptor(CustomNumericType::class, $this->createReflectionProvider(), self::getContainer()),
70+
];
71+
4672
if (!Type::hasType(CustomType::NAME)) {
4773
Type::addType(CustomType::NAME, CustomType::class);
4874
}
4975
if (!Type::hasType(CustomNumericType::NAME)) {
5076
Type::addType(CustomNumericType::NAME, CustomNumericType::class);
5177
}
52-
if (!Type::hasType(FakeTestingUuidType::NAME)) {
53-
Type::addType(FakeTestingUuidType::NAME, FakeTestingUuidType::class);
78+
if ($this->useSymfonyUuid) {
79+
if (!Type::hasType(FakeTestingSymfonyUuidType::NAME)) {
80+
Type::addType(FakeTestingSymfonyUuidType::NAME, FakeTestingSymfonyUuidType::class);
81+
}
82+
$descriptors[] = new SymfonyUuidTypeDescriptor(FakeTestingSymfonyUuidType::class);
83+
84+
if (!Type::hasType(FakeTestingSymfonyUlidType::NAME)) {
85+
Type::addType(FakeTestingSymfonyUlidType::NAME, FakeTestingSymfonyUlidType::class);
86+
}
87+
$descriptors[] = new SymfonyUlidTypeDescriptor(FakeTestingSymfonyUlidType::class);
88+
} else {
89+
if (!Type::hasType(FakeTestingRamseyUuidType::NAME)) {
90+
Type::addType(FakeTestingRamseyUuidType::NAME, FakeTestingRamseyUuidType::class);
91+
}
92+
93+
$descriptors[] = new RamseyUuidTypeDescriptor(FakeTestingRamseyUuidType::class);
5494
}
5595
if (!Type::hasType('carbon')) {
5696
Type::addType('carbon', CarbonType::class);
@@ -64,25 +104,7 @@ protected function getRule(): Rule
64104

65105
return new EntityColumnRule(
66106
new ObjectMetadataResolver($this->objectManagerLoader, __DIR__ . '/../../../../tmp'),
67-
new DefaultDescriptorRegistry([
68-
new ArrayType(),
69-
new BigIntType(),
70-
new BinaryType(),
71-
new DateTimeImmutableType(),
72-
new DateTimeType(),
73-
new DateType(),
74-
new DecimalType(new DriverDetector()),
75-
new JsonType(),
76-
new IntegerType(),
77-
new StringType(),
78-
new SimpleArrayType(),
79-
new UuidTypeDescriptor(FakeTestingUuidType::class),
80-
new EnumType(),
81-
new ReflectionDescriptor(CarbonImmutableType::class, $this->createReflectionProvider(), self::getContainer()),
82-
new ReflectionDescriptor(CarbonType::class, $this->createReflectionProvider(), self::getContainer()),
83-
new ReflectionDescriptor(CustomType::class, $this->createReflectionProvider(), self::getContainer()),
84-
new ReflectionDescriptor(CustomNumericType::class, $this->createReflectionProvider(), self::getContainer()),
85-
]),
107+
new DefaultDescriptorRegistry($descriptors),
86108
$this->createReflectionProvider(),
87109
true,
88110
$this->allowNullablePropertyForRequiredField,
@@ -461,6 +483,18 @@ public function testBug677(?string $objectManagerLoader): void
461483
$this->analyse([__DIR__ . '/data/bug-677.php'], []);
462484
}
463485

486+
/**
487+
* @dataProvider dataObjectManagerLoader
488+
*/
489+
public function testSymfonyUuid(?string $objectManagerLoader): void
490+
{
491+
$this->allowNullablePropertyForRequiredField = true;
492+
$this->objectManagerLoader = $objectManagerLoader;
493+
$this->useSymfonyUuid = true;
494+
495+
$this->analyse([__DIR__ . '/data/EntityWithSymfonyUid.php'], []);
496+
}
497+
464498
/**
465499
* @dataProvider dataObjectManagerLoader
466500
*/

tests/Rules/Doctrine/ORM/FakeTestingUuidType.php renamed to tests/Rules/Doctrine/ORM/FakeTestingRamseyUuidType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* From https://github.com/ramsey/uuid-doctrine/blob/fafebbe972cdaba9274c286ea8923e2de2579027/src/UuidType.php
1414
* Copyright (c) 2012-2022 Ben Ramsey <[email protected]>
1515
*/
16-
final class FakeTestingUuidType extends GuidType
16+
final class FakeTestingRamseyUuidType extends GuidType
1717
{
1818

1919
public const NAME = 'uuid';

0 commit comments

Comments
 (0)