/
PropertiesExtension.php
96 lines (76 loc) · 2.57 KB
/
PropertiesExtension.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Doctrine\ORM;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\Rules\Properties\ReadWritePropertiesExtension;
use PHPStan\Type\Doctrine\ObjectMetadataResolver;
use Throwable;
use function in_array;
class PropertiesExtension implements ReadWritePropertiesExtension
{
/** @var ObjectMetadataResolver */
private $objectMetadataResolver;
public function __construct(ObjectMetadataResolver $objectMetadataResolver)
{
$this->objectMetadataResolver = $objectMetadataResolver;
}
public function isAlwaysRead(PropertyReflection $property, string $propertyName): bool
{
$className = $property->getDeclaringClass()->getName();
$metadata = $this->objectMetadataResolver->getClassMetadata($className);
if ($metadata === null) {
return false;
}
return $metadata->hasField($propertyName) || $metadata->hasAssociation($propertyName);
}
public function isAlwaysWritten(PropertyReflection $property, string $propertyName): bool
{
$declaringClass = $property->getDeclaringClass();
$className = $declaringClass->getName();
$metadata = $this->objectMetadataResolver->getClassMetadata($className);
if ($metadata === null) {
return false;
}
if (!$metadata->hasField($propertyName) && !$metadata->hasAssociation($propertyName)) {
return false;
}
if ($metadata->isReadOnly && !$declaringClass->hasConstructor()) {
return true;
}
if ($metadata->versionField === $propertyName) {
return true;
}
return $this->isGeneratedIdentifier($metadata, $propertyName);
}
public function isInitialized(PropertyReflection $property, string $propertyName): bool
{
$declaringClass = $property->getDeclaringClass();
$className = $declaringClass->getName();
$metadata = $this->objectMetadataResolver->getClassMetadata($className);
if ($metadata === null) {
return false;
}
if (!$metadata->hasField($propertyName) && !$metadata->hasAssociation($propertyName)) {
return false;
}
if ($this->isGeneratedIdentifier($metadata, $propertyName)) {
return true;
}
return $metadata->isReadOnly && !$declaringClass->hasConstructor();
}
private function isGeneratedIdentifier(ClassMetadataInfo $metadata, string $propertyName): bool
{
if ($metadata->isIdentifierNatural()) {
return false;
}
try {
return in_array($propertyName, $metadata->getIdentifierFieldNames(), true);
} catch (Throwable $e) {
$mappingException = 'Doctrine\ORM\Mapping\MappingException';
if (!$e instanceof $mappingException) {
throw $e;
}
return false;
}
}
}