Skip to content

Commit 683aa30

Browse files
Christian Bläulmglaman
authored andcommitted
Improved the types this entity extension works on
Also: - Added support for 4 certain special properties original, target_id entity and value. - Split the inline class into separate files for better maintainability. Remove the need for the Drupal autoloader to work This allows Travis' PHPStan CLI to check this extention.
1 parent 1e7c3b0 commit 683aa30

File tree

5 files changed

+191
-54
lines changed

5 files changed

+191
-54
lines changed

extension.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@ services:
3636
class: PHPStan\Type\ServiceDynamicReturnTypeExtension
3737
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]
3838
-
39-
class: PHPStan\Reflection\EntityFieldsViaMagic
39+
class: PHPStan\Reflection\EntityFieldsViaMagicReflectionExtension
4040
tags: [phpstan.broker.propertiesClassReflectionExtension]
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace PHPStan\Reflection;
4+
5+
use PHPStan\Type\ObjectType;
6+
use PHPStan\Type\Type;
7+
8+
/**
9+
* Allows field access via magic methods
10+
*
11+
* See \Drupal\Core\Entity\ContentEntityBase::__get and ::__set.
12+
*/
13+
class EntityFieldReflection implements PropertyReflection
14+
{
15+
16+
/** @var ClassReflection */
17+
private $declaringClass;
18+
19+
/** @var string */
20+
private $propertyName;
21+
22+
public function __construct(ClassReflection $declaringClass, string $propertyName)
23+
{
24+
$this->declaringClass = $declaringClass;
25+
$this->propertyName = $propertyName;
26+
}
27+
28+
public function getType(): Type
29+
{
30+
if ($this->propertyName == 'original') {
31+
// See Drupal\Core\Entity\EntityStorageBase::doPreSave
32+
return new ObjectType('Drupal\Core\Field\FieldItemListInterface');
33+
}
34+
35+
return new ObjectType('Drupal\Core\Field\FieldItemListInterface');
36+
}
37+
38+
public function getDeclaringClass(): ClassReflection
39+
{
40+
return $this->declaringClass;
41+
}
42+
43+
public function isStatic(): bool
44+
{
45+
return false;
46+
}
47+
48+
public function isPrivate(): bool
49+
{
50+
return false;
51+
}
52+
53+
public function isPublic(): bool
54+
{
55+
return true;
56+
}
57+
58+
public function isReadable(): bool
59+
{
60+
return true;
61+
}
62+
63+
public function isWritable(): bool
64+
{
65+
return true;
66+
}
67+
}

src/Reflection/EntityFieldsViaMagic.php

Lines changed: 0 additions & 53 deletions
This file was deleted.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace PHPStan\Reflection;
4+
5+
/**
6+
* Allows field access via magic methods
7+
*
8+
* See \Drupal\Core\Entity\ContentEntityBase::__get and ::__set.
9+
*/
10+
class EntityFieldsViaMagicReflectionExtension implements PropertiesClassReflectionExtension
11+
{
12+
13+
public function hasProperty(ClassReflection $classReflection, string $propertyName): bool
14+
{
15+
if ($classReflection->hasNativeProperty($propertyName)) {
16+
// Let other parts of PHPStan handle this.
17+
return false;
18+
}
19+
20+
$reflection = $classReflection->getNativeReflection();
21+
if ($reflection->implementsInterface('Drupal\Core\Entity\EntityInterface')) {
22+
return true;
23+
}
24+
if ($reflection->implementsInterface('Drupal\Core\Field\FieldItemListInterface')) {
25+
return FieldItemListPropertyReflection::canHandleProperty($propertyName);
26+
}
27+
28+
return false;
29+
}
30+
31+
public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection
32+
{
33+
$reflection = $classReflection->getNativeReflection();
34+
if ($reflection->implementsInterface('Drupal\Core\Entity\EntityInterface')) {
35+
return new EntityFieldReflection($classReflection, $propertyName);
36+
}
37+
if ($reflection->implementsInterface('Drupal\Core\Field\FieldItemListInterface')) {
38+
return new FieldItemListPropertyReflection($classReflection, $propertyName);
39+
}
40+
41+
throw new \LogicException($classReflection->getName() . "::$propertyName should be handled earlier.");
42+
}
43+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
namespace PHPStan\Reflection;
4+
5+
use PHPStan\Type\IntegerType;
6+
use PHPStan\Type\MixedType;
7+
use PHPStan\Type\ObjectType;
8+
use PHPStan\Type\Type;
9+
10+
/**
11+
* Allows field access via magic methods
12+
*
13+
* See \Drupal\Core\Field\FieldItemListInterface::__get and ::__set.
14+
*/
15+
class FieldItemListPropertyReflection implements PropertyReflection
16+
{
17+
18+
/** @var ClassReflection */
19+
private $declaringClass;
20+
21+
/** @var string */
22+
private $propertyName;
23+
24+
public function __construct(ClassReflection $declaringClass, string $propertyName)
25+
{
26+
$this->declaringClass = $declaringClass;
27+
$this->propertyName = $propertyName;
28+
}
29+
30+
public static function canHandleProperty(string $propertyName): bool
31+
{
32+
$names = ['entity', 'value', 'target_id'];
33+
return in_array($propertyName, $names, true);
34+
}
35+
36+
public function getType(): Type
37+
{
38+
if ($this->propertyName == 'entity') {
39+
// It was a EntityReferenceFieldItemList
40+
return new ObjectType('Drupal\Core\Entity\FieldableEntityInterface');
41+
}
42+
if ($this->propertyName == 'target_id') {
43+
// It was a EntityReferenceFieldItemList
44+
return new IntegerType();
45+
}
46+
if ($this->propertyName == 'value') {
47+
return new MixedType();
48+
}
49+
}
50+
51+
public function getDeclaringClass(): ClassReflection
52+
{
53+
return $this->declaringClass;
54+
}
55+
56+
public function isStatic(): bool
57+
{
58+
return false;
59+
}
60+
61+
public function isPrivate(): bool
62+
{
63+
return false;
64+
}
65+
66+
public function isPublic(): bool
67+
{
68+
return true;
69+
}
70+
71+
public function isReadable(): bool
72+
{
73+
return true;
74+
}
75+
76+
public function isWritable(): bool
77+
{
78+
return true;
79+
}
80+
}

0 commit comments

Comments
 (0)