Skip to content

Commit 35b098c

Browse files
committed
EntityColumnRule, EntityRelationRule - check promoted properties
1 parent 5556305 commit 35b098c

File tree

6 files changed

+105
-6
lines changed

6 files changed

+105
-6
lines changed

src/Rules/Doctrine/ORM/EntityColumnRule.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PhpParser\Node;
66
use PHPStan\Analyser\Scope;
7+
use PHPStan\Node\ClassPropertyNode;
78
use PHPStan\Reflection\MissingPropertyFromReflectionException;
89
use PHPStan\Reflection\ReflectionProvider;
910
use PHPStan\Rules\Rule;
@@ -25,7 +26,7 @@
2526
use function sprintf;
2627

2728
/**
28-
* @implements Rule<Node\Stmt\PropertyProperty>
29+
* @implements Rule<ClassPropertyNode>
2930
*/
3031
class EntityColumnRule implements Rule
3132
{
@@ -67,7 +68,7 @@ public function __construct(
6768

6869
public function getNodeType(): string
6970
{
70-
return Node\Stmt\PropertyProperty::class;
71+
return ClassPropertyNode::class;
7172
}
7273

7374
public function processNode(Node $node, Scope $scope): array
@@ -86,7 +87,7 @@ public function processNode(Node $node, Scope $scope): array
8687
return [];
8788
}
8889

89-
$propertyName = (string) $node->name;
90+
$propertyName = $node->getName();
9091
try {
9192
$property = $class->getNativeProperty($propertyName);
9293
} catch (MissingPropertyFromReflectionException $e) {

src/Rules/Doctrine/ORM/EntityRelationRule.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PhpParser\Node;
66
use PHPStan\Analyser\Scope;
7+
use PHPStan\Node\ClassPropertyNode;
78
use PHPStan\Reflection\MissingPropertyFromReflectionException;
89
use PHPStan\Rules\Rule;
910
use PHPStan\Type\Doctrine\ObjectMetadataResolver;
@@ -20,7 +21,7 @@
2021
use function sprintf;
2122

2223
/**
23-
* @implements Rule<Node\Stmt\PropertyProperty>
24+
* @implements Rule<ClassPropertyNode>
2425
*/
2526
class EntityRelationRule implements Rule
2627
{
@@ -47,7 +48,7 @@ public function __construct(
4748

4849
public function getNodeType(): string
4950
{
50-
return Node\Stmt\PropertyProperty::class;
51+
return ClassPropertyNode::class;
5152
}
5253

5354
public function processNode(Node $node, Scope $scope): array
@@ -67,7 +68,7 @@ public function processNode(Node $node, Scope $scope): array
6768
return [];
6869
}
6970

70-
$propertyName = (string) $node->name;
71+
$propertyName = $node->getName();
7172
try {
7273
$property = $class->getNativeProperty($propertyName);
7374
} catch (MissingPropertyFromReflectionException $e) {

tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,4 +374,22 @@ public function testPhpStanBug6445(?string $objectManagerLoader): void
374374
$this->analyse([__DIR__ . '/data/phpstan-bug-6445.php'], []);
375375
}
376376

377+
/**
378+
* @dataProvider dataObjectManagerLoader
379+
*/
380+
public function testBug306(?string $objectManagerLoader): void
381+
{
382+
if (PHP_VERSION_ID < 80000) {
383+
self::markTestSkipped('Test requires PHP 8.0');
384+
}
385+
$this->allowNullablePropertyForRequiredField = false;
386+
$this->objectManagerLoader = $objectManagerLoader;
387+
$this->analyse([__DIR__ . '/data/bug-306.php'], [
388+
[
389+
'Property PHPStan\Rules\Doctrine\ORM\Bug306\MyBrokenEntity::$one type mapping mismatch: database can contain string|null but property expects string.',
390+
25,
391+
],
392+
]);
393+
}
394+
377395
}

tests/Rules/Doctrine/ORM/EntityRelationRuleTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use PHPStan\Rules\Rule;
77
use PHPStan\Testing\RuleTestCase;
88
use PHPStan\Type\Doctrine\ObjectMetadataResolver;
9+
use const PHP_VERSION_ID;
910

1011
/**
1112
* @extends RuleTestCase<EntityRelationRule>
@@ -307,4 +308,19 @@ public function ruleWithAllowedNullablePropertyProvider(): Iterator
307308
];
308309
}
309310

311+
public function testBug306(): void
312+
{
313+
if (PHP_VERSION_ID < 80000) {
314+
self::markTestSkipped('Test requires PHP 8.0');
315+
}
316+
$this->allowNullablePropertyForRequiredField = false;
317+
$this->objectManagerLoader = __DIR__ . '/entity-manager.php';
318+
$this->analyse([__DIR__ . '/data/bug-306-relation.php'], [
319+
[
320+
'Property PHPStan\Rules\Doctrine\ORM\Bug306Relation\MyBrokenEntity::$genericCollection type mapping mismatch: property can contain Doctrine\Common\Collections\Collection but database expects Doctrine\Common\Collections\Collection&iterable<PHPStan\Rules\Doctrine\ORM\AnotherEntity>.',
321+
25,
322+
],
323+
]);
324+
}
325+
310326
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php // lint >= 8.0
2+
3+
namespace PHPStan\Rules\Doctrine\ORM\Bug306Relation;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
/**
8+
* @ORM\Entity()
9+
*/
10+
class MyBrokenEntity
11+
{
12+
13+
/**
14+
* @ORM\Id()
15+
* @ORM\GeneratedValue()
16+
* @ORM\Column(type="int")
17+
* @var int|null
18+
*/
19+
private $id;
20+
21+
public function __construct(
22+
/**
23+
* @ORM\OneToMany(targetEntity="PHPStan\Rules\Doctrine\ORM\AnotherEntity", mappedBy="manyToOne")
24+
*/
25+
private \Doctrine\Common\Collections\Collection $genericCollection
26+
)
27+
{
28+
}
29+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php // lint >= 8.0
2+
3+
namespace PHPStan\Rules\Doctrine\ORM\Bug306;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
/**
8+
* @ORM\Entity()
9+
*/
10+
class MyBrokenEntity
11+
{
12+
13+
/**
14+
* @ORM\Id()
15+
* @ORM\GeneratedValue()
16+
* @ORM\Column(type="integer")
17+
* @var int|null
18+
*/
19+
private $id;
20+
21+
public function __construct(
22+
/**
23+
* @ORM\Column(type="string", nullable=true)
24+
*/
25+
private string $one,
26+
27+
/**
28+
* @ORM\Column(type="string", nullable=true)
29+
*/
30+
private ?string $two
31+
)
32+
{
33+
}
34+
}

0 commit comments

Comments
 (0)