Skip to content

Commit a98c804

Browse files
committed
Support for SmartObject magic properties
1 parent 10106fd commit a98c804

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"prefer-stable": true,
77
"require": {
88
"php": "~7.0",
9-
"phpstan/phpstan": "dev-dev#3ba62cbb49",
10-
"nette/utils": "~2.3.0"
9+
"phpstan/phpstan": "dev-dev#f85ba19e37",
10+
"nette/utils": "^2.3.0"
1111
},
1212
"autoload": {
1313
"psr-4": {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace PHPStan\Reflection\Nette;
4+
5+
use PHPStan\Reflection\ClassReflection;
6+
use PHPStan\Reflection\NetteObject\NetteObjectPropertyReflection;
7+
use PHPStan\Reflection\PropertiesClassReflectionExtension;
8+
use PHPStan\Reflection\PropertyReflection;
9+
10+
class SmartObjectPropertiesClassReflectionExtension implements PropertiesClassReflectionExtension
11+
{
12+
13+
public function hasProperty(ClassReflection $classReflection, string $propertyName): bool
14+
{
15+
$traitNames = $this->getTraitNames($classReflection->getNativeReflection());
16+
if (!in_array(\Nette\SmartObject::class, $traitNames, true)) {
17+
return false;
18+
}
19+
20+
$property = \Nette\Utils\ObjectMixin::getMagicProperty($classReflection->getName(), $propertyName);
21+
if ($property === null) {
22+
return false;
23+
}
24+
25+
$getterMethod = $this->getMethodByProperty($classReflection, $propertyName);
26+
if ($getterMethod === null) {
27+
return false;
28+
}
29+
30+
return $getterMethod->isPublic();
31+
}
32+
33+
private function getTraitNames(\ReflectionClass $class): array
34+
{
35+
$traitNames = $class->getTraitNames();
36+
while ($class->getParentClass() !== false) {
37+
$traitNames = array_values(array_unique(array_merge($traitNames, $class->getParentClass()->getTraitNames())));
38+
$class = $class->getParentClass();
39+
}
40+
41+
return $traitNames;
42+
}
43+
44+
/**
45+
* @param \PHPStan\Reflection\ClassReflection $classReflection
46+
* @param string $propertyName
47+
* @return \PHPStan\Reflection\MethodReflection|null
48+
*/
49+
private function getMethodByProperty(ClassReflection $classReflection, string $propertyName)
50+
{
51+
$getterMethodName = sprintf('get%s', ucfirst($propertyName));
52+
if (!$classReflection->hasMethod($getterMethodName)) {
53+
return null;
54+
}
55+
56+
return $classReflection->getMethod($getterMethodName);
57+
}
58+
59+
public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection
60+
{
61+
$getterMethod = $this->getMethodByProperty($classReflection, $propertyName);
62+
return new NetteObjectPropertyReflection($classReflection, $getterMethod->getReturnType());
63+
}
64+
65+
}

0 commit comments

Comments
 (0)