Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e83948c

Browse files
Add support for FILTER_NULL_ON_FAILURE flag
This works for all validates, but not sanitizes. For now this lacks support for bit masks, e.g.: `FILTER_FLAG_IPV4 | FILTER_NULL_ON_FAILURE`. The reason for this is that there is also a `FILTER_FORCE_ARRAY` flag, which puts the result in an array. This option, or bit masks, aren't supported either right now. So adding support for bitmasks without `FILTER_FORCE_ARRAY` would result in more false positives
1 parent af8ac06 commit e83948c

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

‎src/Type/Php/FilterVarDynamicReturnTypeExtension.php‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type\Php;
44

5+
use PhpParser\Node;
56
use PhpParser\Node\Expr\ConstFetch;
67
use PhpParser\Node\Expr\FuncCall;
78
use PHPStan\Analyser\Scope;
@@ -12,6 +13,7 @@
1213
use PHPStan\Type\FloatType;
1314
use PHPStan\Type\IntegerType;
1415
use PHPStan\Type\MixedType;
16+
use PHPStan\Type\NullType;
1517
use PHPStan\Type\StringType;
1618
use PHPStan\Type\Type;
1719
use PHPStan\Type\UnionType;
@@ -22,12 +24,19 @@ class FilterVarDynamicReturnTypeExtension implements DynamicFunctionReturnTypeEx
2224
/** @var array<string, Type> */
2325
private $filterTypesHashMaps;
2426

27+
/** @var array<string, Type> */
28+
private $nullableTypes;
29+
2530
public function __construct()
2631
{
2732
$booleanType = new BooleanType();
33+
$nullableBooleanType = new UnionType([new BooleanType(), new NullType()]);
2834
$floatOrFalseType = new UnionType([new FloatType(), new ConstantBooleanType(false)]);
35+
$nullableFloatType = new UnionType([new FloatType(), new NullType()]);
2936
$intOrFalseType = new UnionType([new IntegerType(), new ConstantBooleanType(false)]);
37+
$nullableIntType = new UnionType([new IntegerType(), new NullType()]);
3038
$stringOrFalseType = new UnionType([new StringType(), new ConstantBooleanType(false)]);
39+
$nullableStringType = new UnionType([new StringType(), new NullType()]);
3140

3241
$this->filterTypesHashMaps = [
3342
'FILTER_SANITIZE_EMAIL' => $stringOrFalseType,
@@ -47,6 +56,17 @@ public function __construct()
4756
'FILTER_VALIDATE_REGEXP' => $stringOrFalseType,
4857
'FILTER_VALIDATE_URL' => $stringOrFalseType,
4958
];
59+
60+
$this->nullableTypes = [
61+
'FILTER_VALIDATE_BOOLEAN' => $nullableBooleanType,
62+
'FILTER_VALIDATE_EMAIL' => $nullableStringType,
63+
'FILTER_VALIDATE_FLOAT' => $nullableFloatType,
64+
'FILTER_VALIDATE_INT' => $nullableIntType,
65+
'FILTER_VALIDATE_IP' => $nullableStringType,
66+
'FILTER_VALIDATE_MAC' => $nullableStringType,
67+
'FILTER_VALIDATE_REGEXP' => $nullableStringType,
68+
'FILTER_VALIDATE_URL' => $nullableStringType,
69+
];
5070
}
5171

5272
public function isFunctionSupported(FunctionReflection $functionReflection): bool
@@ -74,7 +94,29 @@ public function getTypeFromFunctionCall(
7494

7595
$filterName = (string) $filterExpr->name;
7696

97+
if ($this->isNullableType($filterName, $functionCall->args[2] ?? null)) {
98+
return $this->nullableTypes[$filterName];
99+
}
100+
77101
return $this->filterTypesHashMaps[$filterName] ?? $mixedType;
78102
}
79103

104+
private function isNullableType(string $filterName, ?Node\Arg $thirdArg): bool
105+
{
106+
if ($thirdArg === null || !array_key_exists($filterName, $this->nullableTypes)) {
107+
return false;
108+
}
109+
110+
$expr = $thirdArg->value;
111+
if ($expr instanceof Node\Expr\Array_) {
112+
foreach ($expr->items as $item) {
113+
if ($item->key instanceof Node\Scalar\String_ && $item->key->value === 'flags') {
114+
$expr = $item->value;
115+
break;
116+
}
117+
}
118+
}
119+
return $expr instanceof ConstFetch && (string) $expr->name === 'FILTER_NULL_ON_FAILURE';
120+
}
121+
80122
}

‎tests/PHPStan/Analyser/NodeScopeResolverTest.php‎

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8038,34 +8038,102 @@ public function dataFilterVar(): array
80388038
'bool',
80398039
'filter_var($mixed, FILTER_VALIDATE_BOOLEAN)',
80408040
],
8041+
[
8042+
'bool|null',
8043+
'filter_var($mixed, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)',
8044+
],
8045+
[
8046+
'bool|null',
8047+
'filter_var($mixed, FILTER_VALIDATE_BOOLEAN ,["flags" => FILTER_NULL_ON_FAILURE])',
8048+
],
80418049
[
80428050
'string|false',
80438051
'filter_var($mixed, FILTER_VALIDATE_EMAIL)',
80448052
],
8053+
[
8054+
'string|null',
8055+
'filter_var($mixed, FILTER_VALIDATE_EMAIL, FILTER_NULL_ON_FAILURE)',
8056+
],
8057+
[
8058+
'string|null',
8059+
'filter_var($mixed, FILTER_VALIDATE_EMAIL ,["flags" => FILTER_NULL_ON_FAILURE])',
8060+
],
80458061
[
80468062
'float|false',
80478063
'filter_var($mixed, FILTER_VALIDATE_FLOAT)',
80488064
],
8065+
[
8066+
'float|null',
8067+
'filter_var($mixed, FILTER_VALIDATE_FLOAT, FILTER_NULL_ON_FAILURE)',
8068+
],
8069+
[
8070+
'float|null',
8071+
'filter_var($mixed, FILTER_VALIDATE_FLOAT ,["flags" => FILTER_NULL_ON_FAILURE])',
8072+
],
80498073
[
80508074
'int|false',
80518075
'filter_var($mixed, FILTER_VALIDATE_INT)',
80528076
],
8077+
[
8078+
'int|null',
8079+
'filter_var($mixed, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE)',
8080+
],
8081+
[
8082+
'int|null',
8083+
'filter_var($mixed, FILTER_VALIDATE_INT ,["flags" => FILTER_NULL_ON_FAILURE])',
8084+
],
80538085
[
80548086
'string|false',
80558087
'filter_var($mixed, FILTER_VALIDATE_IP)',
80568088
],
8089+
[
8090+
'string|false',
8091+
'filter_var($mixed, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)',
8092+
],
8093+
[
8094+
'string|null',
8095+
'filter_var($mixed, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE)',
8096+
],
8097+
[
8098+
'string|null',
8099+
'filter_var($mixed, FILTER_VALIDATE_IP ,["flags" => FILTER_NULL_ON_FAILURE])',
8100+
],
80578101
[
80588102
'string|false',
80598103
'filter_var($mixed, FILTER_VALIDATE_MAC)',
80608104
],
8105+
[
8106+
'string|null',
8107+
'filter_var($mixed, FILTER_VALIDATE_MAC, FILTER_NULL_ON_FAILURE)',
8108+
],
8109+
[
8110+
'string|null',
8111+
'filter_var($mixed, FILTER_VALIDATE_MAC ,["flags" => FILTER_NULL_ON_FAILURE])',
8112+
],
80618113
[
80628114
'string|false',
80638115
'filter_var($mixed, FILTER_VALIDATE_REGEXP)',
80648116
],
8117+
[
8118+
'string|null',
8119+
'filter_var($mixed, FILTER_VALIDATE_REGEXP, FILTER_NULL_ON_FAILURE)',
8120+
],
8121+
[
8122+
'string|null',
8123+
'filter_var($mixed, FILTER_VALIDATE_REGEXP ,["flags" => FILTER_NULL_ON_FAILURE])',
8124+
],
80658125
[
80668126
'string|false',
80678127
'filter_var($mixed, FILTER_VALIDATE_URL)',
80688128
],
8129+
[
8130+
'string|null',
8131+
'filter_var($mixed, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)',
8132+
],
8133+
[
8134+
'string|null',
8135+
'filter_var($mixed, FILTER_VALIDATE_URL ,["flags" => FILTER_NULL_ON_FAILURE])',
8136+
],
80698137
];
80708138
}
80718139

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /