diff --git a/extension.neon b/extension.neon index 9f8ba2f..534451f 100644 --- a/extension.neon +++ b/extension.neon @@ -20,6 +20,9 @@ services: - class: Proget\PHPStan\Yii2\Type\ActiveRecordDynamicMethodReturnTypeExtension tags: [phpstan.broker.dynamicMethodReturnTypeExtension] + - + class: Proget\PHPStan\Yii2\Type\HeaderCollectionDynamicMethodReturnTypeExtension + tags: [phpstan.broker.dynamicMethodReturnTypeExtension] - class: Proget\PHPStan\Yii2\Type\ActiveRecordDynamicStaticMethodReturnTypeExtension tags: [phpstan.broker.dynamicStaticMethodReturnTypeExtension] diff --git a/src/Type/HeaderCollectionDynamicMethodReturnTypeExtension.php b/src/Type/HeaderCollectionDynamicMethodReturnTypeExtension.php new file mode 100644 index 0000000..8d9b5a9 --- /dev/null +++ b/src/Type/HeaderCollectionDynamicMethodReturnTypeExtension.php @@ -0,0 +1,55 @@ +getName() === 'get'; + } + + public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type + { + if (count($methodCall->args) < 3) { + // $first === true (the default) and the get-method returns something of type string + return new StringType(); + } + + $val = $methodCall->args[2]->value; + if ($val instanceof ConstFetch) { + $value = $val->name->parts[0]; + if ($value === 'true') { + // $first === true, therefore string + return new StringType(); + } + + if ($value === 'false') { + // $first === false, therefore string[] + return new ArrayType(new IntegerType(), new StringType()); + } + } + + // Unable to figure out value of third parameter $first, therefore it can be of either type + return new UnionType([new ArrayType(new IntegerType(), new StringType()), new StringType()]); + } +} diff --git a/tests/Yii/MyController.php b/tests/Yii/MyController.php index 621354e..4b7c000 100644 --- a/tests/Yii/MyController.php +++ b/tests/Yii/MyController.php @@ -49,5 +49,10 @@ public function actionMy(): void \Yii::createObject(static function (): \SplObjectStorage { return new \SplObjectStorage(); })->count(); + + (int)\Yii::$app->request->headers->get('Content-Length'); + (int)\Yii::$app->request->headers->get('Content-Length', 0, true); + $values = \Yii::$app->request->headers->get('X-Key', '', false); + reset($values); } }