From 1eecbdbe112c91f3e0f51f0a20249f6433581c8d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 29 Mar 2026 00:03:41 +0000 Subject: [PATCH 1/5] Fix phpstan/phpstan#11339: filter_input with FILTER_FORCE_ARRAY has incorrect return type - When FILTER_FORCE_ARRAY or FILTER_REQUIRE_ARRAY is used, input values can be arbitrarily nested arrays (e.g. from query strings like ?a[a][b][]=val), so the array value type must include array when input could be an array - Updated FilterFunctionReturnTypeHelper::getType() to union ArrayType into the value type when inputIsArray is not no - New regression test in tests/PHPStan/Analyser/nsrt/bug-11339.php - Updated existing test expectations in filterVar.php, filter-var.php, filter-input.php, and discussion-9134.php to reflect the corrected types --- .../Php/FilterFunctionReturnTypeHelper.php | 6 + tests/PHPStan/Analyser/nsrt/bug-11339.php | 26 ++ .../PHPStan/Analyser/nsrt/discussion-9134.php | 2 +- tests/PHPStan/Analyser/nsrt/filter-input.php | 4 +- tests/PHPStan/Analyser/nsrt/filter-var.php | 24 +- tests/PHPStan/Analyser/nsrt/filterVar.php | 302 +++++++++--------- 6 files changed, 198 insertions(+), 166 deletions(-) create mode 100644 tests/PHPStan/Analyser/nsrt/bug-11339.php diff --git a/src/Type/Php/FilterFunctionReturnTypeHelper.php b/src/Type/Php/FilterFunctionReturnTypeHelper.php index ee7169f71bb..14569a80956 100644 --- a/src/Type/Php/FilterFunctionReturnTypeHelper.php +++ b/src/Type/Php/FilterFunctionReturnTypeHelper.php @@ -198,6 +198,9 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T } if ($hasRequireArrayFlag->yes()) { + if (!$inputIsArray->no()) { + $type = TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); + } $type = new ArrayType($inputArrayKeyType ?? $mixedType, $type); if (!$inputIsArray->yes()) { $type = TypeCombinator::union($type, $defaultType); @@ -205,6 +208,9 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T } if ($hasRequireArrayFlag->no() && $hasForceArrayFlag->yes()) { + if (!$inputIsArray->no()) { + $type = TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); + } return new ArrayType($inputArrayKeyType ?? $mixedType, $type); } diff --git a/tests/PHPStan/Analyser/nsrt/bug-11339.php b/tests/PHPStan/Analyser/nsrt/bug-11339.php new file mode 100644 index 00000000000..6eee5fa7ada --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-11339.php @@ -0,0 +1,26 @@ +|null', $f); + +$g = filter_input(INPUT_GET, 'a', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY); +assertType('array|false|null', $g); + +$h = filter_input(INPUT_GET, 'a', FILTER_VALIDATE_INT, FILTER_FORCE_ARRAY); +assertType('array|null', $h); + +$i = filter_input(INPUT_GET, 'a', FILTER_VALIDATE_INT, FILTER_REQUIRE_ARRAY); +assertType('array|false|null', $i); + +// filter_var with known scalar should not include array in value type +$j = filter_var('foo', FILTER_DEFAULT, FILTER_FORCE_ARRAY); +assertType("array<'foo'>", $j); + +$k = filter_var('foo', FILTER_VALIDATE_INT, FILTER_FORCE_ARRAY); +assertType('array', $k); diff --git a/tests/PHPStan/Analyser/nsrt/discussion-9134.php b/tests/PHPStan/Analyser/nsrt/discussion-9134.php index c431d86ec6f..df66c48477f 100644 --- a/tests/PHPStan/Analyser/nsrt/discussion-9134.php +++ b/tests/PHPStan/Analyser/nsrt/discussion-9134.php @@ -6,7 +6,7 @@ $var = $_GET["data"]; $res = filter_var($var, FILTER_VALIDATE_INT, FILTER_REQUIRE_ARRAY); -assertType('array|false', $res); +assertType('array|false', $res); if (is_array($res) === false) { throw new \RuntimeException(); } diff --git a/tests/PHPStan/Analyser/nsrt/filter-input.php b/tests/PHPStan/Analyser/nsrt/filter-input.php index 466862d85bd..da8cd9df0bf 100644 --- a/tests/PHPStan/Analyser/nsrt/filter-input.php +++ b/tests/PHPStan/Analyser/nsrt/filter-input.php @@ -34,8 +34,8 @@ public function doFoo(string $foo): void assertType('int|false|null', filter_input(INPUT_GET, 'foo', FILTER_VALIDATE_INT)); assertType('int|false|null', filter_input(INPUT_GET, 'foo', FILTER_VALIDATE_INT, ['flags' => FILTER_NULL_ON_FAILURE])); assertType("'invalid'|int|null", filter_input(INPUT_GET, 'foo', FILTER_VALIDATE_INT, ['options' => ['default' => 'invalid']])); - assertType('array|null', filter_input(INPUT_GET, 'foo', FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY])); - assertType('array|false', filter_input(INPUT_GET, 'foo', FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array|null', filter_input(INPUT_GET, 'foo', FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY])); + assertType('array|false', filter_input(INPUT_GET, 'foo', FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('0|int<17, 19>|null', filter_input(INPUT_GET, 'foo', FILTER_VALIDATE_INT, ['options' => ['default' => 0, 'min_range' => 17, 'max_range' => 19]])); } diff --git a/tests/PHPStan/Analyser/nsrt/filter-var.php b/tests/PHPStan/Analyser/nsrt/filter-var.php index 34d23f9c8fd..e5bb48e4179 100644 --- a/tests/PHPStan/Analyser/nsrt/filter-var.php +++ b/tests/PHPStan/Analyser/nsrt/filter-var.php @@ -23,28 +23,28 @@ public function doFoo($mixed, array $stringMixedMap): void assertType('null', filter_var(17, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('false', filter_var('foo', FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY])); assertType('null', filter_var('foo', FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); - assertType('array|false', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY])); - assertType('array|null', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); - assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY])); - assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array|false', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY])); + assertType('array|null', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY])); + assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('array<17>', filter_var(17, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY])); assertType('array<17>', filter_var(17, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('array', filter_var('foo', FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY])); assertType('array', filter_var('foo', FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); - assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('false', filter_var(17, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); assertType('null', filter_var(17, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('false', filter_var('foo', FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); assertType('null', filter_var('foo', FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); - assertType('array|false', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); - assertType('array|null', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); - assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); - assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array|false', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); + assertType('array|null', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); + assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('0|int<17, 19>', filter_var($mixed, FILTER_VALIDATE_INT, ['options' => ['default' => 0, 'min_range' => 17, 'max_range' => 19]])); diff --git a/tests/PHPStan/Analyser/nsrt/filterVar.php b/tests/PHPStan/Analyser/nsrt/filterVar.php index 8b189d755a6..74039410b70 100644 --- a/tests/PHPStan/Analyser/nsrt/filterVar.php +++ b/tests/PHPStan/Analyser/nsrt/filterVar.php @@ -19,14 +19,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_DEFAULT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_DEFAULT , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_DEFAULT , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_DEFAULT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_DEFAULT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_DEFAULT , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_DEFAULT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_DEFAULT , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_DEFAULT , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_DEFAULT , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_DEFAULT , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_DEFAULT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_DEFAULT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_DEFAULT , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_DEFAULT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_DEFAULT , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_DEFAULT , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_DEFAULT , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_DEFAULT , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('string|false', filter_var($mixed, FILTER_UNSAFE_RAW )); assertType('mixed', filter_var($mixed, FILTER_UNSAFE_RAW , $mixed)); assertType('mixed', filter_var($mixed, FILTER_UNSAFE_RAW , ["flags" => $mixed])); @@ -35,14 +35,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_UNSAFE_RAW , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_UNSAFE_RAW , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_UNSAFE_RAW , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_UNSAFE_RAW , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('string|false', filter_var($mixed, FILTER_SANITIZE_EMAIL )); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_EMAIL , $mixed)); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["flags" => $mixed])); @@ -51,14 +51,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_EMAIL , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('string|false', filter_var($mixed, FILTER_SANITIZE_ENCODED )); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_ENCODED , $mixed)); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["flags" => $mixed])); @@ -67,14 +67,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ENCODED , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('string|false', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT )); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , $mixed)); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["flags" => $mixed])); @@ -83,14 +83,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_FLOAT , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('string|false', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT )); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , $mixed)); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["flags" => $mixed])); @@ -99,14 +99,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_NUMBER_INT , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('string|false', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS )); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , $mixed)); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["flags" => $mixed])); @@ -115,14 +115,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_SPECIAL_CHARS , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('string|false', filter_var($mixed, FILTER_SANITIZE_STRING )); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_STRING , $mixed)); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_STRING , ["flags" => $mixed])); @@ -131,14 +131,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_SANITIZE_STRING , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_SANITIZE_STRING , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_SANITIZE_STRING , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_STRING , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('string|false', filter_var($mixed, FILTER_SANITIZE_URL )); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_URL , $mixed)); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_URL , ["flags" => $mixed])); @@ -147,14 +147,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_SANITIZE_URL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_SANITIZE_URL , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_SANITIZE_URL , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_URL , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('string|false', filter_var($mixed, FILTER_VALIDATE_REGEXP )); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_REGEXP , $mixed)); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["flags" => $mixed])); @@ -163,14 +163,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_REGEXP , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('string|false', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES )); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , $mixed)); assertType('mixed', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["flags" => $mixed])); @@ -179,14 +179,14 @@ function () { assertType('string|null', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('string|null', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|string', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_SANITIZE_ADD_SLASHES , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('non-falsy-string|false', filter_var($mixed, FILTER_VALIDATE_EMAIL )); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_EMAIL , $mixed)); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["flags" => $mixed])); @@ -195,14 +195,14 @@ function () { assertType('non-falsy-string|null', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('non-falsy-string|null', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|non-falsy-string', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_EMAIL , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('non-falsy-string|false', filter_var($mixed, FILTER_VALIDATE_IP )); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_IP , $mixed)); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_IP , ["flags" => $mixed])); @@ -211,14 +211,14 @@ function () { assertType('non-falsy-string|null', filter_var($mixed, FILTER_VALIDATE_IP , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('non-falsy-string|null', filter_var($mixed, FILTER_VALIDATE_IP , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|non-falsy-string', filter_var($mixed, FILTER_VALIDATE_IP , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_IP , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('non-falsy-string|false', filter_var($mixed, $filterIp )); assertType('mixed', filter_var($mixed, $filterIp , $mixed)); assertType('mixed', filter_var($mixed, $filterIp , ["flags" => $mixed])); @@ -227,14 +227,14 @@ function () { assertType('non-falsy-string|null', filter_var($mixed, $filterIp , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('non-falsy-string|null', filter_var($mixed, $filterIp , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|non-falsy-string', filter_var($mixed, $filterIp , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, $filterIp , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, $filterIp , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, $filterIp , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, $filterIp , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, $filterIp , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, $filterIp , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, $filterIp , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, $filterIp , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, $filterIp , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, $filterIp , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, $filterIp , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, $filterIp , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, $filterIp , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, $filterIp , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, $filterIp , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, $filterIp , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('non-falsy-string|false', filter_var($mixed, FILTER_VALIDATE_MAC )); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_MAC , $mixed)); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_MAC , ["flags" => $mixed])); @@ -243,14 +243,14 @@ function () { assertType('non-falsy-string|null', filter_var($mixed, FILTER_VALIDATE_MAC , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('non-falsy-string|null', filter_var($mixed, FILTER_VALIDATE_MAC , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|non-falsy-string', filter_var($mixed, FILTER_VALIDATE_MAC , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_MAC , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('non-falsy-string|false', filter_var($mixed, FILTER_VALIDATE_URL )); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_URL , $mixed)); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_URL , ["flags" => $mixed])); @@ -259,14 +259,14 @@ function () { assertType('non-falsy-string|null', filter_var($mixed, FILTER_VALIDATE_URL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('non-falsy-string|null', filter_var($mixed, FILTER_VALIDATE_URL , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|non-falsy-string', filter_var($mixed, FILTER_VALIDATE_URL , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_URL , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('int|false', filter_var($mixed, FILTER_VALIDATE_INT )); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_INT , $mixed)); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_INT , ["flags" => $mixed])); @@ -275,14 +275,14 @@ function () { assertType('int|null', filter_var($mixed, FILTER_VALIDATE_INT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('int|null', filter_var($mixed, FILTER_VALIDATE_INT , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|int', filter_var($mixed, FILTER_VALIDATE_INT , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_INT , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('float|false', filter_var($mixed, FILTER_VALIDATE_FLOAT )); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_FLOAT , $mixed)); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["flags" => $mixed])); @@ -291,14 +291,14 @@ function () { assertType('float|null', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4])); assertType('float|null', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["flags" => $nullFilter])); assertType('FilterVar\\Analyser|float', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["options" => ["default" => new Analyser]])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["flags" => FILTER_FORCE_ARRAY | FILTER_FLAG_IPV4])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_FLOAT , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('bool', filter_var($mixed, FILTER_VALIDATE_BOOLEAN )); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , $mixed)); assertType('mixed', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["flags" => $mixed])); @@ -308,13 +308,13 @@ function () { assertType('bool|null', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["flags" => $nullFilter])); assertType('bool|FilterVar\\Analyser', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["options" => ["default" => new Analyser]])); assertType('bool', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["options" => ["default" => true]])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , FILTER_FORCE_ARRAY)); - assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["flags" => $forceArrayFilter])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["options" => ["default" => false], "flags" => FILTER_FORCE_ARRAY])); - assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , FILTER_FORCE_ARRAY)); + assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["flags" => $forceArrayFilter])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["options" => ["default" => new Analyser], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["options" => ["default" => false], "flags" => FILTER_FORCE_ARRAY])); + assertType('array', filter_var($mixed, FILTER_VALIDATE_BOOLEAN , ["options" => ["default" => new Analyser], "flags" => FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY])); assertType('mixed', filter_var($mixed, $mixed)); assertType('string', filter_var($mixed, FILTER_SANITIZE_URL, ["options" => ["default" => "foo"]])); assertType('string|false', filter_var($mixed)); From 6eaa2ba5c77642e5ca73821c2c804738c268145f Mon Sep 17 00:00:00 2001 From: phpstan-bot Date: Sun, 29 Mar 2026 21:41:00 +0000 Subject: [PATCH 2/5] Improve precision of filter_var/filter_input return types for typed array inputs When the input array has a known value type (e.g. array, array>), use that type information instead of always adding generic array to the value type. - When value type is definitely not array (e.g. array): don't add array - When value type is definitely array (e.g. array>): recursively compute the precise nested filtered type - When value type is a union of scalar and array (e.g. array>): extract scalar/array parts and handle each precisely - For mixed/unknown value types: fall back to array as before Co-Authored-By: Claude Opus 4.6 --- .../Php/FilterFunctionReturnTypeHelper.php | 54 ++++++++++++++++--- tests/PHPStan/Analyser/nsrt/bug-11339.php | 36 +++++++++++++ 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/src/Type/Php/FilterFunctionReturnTypeHelper.php b/src/Type/Php/FilterFunctionReturnTypeHelper.php index 14569a80956..b11319c783c 100644 --- a/src/Type/Php/FilterFunctionReturnTypeHelper.php +++ b/src/Type/Php/FilterFunctionReturnTypeHelper.php @@ -165,9 +165,21 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T return $mixedType; } + $inputValueType = null; if ($inputIsArray->yes() && ($hasRequireArrayFlag->yes() || $hasForceArrayFlag->yes())) { $inputArrayKeyType = $inputType->getIterableKeyType(); $inputType = $inputType->getIterableValueType(); + $inputValueType = $inputType; + + // When the value type is a union of scalar and array types (e.g. int|array), + // only use the scalar part for scalar filtering - array parts are handled separately + // via recursive filtering in addNestedArrayType + if ($inputType->isArray()->maybe()) { + $scalarPart = TypeCombinator::remove($inputType, new ArrayType($mixedType, $mixedType)); + if (!$scalarPart instanceof NeverType) { + $inputType = $scalarPart; + } + } } if ($inputType->isScalar()->no() && $inputType->isNull()->no()) { @@ -198,9 +210,7 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T } if ($hasRequireArrayFlag->yes()) { - if (!$inputIsArray->no()) { - $type = TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); - } + $type = $this->addNestedArrayType($type, $inputValueType, $inputIsArray, $filterType, $flagsType, $mixedType); $type = new ArrayType($inputArrayKeyType ?? $mixedType, $type); if (!$inputIsArray->yes()) { $type = TypeCombinator::union($type, $defaultType); @@ -208,9 +218,7 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T } if ($hasRequireArrayFlag->no() && $hasForceArrayFlag->yes()) { - if (!$inputIsArray->no()) { - $type = TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); - } + $type = $this->addNestedArrayType($type, $inputValueType, $inputIsArray, $filterType, $flagsType, $mixedType); return new ArrayType($inputArrayKeyType ?? $mixedType, $type); } @@ -221,6 +229,40 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T return $type; } + private function addNestedArrayType(Type $type, ?Type $inputValueType, TrinaryLogic $inputIsArray, ?Type $filterType, ?Type $flagsType, MixedType $mixedType): Type + { + if ($inputValueType !== null) { + // Input was unwrapped - check if the value type could be an array + $valueTypeIsArray = $inputValueType->isArray(); + if ($valueTypeIsArray->yes()) { + // Value type is definitely an array - recursively compute precise nested type + // Replace $type entirely since the scalar filtering path produces incorrect + // results for array inputs (arrays are recursively filtered, not failed) + return $this->getType($inputValueType, $filterType, $flagsType); + } + if ($valueTypeIsArray->maybe()) { + // Value type is a union of scalar and array types (e.g. int|array) + // Try to extract the array part for precise recursive filtering + $inputArrayPart = TypeCombinator::intersect($inputValueType, new ArrayType($mixedType, $mixedType)); + if (!$inputArrayPart instanceof NeverType && !$inputArrayPart->getIterableValueType() instanceof MixedType) { + $nestedType = $this->getType($inputArrayPart, $filterType, $flagsType); + return TypeCombinator::union($type, $nestedType); + } + // Fall back to generic array for mixed-like value types + return TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); + } + // Value type is definitely not an array - don't add array to type + return $type; + } + + // No unwrap happened (input is maybe-array, e.g. from filter_input with mixed) + if (!$inputIsArray->no()) { + return TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); + } + + return $type; + } + /** * @return array */ diff --git a/tests/PHPStan/Analyser/nsrt/bug-11339.php b/tests/PHPStan/Analyser/nsrt/bug-11339.php index 6eee5fa7ada..e1b53285844 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-11339.php +++ b/tests/PHPStan/Analyser/nsrt/bug-11339.php @@ -24,3 +24,39 @@ $k = filter_var('foo', FILTER_VALIDATE_INT, FILTER_FORCE_ARRAY); assertType('array', $k); + +/** + * @param array $arrayOfInt + * @param array> $arrayOfArrayOfInt + * @param array> $arrayOfIntOrArrayOfInt + */ +function typedArrayInputs(array $arrayOfInt, array $arrayOfArrayOfInt, array $arrayOfIntOrArrayOfInt): void +{ + // array - values are ints, not arrays, so no array in value type + $l = filter_var($arrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY]); + assertType('array', $l); + + $m = filter_var($arrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE]); + assertType('array', $m); + + // array> - values are arrays, recursively filtered + $n = filter_var($arrayOfArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY]); + assertType('array>', $n); + + $o = filter_var($arrayOfArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE]); + assertType('array>', $o); + + // array> - mixed values, both scalar and array possible + $p = filter_var($arrayOfIntOrArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY]); + assertType('array|int>', $p); + + $q = filter_var($arrayOfIntOrArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE]); + assertType('array|int>', $q); + + // FORCE_ARRAY with typed arrays + $r = filter_var($arrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY]); + assertType('array', $r); + + $s = filter_var($arrayOfArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY]); + assertType('array>', $s); +} From 9d9f614e651f4bf121a9660e833ac063eb44dfbd Mon Sep 17 00:00:00 2001 From: phpstan-bot Date: Sun, 29 Mar 2026 22:08:55 +0000 Subject: [PATCH 3/5] Simplify nested array handling using TypeTraverser::map Replace the manual addNestedArrayType method with TypeTraverser::map to recursively filter each component of the array value type. Extract filterScalarType method for cleaner separation of scalar filtering logic from array wrapping logic. Co-Authored-By: Claude Opus 4.6 --- .../Php/FilterFunctionReturnTypeHelper.php | 113 ++++++++---------- 1 file changed, 51 insertions(+), 62 deletions(-) diff --git a/src/Type/Php/FilterFunctionReturnTypeHelper.php b/src/Type/Php/FilterFunctionReturnTypeHelper.php index b11319c783c..5cf31a1b5f2 100644 --- a/src/Type/Php/FilterFunctionReturnTypeHelper.php +++ b/src/Type/Php/FilterFunctionReturnTypeHelper.php @@ -27,6 +27,7 @@ use PHPStan\Type\StringType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; +use PHPStan\Type\TypeTraverser; use PHPStan\Type\UnionType; use function array_key_exists; use function array_merge; @@ -165,23 +166,62 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T return $mixedType; } - $inputValueType = null; + // When input is definitely an array with REQUIRE/FORCE_ARRAY, + // use TypeTraverser to recursively filter each component of the value type if ($inputIsArray->yes() && ($hasRequireArrayFlag->yes() || $hasForceArrayFlag->yes())) { $inputArrayKeyType = $inputType->getIterableKeyType(); - $inputType = $inputType->getIterableValueType(); - $inputValueType = $inputType; - - // When the value type is a union of scalar and array types (e.g. int|array), - // only use the scalar part for scalar filtering - array parts are handled separately - // via recursive filtering in addNestedArrayType - if ($inputType->isArray()->maybe()) { - $scalarPart = TypeCombinator::remove($inputType, new ArrayType($mixedType, $mixedType)); - if (!$scalarPart instanceof NeverType) { - $inputType = $scalarPart; + $inputValueType = $inputType->getIterableValueType(); + + $filteredValueType = TypeTraverser::map($inputValueType, function (Type $type, callable $traverse) use ($filterType, $flagsType, $filterValue, $defaultType, $mixedType, $hasOptions, $options): Type { + if ($type instanceof UnionType || $type instanceof IntersectionType) { + return $traverse($type); + } + if ($type->isArray()->yes()) { + return $this->getType($type, $filterType, $flagsType); } + $scalarResult = $this->filterScalarType($type, $filterValue, $defaultType, $flagsType, $mixedType, $hasOptions, $options); + if ($type->isArray()->maybe()) { + return TypeCombinator::union($scalarResult, new ArrayType($mixedType, $mixedType)); + } + return $scalarResult; + }); + + return new ArrayType($inputArrayKeyType, $filteredValueType); + } + + $type = $this->filterScalarType($inputType, $filterValue, $defaultType, $flagsType, $mixedType, $hasOptions, $options); + + if ($hasRequireArrayFlag->yes()) { + if (!$inputIsArray->no()) { + $type = TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); + } + $type = new ArrayType($mixedType, $type); + if (!$inputIsArray->yes()) { + $type = TypeCombinator::union($type, $defaultType); } } + if ($hasRequireArrayFlag->no() && $hasForceArrayFlag->yes()) { + if (!$inputIsArray->no()) { + $type = TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); + } + return new ArrayType($mixedType, $type); + } + + if ($this->hasFlag('FILTER_THROW_ON_FAILURE', $flagsType)->yes()) { + $type = TypeCombinator::remove($type, $defaultType); + } + + return $type; + } + + /** + * Applies the filter to a scalar input type (no array wrapping). + * + * @param array $options + */ + private function filterScalarType(Type $inputType, int $filterValue, Type $defaultType, ?Type $flagsType, MixedType $mixedType, TrinaryLogic $hasOptions, array $options): Type + { if ($inputType->isScalar()->no() && $inputType->isNull()->no()) { $exactType = $defaultType; } else { @@ -209,57 +249,6 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T } } - if ($hasRequireArrayFlag->yes()) { - $type = $this->addNestedArrayType($type, $inputValueType, $inputIsArray, $filterType, $flagsType, $mixedType); - $type = new ArrayType($inputArrayKeyType ?? $mixedType, $type); - if (!$inputIsArray->yes()) { - $type = TypeCombinator::union($type, $defaultType); - } - } - - if ($hasRequireArrayFlag->no() && $hasForceArrayFlag->yes()) { - $type = $this->addNestedArrayType($type, $inputValueType, $inputIsArray, $filterType, $flagsType, $mixedType); - return new ArrayType($inputArrayKeyType ?? $mixedType, $type); - } - - if ($this->hasFlag('FILTER_THROW_ON_FAILURE', $flagsType)->yes()) { - $type = TypeCombinator::remove($type, $defaultType); - } - - return $type; - } - - private function addNestedArrayType(Type $type, ?Type $inputValueType, TrinaryLogic $inputIsArray, ?Type $filterType, ?Type $flagsType, MixedType $mixedType): Type - { - if ($inputValueType !== null) { - // Input was unwrapped - check if the value type could be an array - $valueTypeIsArray = $inputValueType->isArray(); - if ($valueTypeIsArray->yes()) { - // Value type is definitely an array - recursively compute precise nested type - // Replace $type entirely since the scalar filtering path produces incorrect - // results for array inputs (arrays are recursively filtered, not failed) - return $this->getType($inputValueType, $filterType, $flagsType); - } - if ($valueTypeIsArray->maybe()) { - // Value type is a union of scalar and array types (e.g. int|array) - // Try to extract the array part for precise recursive filtering - $inputArrayPart = TypeCombinator::intersect($inputValueType, new ArrayType($mixedType, $mixedType)); - if (!$inputArrayPart instanceof NeverType && !$inputArrayPart->getIterableValueType() instanceof MixedType) { - $nestedType = $this->getType($inputArrayPart, $filterType, $flagsType); - return TypeCombinator::union($type, $nestedType); - } - // Fall back to generic array for mixed-like value types - return TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); - } - // Value type is definitely not an array - don't add array to type - return $type; - } - - // No unwrap happened (input is maybe-array, e.g. from filter_input with mixed) - if (!$inputIsArray->no()) { - return TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); - } - return $type; } From 6568982fd2255c01de755c183981e568d63f857f Mon Sep 17 00:00:00 2001 From: phpstan-bot Date: Sun, 29 Mar 2026 22:45:19 +0000 Subject: [PATCH 4/5] Use TypeTraverser::map for nested array type in maybe-array input paths Replace conservative `array` with precise nested array type computation using TypeTraverser::map when input type carries array structure information (e.g., `int|array`). Co-Authored-By: Claude Opus 4.6 --- .../Php/FilterFunctionReturnTypeHelper.php | 26 ++++++++++++++-- tests/PHPStan/Analyser/nsrt/bug-11339.php | 30 +++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/Type/Php/FilterFunctionReturnTypeHelper.php b/src/Type/Php/FilterFunctionReturnTypeHelper.php index 5cf31a1b5f2..b978024f8e8 100644 --- a/src/Type/Php/FilterFunctionReturnTypeHelper.php +++ b/src/Type/Php/FilterFunctionReturnTypeHelper.php @@ -193,7 +193,8 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T if ($hasRequireArrayFlag->yes()) { if (!$inputIsArray->no()) { - $type = TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); + $nestedArrayType = $this->computeNestedArrayType($inputType, $filterType, $flagsType, $mixedType); + $type = TypeCombinator::union($type, $nestedArrayType); } $type = new ArrayType($mixedType, $type); if (!$inputIsArray->yes()) { @@ -203,7 +204,8 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T if ($hasRequireArrayFlag->no() && $hasForceArrayFlag->yes()) { if (!$inputIsArray->no()) { - $type = TypeCombinator::union($type, new ArrayType($mixedType, $mixedType)); + $nestedArrayType = $this->computeNestedArrayType($inputType, $filterType, $flagsType, $mixedType); + $type = TypeCombinator::union($type, $nestedArrayType); } return new ArrayType($mixedType, $type); } @@ -252,6 +254,26 @@ private function filterScalarType(Type $inputType, int $filterValue, Type $defau return $type; } + /** + * Computes the nested array type for the array portion of a maybe-array input. + * Uses TypeTraverser to extract array components and recursively filter them. + */ + private function computeNestedArrayType(Type $inputType, ?Type $filterType, ?Type $flagsType, MixedType $mixedType): Type + { + return TypeTraverser::map($inputType, function (Type $type, callable $traverse) use ($filterType, $flagsType, $mixedType): Type { + if ($type instanceof UnionType || $type instanceof IntersectionType) { + return $traverse($type); + } + if ($type->isArray()->yes()) { + return $this->getType($type, $filterType, $flagsType); + } + if ($type->isArray()->maybe()) { + return new ArrayType($mixedType, $mixedType); + } + return new NeverType(); + }); + } + /** * @return array */ diff --git a/tests/PHPStan/Analyser/nsrt/bug-11339.php b/tests/PHPStan/Analyser/nsrt/bug-11339.php index e1b53285844..f881f08d600 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-11339.php +++ b/tests/PHPStan/Analyser/nsrt/bug-11339.php @@ -60,3 +60,33 @@ function typedArrayInputs(array $arrayOfInt, array $arrayOfArrayOfInt, array $ar $s = filter_var($arrayOfArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY]); assertType('array>', $s); } + +/** + * Union-typed inputs (scalar | array) exercise the inputIsArray->maybe() path + * + * @param int|array $intOrArrayOfInt + * @param string|array $stringOrArrayOfString + */ +function unionTypedInputs(int|array $intOrArrayOfInt, string|array $stringOrArrayOfString): void +{ + // FORCE_ARRAY: scalar part filtered, array part recursively filtered + $a = filter_var($intOrArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY]); + assertType('array|int|false>', $a); + + $b = filter_var($stringOrArrayOfString, FILTER_DEFAULT, ['flags' => FILTER_FORCE_ARRAY]); + assertType('array|string|false>', $b); + + // REQUIRE_ARRAY: scalar input returns false, array input recursively filtered + $c = filter_var($intOrArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY]); + assertType('array|int|false>|false', $c); + + $d = filter_var($stringOrArrayOfString, FILTER_DEFAULT, ['flags' => FILTER_REQUIRE_ARRAY]); + assertType('array|string|false>|false', $d); + + // REQUIRE_ARRAY with NULL_ON_FAILURE + $e = filter_var($intOrArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE]); + assertType('array|int|null>|null', $e); + + $f = filter_var($stringOrArrayOfString, FILTER_DEFAULT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE]); + assertType('array|string|null>|null', $f); +} From da9a05fe14cae94607bc9ee32eb1543dec2b299b Mon Sep 17 00:00:00 2001 From: phpstan-bot Date: Sun, 29 Mar 2026 23:05:06 +0000 Subject: [PATCH 5/5] Unify TypeTraverser::map usages into single filterTypeComponents method Replaces the inline TypeTraverser::map and the separate computeNestedArrayType method with a single reusable filterTypeComponents method. This also simplifies the REQUIRE_ARRAY and FORCE_ARRAY code paths by using the unified method directly instead of filterScalarType + computeNestedArrayType + union. As a side effect, union-typed inputs now produce more precise types since each union member is filtered individually rather than the union being treated as a non-scalar whole. Co-Authored-By: Claude Opus 4.6 --- .../Php/FilterFunctionReturnTypeHelper.php | 61 +++++++------------ tests/PHPStan/Analyser/nsrt/bug-11339.php | 12 ++-- 2 files changed, 29 insertions(+), 44 deletions(-) diff --git a/src/Type/Php/FilterFunctionReturnTypeHelper.php b/src/Type/Php/FilterFunctionReturnTypeHelper.php index b978024f8e8..720168b23d1 100644 --- a/src/Type/Php/FilterFunctionReturnTypeHelper.php +++ b/src/Type/Php/FilterFunctionReturnTypeHelper.php @@ -166,50 +166,30 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T return $mixedType; } - // When input is definitely an array with REQUIRE/FORCE_ARRAY, - // use TypeTraverser to recursively filter each component of the value type if ($inputIsArray->yes() && ($hasRequireArrayFlag->yes() || $hasForceArrayFlag->yes())) { $inputArrayKeyType = $inputType->getIterableKeyType(); $inputValueType = $inputType->getIterableValueType(); - - $filteredValueType = TypeTraverser::map($inputValueType, function (Type $type, callable $traverse) use ($filterType, $flagsType, $filterValue, $defaultType, $mixedType, $hasOptions, $options): Type { - if ($type instanceof UnionType || $type instanceof IntersectionType) { - return $traverse($type); - } - if ($type->isArray()->yes()) { - return $this->getType($type, $filterType, $flagsType); - } - $scalarResult = $this->filterScalarType($type, $filterValue, $defaultType, $flagsType, $mixedType, $hasOptions, $options); - if ($type->isArray()->maybe()) { - return TypeCombinator::union($scalarResult, new ArrayType($mixedType, $mixedType)); - } - return $scalarResult; - }); + $filteredValueType = $this->filterTypeComponents($inputValueType, $filterType, $flagsType, $filterValue, $defaultType, $mixedType, $hasOptions, $options); return new ArrayType($inputArrayKeyType, $filteredValueType); } - $type = $this->filterScalarType($inputType, $filterValue, $defaultType, $flagsType, $mixedType, $hasOptions, $options); - if ($hasRequireArrayFlag->yes()) { - if (!$inputIsArray->no()) { - $nestedArrayType = $this->computeNestedArrayType($inputType, $filterType, $flagsType, $mixedType); - $type = TypeCombinator::union($type, $nestedArrayType); - } + $type = $this->filterTypeComponents($inputType, $filterType, $flagsType, $filterValue, $defaultType, $mixedType, $hasOptions, $options); $type = new ArrayType($mixedType, $type); if (!$inputIsArray->yes()) { $type = TypeCombinator::union($type, $defaultType); } + return $type; } - if ($hasRequireArrayFlag->no() && $hasForceArrayFlag->yes()) { - if (!$inputIsArray->no()) { - $nestedArrayType = $this->computeNestedArrayType($inputType, $filterType, $flagsType, $mixedType); - $type = TypeCombinator::union($type, $nestedArrayType); - } + if ($hasForceArrayFlag->yes()) { + $type = $this->filterTypeComponents($inputType, $filterType, $flagsType, $filterValue, $defaultType, $mixedType, $hasOptions, $options); return new ArrayType($mixedType, $type); } + $type = $this->filterScalarType($inputType, $filterValue, $defaultType, $flagsType, $mixedType, $hasOptions, $options); + if ($this->hasFlag('FILTER_THROW_ON_FAILURE', $flagsType)->yes()) { $type = TypeCombinator::remove($type, $defaultType); } @@ -255,22 +235,27 @@ private function filterScalarType(Type $inputType, int $filterValue, Type $defau } /** - * Computes the nested array type for the array portion of a maybe-array input. - * Uses TypeTraverser to extract array components and recursively filter them. + * Recursively filters each component of a type that may contain arrays. + * Array components are recursively filtered via getType(), scalar components + * are filtered via filterScalarType(), and maybe-array components produce + * a union of both. + * + * @param array $options */ - private function computeNestedArrayType(Type $inputType, ?Type $filterType, ?Type $flagsType, MixedType $mixedType): Type + private function filterTypeComponents(Type $type, ?Type $filterType, ?Type $flagsType, int $filterValue, Type $defaultType, MixedType $mixedType, TrinaryLogic $hasOptions, array $options): Type { - return TypeTraverser::map($inputType, function (Type $type, callable $traverse) use ($filterType, $flagsType, $mixedType): Type { - if ($type instanceof UnionType || $type instanceof IntersectionType) { - return $traverse($type); + return TypeTraverser::map($type, function (Type $innerType, callable $traverse) use ($filterType, $flagsType, $filterValue, $defaultType, $mixedType, $hasOptions, $options): Type { + if ($innerType instanceof UnionType || $innerType instanceof IntersectionType) { + return $traverse($innerType); } - if ($type->isArray()->yes()) { - return $this->getType($type, $filterType, $flagsType); + if ($innerType->isArray()->yes()) { + return $this->getType($innerType, $filterType, $flagsType); } - if ($type->isArray()->maybe()) { - return new ArrayType($mixedType, $mixedType); + $scalarResult = $this->filterScalarType($innerType, $filterValue, $defaultType, $flagsType, $mixedType, $hasOptions, $options); + if ($innerType->isArray()->maybe()) { + return TypeCombinator::union($scalarResult, new ArrayType($mixedType, $mixedType)); } - return new NeverType(); + return $scalarResult; }); } diff --git a/tests/PHPStan/Analyser/nsrt/bug-11339.php b/tests/PHPStan/Analyser/nsrt/bug-11339.php index f881f08d600..07beafcb2f3 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-11339.php +++ b/tests/PHPStan/Analyser/nsrt/bug-11339.php @@ -71,22 +71,22 @@ function unionTypedInputs(int|array $intOrArrayOfInt, string|array $stringOrArra { // FORCE_ARRAY: scalar part filtered, array part recursively filtered $a = filter_var($intOrArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY]); - assertType('array|int|false>', $a); + assertType('array|int>', $a); $b = filter_var($stringOrArrayOfString, FILTER_DEFAULT, ['flags' => FILTER_FORCE_ARRAY]); - assertType('array|string|false>', $b); + assertType('array|string>', $b); // REQUIRE_ARRAY: scalar input returns false, array input recursively filtered $c = filter_var($intOrArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY]); - assertType('array|int|false>|false', $c); + assertType('array|int>|false', $c); $d = filter_var($stringOrArrayOfString, FILTER_DEFAULT, ['flags' => FILTER_REQUIRE_ARRAY]); - assertType('array|string|false>|false', $d); + assertType('array|string>|false', $d); // REQUIRE_ARRAY with NULL_ON_FAILURE $e = filter_var($intOrArrayOfInt, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE]); - assertType('array|int|null>|null', $e); + assertType('array|int>|null', $e); $f = filter_var($stringOrArrayOfString, FILTER_DEFAULT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE]); - assertType('array|string|null>|null', $f); + assertType('array|string>|null', $f); }