Skip to content

Commit 127b18b

Browse files
committed
fix: Improve Yii2 integration component property handling.
1 parent 1700d59 commit 127b18b

10 files changed

+58
-57
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Bug #22: Make `$configPath` optional in constructor `ServiceMap` class and update docs `README.md` (@terabytesoftw)
66
- Bug #23: Update the path to `Yii.php` in the `stubFiles` configuration for correct referencing (@terabytesoftw)
7+
- Bug #24: Improve `Yii2` integration component property handling.
78

89
## 0.2.1 June 03, 2025
910

README.md

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -126,21 +126,7 @@ includes:
126126
- vendor/yii2-extensions/phpstan/extension.neon
127127
128128
parameters:
129-
level: 8
130-
131-
paths:
132-
- src
133-
- controllers
134-
- models
135-
- widgets
136-
137-
excludePaths:
138-
- src/legacy
139-
- tests/_support
140-
- vendor
141-
142129
bootstrapFiles:
143-
- config/bootstrap.php
144130
- tests/bootstrap.php
145131
146132
# Complete dynamic constants list (extension defaults + custom)
@@ -151,7 +137,20 @@ parameters:
151137
- YII_ENV_PROD
152138
- YII_ENV_TEST
153139
- APP_VERSION
154-
- MAINTENANCE_MODE
140+
- MAINTENANCE_MODE
141+
142+
level: 8
143+
144+
paths:
145+
- src
146+
- controllers
147+
- models
148+
- widgets
149+
150+
excludePaths:
151+
- src/legacy
152+
- tests/_support
153+
- vendor
155154
156155
yii2:
157156
config_path: %currentWorkingDirectory%/config/web.php

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
},
3232
"extra": {
3333
"branch-alias": {
34-
"dev-main": "0.1-dev"
34+
"dev-main": "0.2.x-dev"
3535
}
3636
},
3737
"config": {

extension.neon

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ parameters:
99
yii2:
1010
config_path: ''
1111

12-
stubFiles:
13-
- stubs/BaseYii.stub
14-
- %currentWorkingDirectory%/vendor/yiisoft/yii2/Yii.php
15-
1612
parametersSchema:
1713
yii2: structure(
1814
[

phpstan.neon

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ includes:
55
- phar://phpstan.phar/conf/bleedingEdge.neon
66

77
parameters:
8+
bootstrapFiles:
9+
- tests/bootstrap.php
10+
811
ignoreErrors:
912
- '#Calling PHPStan\\Reflection\\Annotations\\AnnotationsPropertiesClassReflectionExtension\:\:(has|get)Property\(\) is not covered.+#'
1013
- '#Creating new PHPStan\\Reflection\\Dummy\\DummyPropertyReflection is not covered.+#'
@@ -13,9 +16,3 @@ parameters:
1316

1417
paths:
1518
- src
16-
17-
scanFiles:
18-
- vendor/yiisoft/yii2/Yii.php
19-
20-
yii2:
21-
config_path: tests/fixture/yii-config-valid.php

src/reflection/ApplicationPropertiesClassReflectionExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public function getProperty(ClassReflection $classReflection, string $propertyNa
9494
return new ComponentPropertyReflection(
9595
new DummyPropertyReflection($propertyName),
9696
new ObjectType($componentClass),
97+
$classReflection,
9798
);
9899
}
99100

src/reflection/ComponentPropertyReflection.php

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,14 @@ final class ComponentPropertyReflection implements PropertyReflection
3838
* Creates a new instance of the {@see ComponentPropertyReflection} class.
3939
*
4040
* @param PropertyReflection $fallbackProperty Fallback property reflection instance for delegation.
41-
* @param Type $type Actual type of the dynamic component as resolved by the service map.
41+
* @param Type $type Type of the dynamic component as resolved by the service map or dependency injection.
42+
* @param ClassReflection $declaringClass Class reflection of the class declaring the dynamic property.
4243
*/
43-
public function __construct(private readonly PropertyReflection $fallbackProperty, private readonly Type $type) {}
44+
public function __construct(
45+
private readonly PropertyReflection $fallbackProperty,
46+
private readonly Type $type,
47+
private readonly ClassReflection $declaringClass,
48+
) {}
4449

4550
/**
4651
* Determines whether the type of the dynamic Yii application component property can change after assignment.
@@ -71,7 +76,7 @@ public function canChangeTypeAfterAssignment(): bool
7176
*/
7277
public function getDeclaringClass(): ClassReflection
7378
{
74-
return $this->fallbackProperty->getDeclaringClass();
79+
return $this->declaringClass;
7580
}
7681

7782
/**
@@ -99,11 +104,17 @@ public function getDeprecatedDescription(): string|null
99104
* This method allows static analysis tools and IDEs to display inline documentation for dynamic application
100105
* components, supporting accurate code completion, type checking, and developer guidance.
101106
*
102-
* @return string|null PHPDoc comment string if available, or `null` if no documentation is set.
107+
* @return string PHPDoc comment string for the property, or an empty string if no comment is set.
103108
*/
104-
public function getDocComment(): string|null
109+
public function getDocComment(): string
105110
{
106-
return $this->fallbackProperty->getDocComment();
111+
$componentTypeName = $this->type->describe(\PHPStan\Type\VerbosityLevel::typeOnly());
112+
113+
return <<<PHPDOC
114+
/**
115+
* @var {$componentTypeName}
116+
*/
117+
PHPDOC;
107118
}
108119

109120
/**
@@ -119,7 +130,7 @@ public function getDocComment(): string|null
119130
*/
120131
public function getReadableType(): Type
121132
{
122-
return $this->fallbackProperty->getReadableType();
133+
return $this->type;
123134
}
124135

125136
/**
@@ -151,7 +162,7 @@ public function getType(): Type
151162
*/
152163
public function getWritableType(): Type
153164
{
154-
return $this->fallbackProperty->getWritableType();
165+
return $this->type;
155166
}
156167

157168
/**
@@ -167,7 +178,7 @@ public function getWritableType(): Type
167178
*/
168179
public function isDeprecated(): TrinaryLogic
169180
{
170-
return $this->fallbackProperty->isDeprecated();
181+
return TrinaryLogic::createNo();
171182
}
172183

173184
/**
@@ -183,7 +194,7 @@ public function isDeprecated(): TrinaryLogic
183194
*/
184195
public function isInternal(): TrinaryLogic
185196
{
186-
return $this->fallbackProperty->isInternal();
197+
return TrinaryLogic::createNo();
187198
}
188199

189200
/**

src/reflection/UserPropertiesClassReflectionExtension.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
};
1313
use PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension;
1414
use PHPStan\Reflection\Dummy\DummyPropertyReflection;
15-
use PHPStan\Type\MixedType;
15+
use PHPStan\Type\ObjectType;
1616
use yii\web\User;
17+
use yii2\extensions\phpstan\ServiceMap;
1718

1819
/**
1920
* Provides property reflection for a Yii user component in PHPStan analysis.
@@ -49,7 +50,10 @@ final class UserPropertiesClassReflectionExtension implements PropertiesClassRef
4950
* @param AnnotationsPropertiesClassReflectionExtension $annotationsProperties Extension for handling
5051
* annotation-based properties.
5152
*/
52-
public function __construct(private readonly AnnotationsPropertiesClassReflectionExtension $annotationsProperties) {}
53+
public function __construct(
54+
private readonly AnnotationsPropertiesClassReflectionExtension $annotationsProperties,
55+
private readonly ServiceMap $serviceMap,
56+
) {}
5357

5458
/**
5559
* Retrieves the property reflection for a given property on the Yii user component.
@@ -69,8 +73,15 @@ public function __construct(private readonly AnnotationsPropertiesClassReflectio
6973
*/
7074
public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection
7175
{
72-
if ($propertyName === 'identity') {
73-
return new ComponentPropertyReflection(new DummyPropertyReflection($propertyName), new MixedType());
76+
if (
77+
$propertyName === 'identity' &&
78+
($componentClass = $this->serviceMap->getComponentClassById($propertyName)) !== null
79+
) {
80+
return new ComponentPropertyReflection(
81+
new DummyPropertyReflection($propertyName),
82+
new ObjectType($componentClass),
83+
$classReflection,
84+
);
7485
}
7586

7687
if ($classReflection->hasNativeProperty($propertyName)) {

stubs/BaseYii.stub

Lines changed: 0 additions & 15 deletions
This file was deleted.

tests/bootstrap.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
define('YII_ENV', 'test');
1010

1111
// require composer autoloader if available
12-
require(__DIR__ . '/../vendor/autoload.php');
13-
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
12+
require(dirname(__DIR__) . '/vendor/autoload.php');
13+
require(dirname(__DIR__) . '/vendor/yiisoft/yii2/Yii.php');

0 commit comments

Comments
 (0)