1313
1414namespace CodeIgniter \PHPStan \Type ;
1515
16+ use CodeIgniter \PHPStan \NodeVisitor \ModelReturnTypeTransformVisitor ;
17+ use PhpParser \Node \Expr ;
18+ use PhpParser \Node \Expr \MethodCall ;
1619use PHPStan \Analyser \Scope ;
1720use PHPStan \Reflection \ClassReflection ;
1821use PHPStan \Reflection \ReflectionProvider ;
@@ -33,8 +36,11 @@ final class ModelFetchedReturnTypeHelper
3336 * @var array<string, class-string<Type>>
3437 */
3538 private static array $ notStringFormattedFields = [
36- 'success ' => BooleanType::class,
37- 'user_id ' => IntegerType::class,
39+ 'active ' => BooleanType::class,
40+ 'force_reset ' => BooleanType::class,
41+ 'id ' => IntegerType::class,
42+ 'success ' => BooleanType::class,
43+ 'user_id ' => IntegerType::class,
3844 ];
3945
4046 /**
@@ -66,9 +72,15 @@ public function __construct(
6672 }
6773 }
6874
69- public function getFetchedReturnType (ClassReflection $ classReflection , Scope $ scope ): Type
75+ public function getFetchedReturnType (ClassReflection $ classReflection , ? MethodCall $ methodCall , Scope $ scope ): Type
7076 {
71- $ returnType = $ this ->getNativeStringPropertyValue ($ classReflection , $ scope , 'returnType ' );
77+ $ returnType = $ this ->getNativeStringPropertyValue ($ classReflection , $ scope , ModelReturnTypeTransformVisitor::RETURN_TYPE );
78+
79+ if ($ methodCall !== null && $ methodCall ->hasAttribute (ModelReturnTypeTransformVisitor::RETURN_TYPE )) {
80+ /** @var Expr $returnExpr */
81+ $ returnExpr = $ methodCall ->getAttribute (ModelReturnTypeTransformVisitor::RETURN_TYPE );
82+ $ returnType = $ this ->getStringValueFromExpr ($ returnExpr , $ scope );
83+ }
7284
7385 if ($ returnType === 'object ' ) {
7486 return new ObjectType (stdClass::class);
@@ -88,7 +100,9 @@ public function getFetchedReturnType(ClassReflection $classReflection, Scope $sc
88100 private function getArrayReturnType (ClassReflection $ classReflection , Scope $ scope ): Type
89101 {
90102 $ this ->fillDateFields ($ classReflection , $ scope );
91- $ fieldsTypes = $ this ->getNativePropertyType ($ classReflection , $ scope , 'allowedFields ' )->getConstantArrays ();
103+ $ fieldsTypes = $ scope ->getType (
104+ $ classReflection ->getNativeProperty ('allowedFields ' )->getNativeReflection ()->getDefaultValueExpression ()
105+ )->getConstantArrays ();
92106
93107 if ($ fieldsTypes === []) {
94108 return new ConstantArrayType ([], []);
@@ -131,20 +145,23 @@ private function fillDateFields(ClassReflection $classReflection, Scope $scope):
131145 }
132146 }
133147
134- private function getNativePropertyType (ClassReflection $ classReflection , Scope $ scope , string $ property ): Type
148+ private function getNativeStringPropertyValue (ClassReflection $ classReflection , Scope $ scope , string $ property ): string
135149 {
136150 if (! $ classReflection ->hasNativeProperty ($ property )) {
137151 throw new ShouldNotHappenException (sprintf ('Native property %s::$%s does not exist. ' , $ classReflection ->getDisplayName (), $ property ));
138152 }
139153
140- return $ scope ->getType ($ classReflection ->getNativeProperty ($ property )->getNativeReflection ()->getDefaultValueExpression ());
154+ return $ this ->getStringValueFromExpr (
155+ $ classReflection ->getNativeProperty ($ property )->getNativeReflection ()->getDefaultValueExpression (),
156+ $ scope
157+ );
141158 }
142159
143- private function getNativeStringPropertyValue ( ClassReflection $ classReflection , Scope $ scope, string $ property ): string
160+ private function getStringValueFromExpr ( Expr $ expr , Scope $ scope ): string
144161 {
145- $ propertyType = $ this -> getNativePropertyType ( $ classReflection , $ scope , $ property )->getConstantStrings ();
146- assert (count ($ propertyType ) === 1 );
162+ $ exprType = $ scope -> getType ( $ expr )->getConstantStrings ();
163+ assert (count ($ exprType ) === 1 );
147164
148- return current ($ propertyType )->getValue ();
165+ return current ($ exprType )->getValue ();
149166 }
150167}
0 commit comments