From c17b58e2e37f34030e12d591493acfcc739f51a6 Mon Sep 17 00:00:00 2001 From: Martin Herndl Date: Tue, 27 Dec 2022 17:03:36 +0100 Subject: [PATCH] Support `float` -> `int` and `bool|float|int|null` -> `string` cast via `filter_var()` --- src/Type/Php/FilterVarDynamicReturnTypeExtension.php | 8 ++++++++ .../data/filter-var-returns-non-empty-string.php | 5 ++++- tests/PHPStan/Analyser/data/filter-var.php | 9 +++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Type/Php/FilterVarDynamicReturnTypeExtension.php b/src/Type/Php/FilterVarDynamicReturnTypeExtension.php index 7c4dab9c7ee..ecb305bf465 100644 --- a/src/Type/Php/FilterVarDynamicReturnTypeExtension.php +++ b/src/Type/Php/FilterVarDynamicReturnTypeExtension.php @@ -231,6 +231,14 @@ private function determineExactType(Type $in, int $filterValue, Type $defaultTyp return $in->toFloat(); } + if ($filterValue === $this->getConstant('FILTER_VALIDATE_INT') && $in->isFloat()->yes()) { + return $in->toInteger(); + } + + if ($filterValue === $this->getConstant('FILTER_DEFAULT') && ($in->isBoolean()->yes() || $in->isFloat()->yes() || $in->isInteger()->yes() || $in->isNull()->yes())) { + return $in->toString(); + } + return null; } diff --git a/tests/PHPStan/Analyser/data/filter-var-returns-non-empty-string.php b/tests/PHPStan/Analyser/data/filter-var-returns-non-empty-string.php index 26965000cfe..635b2f9368e 100644 --- a/tests/PHPStan/Analyser/data/filter-var-returns-non-empty-string.php +++ b/tests/PHPStan/Analyser/data/filter-var-returns-non-empty-string.php @@ -82,7 +82,10 @@ public function run(string $str, int $int, int $positive_int, int $negative_int) assertType('9', $return); $return = filter_var(1.0, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 9]]); - assertType('int<1, 9>|false', $return); + assertType('1', $return); + + $return = filter_var(11.0, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 9]]); + assertType('false', $return); $return = filter_var($str, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => $positive_int]]); assertType('int<1, max>|false', $return); diff --git a/tests/PHPStan/Analyser/data/filter-var.php b/tests/PHPStan/Analyser/data/filter-var.php index ac35a5df947..9aa39ad6b97 100644 --- a/tests/PHPStan/Analyser/data/filter-var.php +++ b/tests/PHPStan/Analyser/data/filter-var.php @@ -26,7 +26,16 @@ public function intToInt(int $int, array $options): void public function constants(): void { assertType('array', filter_var(false, FILTER_VALIDATE_BOOLEAN, FILTER_FORCE_ARRAY | FILTER_NULL_ON_FAILURE)); + assertType('17', filter_var(17, FILTER_VALIDATE_INT)); + + assertType('17.0', filter_var(17, FILTER_VALIDATE_FLOAT)); + + assertType("'17'", filter_var(17)); + assertType("'17'", filter_var(17.0)); + assertType("'1'", filter_var(true)); + assertType("''", filter_var(false)); + assertType("''", filter_var(null)); } }