Skip to content

Commit fecdf4c

Browse files
authored
Merge pull request #268 from jacktonkin/allow-property-annotations-on-entity-classes
Respect @Property annotations on Entity classes
2 parents 650e728 + 34fe9f6 commit fecdf4c

File tree

5 files changed

+61
-3
lines changed

5 files changed

+61
-3
lines changed

src/Reflection/EntityFieldsViaMagicReflectionExtension.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ class EntityFieldsViaMagicReflectionExtension implements PropertiesClassReflecti
2020

2121
public function hasProperty(ClassReflection $classReflection, string $propertyName): bool
2222
{
23-
if ($classReflection->hasNativeProperty($propertyName)) {
23+
// @todo Have this run after PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension
24+
// We should not have to check for the property tags if we could get this to run after PHPStan's
25+
// existing annotation property reflection.
26+
if ($classReflection->hasNativeProperty($propertyName) || array_key_exists($propertyName, $classReflection->getPropertyTags())) {
2427
// Let other parts of PHPStan handle this.
2528
return false;
2629
}
@@ -57,8 +60,7 @@ public function getProperty(ClassReflection $classReflection, string $propertyNa
5760
protected static function classObjectIsSuperOfFieldItemList(\ReflectionClass $reflection) : TrinaryLogic
5861
{
5962
$classObject = new ObjectType($reflection->getName());
60-
$interfaceObject = self::getFieldItemListInterfaceObject();
61-
return $interfaceObject->isSuperTypeOf($classObject);
63+
return self::getFieldItemListInterfaceObject()->isSuperTypeOf($classObject);
6264
}
6365

6466
protected static function getFieldItemListInterfaceObject() : ObjectType

tests/fixtures/drupal/modules/phpstan_fixtures/src/Entity/ReflectionEntityTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
use Drupal\Core\Field\BaseFieldDefinition;
88
use Drupal\user\UserInterface;
99

10+
/**
11+
* @property \Drupal\Core\Field\EntityReferenceFieldItemListInterface $user_id
12+
*/
1013
final class ReflectionEntityTest extends ContentEntityBase {
1114

1215
public static function baseFieldDefinitions(EntityTypeInterface $entity_type)

tests/src/Reflection/EntityFieldsViaMagicReflectionExtensionTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Drupal\Core\Field\FieldItemListInterface;
77
use Drupal\entity_test\Entity\EntityTest;
88
use Drupal\module_installer_config_test\Entity\TestConfigType;
9+
use Drupal\phpstan_fixtures\Entity\ReflectionEntityTest;
910
use mglaman\PHPStanDrupal\Reflection\EntityFieldsViaMagicReflectionExtension;
1011
use mglaman\PHPStanDrupal\Tests\AdditionalConfigFilesTrait;
1112
use PHPStan\Testing\PHPStanTestCase;
@@ -53,6 +54,12 @@ public function dataHasProperty(): \Generator
5354
'foobar',
5455
false
5556
];
57+
yield 'annotated properties are skipped on content entities' => [
58+
// @phpstan-ignore-next-line
59+
ReflectionEntityTest::class,
60+
'user_id',
61+
false
62+
];
5663
// @todo really entity is only supported on EntityFieldItemList
5764
yield 'field item list: entity' => [
5865
\Drupal\Core\Field\FieldItemList::class,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace mglaman\PHPStanDrupal\Tests\Type;
6+
7+
use mglaman\PHPStanDrupal\Tests\AdditionalConfigFilesTrait;
8+
use PHPStan\Testing\TypeInferenceTestCase;
9+
10+
final class EntityPropertyTypeTest extends TypeInferenceTestCase
11+
{
12+
use AdditionalConfigFilesTrait;
13+
14+
public function dataFileAsserts(): iterable
15+
{
16+
yield from $this->gatherAssertTypes(__DIR__ . '/data/entity-properties.php');
17+
}
18+
19+
/**
20+
* @dataProvider dataFileAsserts
21+
* @param string $assertType
22+
* @param string $file
23+
* @param mixed ...$args
24+
*/
25+
public function testFileAsserts(
26+
string $assertType,
27+
string $file,
28+
...$args
29+
): void
30+
{
31+
$this->assertFileAsserts($assertType, $file, ...$args);
32+
}
33+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace DrupalEntity;
4+
5+
use Drupal\node\Entity\Node;
6+
use Drupal\phpstan_fixtures\Entity\ReflectionEntityTest;
7+
use function PHPStan\Testing\assertType;
8+
9+
$node = Node::create(['type' => 'page']);
10+
assertType('Drupal\Core\Field\FieldItemListInterface', $node->uid);
11+
12+
$entity = ReflectionEntityTest::create();
13+
assertType('Drupal\Core\Field\EntityReferenceFieldItemListInterface', $entity->user_id);

0 commit comments

Comments
 (0)