diff --git a/src/Type/QueryInterfaceDynamicReturnTypeExtension.php b/src/Type/QueryInterfaceDynamicReturnTypeExtension.php index e18ab79..2d90fe1 100644 --- a/src/Type/QueryInterfaceDynamicReturnTypeExtension.php +++ b/src/Type/QueryInterfaceDynamicReturnTypeExtension.php @@ -6,6 +6,7 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\ArrayType; +use PHPStan\Type\BooleanType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\DynamicMethodReturnTypeExtension; use PHPStan\Type\ErrorType; @@ -13,7 +14,9 @@ use PHPStan\Type\IntegerType; use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; +use PHPStan\Type\StringType; use PHPStan\Type\Type; +use PHPStan\Type\TypeCombinator; use SaschaEgerer\PhpstanTypo3\Helpers\Typo3ClassNamingUtilityTrait; use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult; use TYPO3\CMS\Extbase\Persistence\QueryInterface; @@ -45,7 +48,6 @@ public function getTypeFromMethodCall( $argument = $methodCall->getArgs()[0] ?? null; $classReflection = $scope->getClassReflection(); - $queryType = $scope->getType($methodCall->var); if ($queryType instanceof GenericObjectType) { $modelType = $queryType->getTypes(); @@ -64,15 +66,23 @@ public function getTypeFromMethodCall( } } + $returnType = new GenericObjectType(QueryResult::class, $modelType); + $rawReturnType = new ArrayType(new IntegerType(), new ArrayType(new StringType(), new MixedType())); + if ($argument !== null) { $argType = $scope->getType($argument->value); - if ($classReflection !== null && $argType instanceof ConstantBooleanType && $argType->getValue() === true) { - return new ArrayType(new IntegerType(), $modelType[0]); + if ($argType instanceof ConstantBooleanType) { + if ($argType->getValue() === true) { + // A static boolean value with "true" has been given + return $rawReturnType; + } + } elseif ($argType instanceof BooleanType) { + // A variable with a boolean value has been given but we don't know it's value + return TypeCombinator::union($rawReturnType, $returnType); } } - - return new GenericObjectType(QueryResult::class, $modelType); + return $returnType; } } diff --git a/stubs/QueryInterface.stub b/stubs/QueryInterface.stub index 96621ea..42ed331 100644 --- a/stubs/QueryInterface.stub +++ b/stubs/QueryInterface.stub @@ -6,12 +6,6 @@ namespace TYPO3\CMS\Extbase\Persistence; */ interface QueryInterface { - /** - * @param bool $returnRawQueryResult - * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array - */ - public function execute($returnRawQueryResult = false); - /** * @param mixed $constraint * @return \TYPO3\CMS\Extbase\Persistence\QueryInterface diff --git a/tests/Unit/Type/data/custom-query-type.php b/tests/Unit/Type/data/custom-query-type.php index 2131cd2..dc914c3 100644 --- a/tests/Unit/Type/data/custom-query-type.php +++ b/tests/Unit/Type/data/custom-query-type.php @@ -28,19 +28,31 @@ class SomeOtherModel extends AbstractEntity class MyModelRepository extends Repository { - public function findBySomething(): void + public function findBySomething(bool $booleanParameter = false): void { /** @var QueryInterface $query */ $query = $this->persistenceManager->createQueryForType(SomeOtherModel::class); $result = $query->execute(); assertType( - 'TYPO3\CMS\Extbase\Persistence\QueryInterface', - $query + 'TYPO3\CMS\Extbase\Persistence\Generic\QueryResult', + $result + ); + + $result = $query->execute(false); + assertType( + 'TYPO3\CMS\Extbase\Persistence\Generic\QueryResult', + $result + ); + + $result = $query->execute($booleanParameter); + assertType( + 'array>|TYPO3\CMS\Extbase\Persistence\Generic\QueryResult', + $result ); $rawResult = $query->execute(true); - assertType('array', $rawResult); + assertType('array>', $rawResult); $array = $result->toArray(); assertType('array', $array);