From bfb02864cba8c6f0657ec17c55821edb4e07cf7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=A4u=C3=9Fler?= Date: Tue, 21 Feb 2023 12:34:56 +0100 Subject: [PATCH] [BUGFIX] Include default value passed to `$request->getAttribute()` Whenever the `$request->getAttribute()` method is called, it is possible to provide a default value in case the given argument is null. Thus, the default value should be part of the return type. --- .../RequestDynamicReturnTypeExtension.php | 22 ++++++++++++++----- .../request-get-attribute-return-types.php | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Type/RequestDynamicReturnTypeExtension.php b/src/Type/RequestDynamicReturnTypeExtension.php index edc2be8..33a1988 100644 --- a/src/Type/RequestDynamicReturnTypeExtension.php +++ b/src/Type/RequestDynamicReturnTypeExtension.php @@ -48,16 +48,28 @@ public function getTypeFromMethodCall( ): Type { $argument = $methodCall->getArgs()[0] ?? null; + $defaultArgument = $methodCall->getArgs()[1] ?? null; - if ($argument === null || !($argument->value instanceof \PhpParser\Node\Scalar\String_)) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + if ($argument === null + || !($argument->value instanceof \PhpParser\Node\Scalar\String_) + || !isset($this->requestGetAttributeMapping[$argument->value->value]) + ) { + $type = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + + if ($defaultArgument === null) { + return $type; + } + + return TypeCombinator::union($type, $scope->getType($defaultArgument->value)); } - if (isset($this->requestGetAttributeMapping[$argument->value->value])) { - return TypeCombinator::addNull($this->typeStringResolver->resolve($this->requestGetAttributeMapping[$argument->value->value])); + $type = $this->typeStringResolver->resolve($this->requestGetAttributeMapping[$argument->value->value]); + + if ($defaultArgument === null) { + return TypeCombinator::addNull($type); } - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return TypeCombinator::union($type, $scope->getType($defaultArgument->value)); } public function isMethodSupported( diff --git a/tests/Unit/Type/data/request-get-attribute-return-types.php b/tests/Unit/Type/data/request-get-attribute-return-types.php index 8fff231..2847560 100644 --- a/tests/Unit/Type/data/request-get-attribute-return-types.php +++ b/tests/Unit/Type/data/request-get-attribute-return-types.php @@ -4,6 +4,7 @@ use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Http\NormalizedParams; +use TYPO3\CMS\Core\Site\Entity\NullSite; use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use function PHPStan\Testing\assertType; @@ -21,6 +22,7 @@ public function getAttributeTests(ServerRequestInterface $request): void ); assertType(SiteLanguage::class . '|null', $request->getAttribute('language')); assertType(Site::class . '|null', $request->getAttribute('site')); + assertType(NullSite::class . '|' . Site::class, $request->getAttribute('site', new NullSite())); assertType(NormalizedParams::class . '|null', $request->getAttribute('normalizedParams')); assertType('1|2|4|8|16|null', $request->getAttribute('applicationType')); assertType('FlowdGmbh\\MyProject\\Http\\MyAttribute|null', $request->getAttribute('myCustomAttribute'));