Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 681d38e

Browse files
committedDec 26, 2022
Improve QueryResultDynamicReturnTypeExtension
1 parent f769796 commit 681d38e

File tree

2 files changed

+355
-18
lines changed

2 files changed

+355
-18
lines changed
 

‎src/Type/Doctrine/Query/QueryResultDynamicReturnTypeExtension.php

+28-9
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
use PHPStan\Type\IterableType;
1717
use PHPStan\Type\MixedType;
1818
use PHPStan\Type\NullType;
19+
use PHPStan\Type\ObjectWithoutClassType;
1920
use PHPStan\Type\Type;
2021
use PHPStan\Type\TypeCombinator;
22+
use PHPStan\Type\TypeTraverser;
2123
use PHPStan\Type\VoidType;
2224

2325
final class QueryResultDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
@@ -109,12 +111,20 @@ private function getMethodReturnTypeForHydrationMode(
109111
return $this->originalReturnType($methodReflection);
110112
}
111113

112-
if (!$this->isObjectHydrationMode($hydrationMode)) {
113-
// We support only HYDRATE_OBJECT. For other hydration modes, we
114-
// return the declared return type of the method.
114+
if (!$hydrationMode instanceof ConstantIntegerType) {
115115
return $this->originalReturnType($methodReflection);
116116
}
117117

118+
switch ($hydrationMode->getValue()) {
119+
case AbstractQuery::HYDRATE_OBJECT;
120+
break;
121+
case AbstractQuery::HYDRATE_ARRAY;
122+
$queryResultType = $this->getArrayHydratedReturnType($queryResultType);
123+
break;
124+
default:
125+
return $this->originalReturnType($methodReflection);
126+
}
127+
118128
switch ($methodReflection->getName()) {
119129
case 'getSingleResult':
120130
return $queryResultType;
@@ -133,13 +143,22 @@ private function getMethodReturnTypeForHydrationMode(
133143
}
134144
}
135145

136-
private function isObjectHydrationMode(Type $type): bool
146+
private function getArrayHydratedReturnType(Type $queryResultType): Type
137147
{
138-
if (!$type instanceof ConstantIntegerType) {
139-
return false;
140-
}
141-
142-
return $type->getValue() === AbstractQuery::HYDRATE_OBJECT;
148+
return TypeTraverser::map(
149+
$queryResultType,
150+
static function (Type $type, callable $traverse): Type {
151+
$isObject = (new ObjectWithoutClassType())->isSuperTypeOf($type);
152+
if ($isObject->yes()) {
153+
return new ArrayType(new MixedType(), new MixedType());
154+
}
155+
if ($isObject->maybe()) {
156+
return new MixedType();
157+
}
158+
159+
return $traverse($type);
160+
}
161+
);
143162
}
144163

145164
private function originalReturnType(MethodReflection $methodReflection): Type

0 commit comments

Comments
 (0)
Please sign in to comment.