33namespace PHPStan \Type \Php ;
44
55use PhpParser \Node ;
6- use PhpParser \Node \Arg ;
76use PhpParser \Node \Expr \FuncCall ;
87use PHPStan \Analyser \Scope ;
98use PHPStan \Reflection \FunctionReflection ;
@@ -143,32 +142,30 @@ public function getTypeFromFunctionCall(
143142 {
144143 $ mixedType = new MixedType ();
145144
146- $ filterArg = $ functionCall ->getArgs ()[1 ] ?? null ;
147- if ($ filterArg === null ) {
145+ $ filterType = isset ( $ functionCall ->getArgs ()[1 ]) ? $ scope -> getType ( $ functionCall -> getArgs ()[ 1 ]-> value ) : null ;
146+ if ($ filterType === null ) {
148147 $ filterValue = $ this ->getConstant ('FILTER_DEFAULT ' );
149148 } else {
150- $ filterType = $ scope ->getType ($ filterArg ->value );
151149 if (!$ filterType instanceof ConstantIntegerType) {
152150 return $ mixedType ;
153151 }
154152 $ filterValue = $ filterType ->getValue ();
155153 }
156154
157- $ flagsArg = $ functionCall ->getArgs ()[2 ] ?? null ;
155+ $ flagsType = isset ( $ functionCall ->getArgs ()[2 ]) ? $ scope -> getType ( $ functionCall -> getArgs ()[ 2 ]-> value ) : null ;
158156 $ inputType = $ scope ->getType ($ functionCall ->getArgs ()[0 ]->value );
159-
160- $ defaultType = $ this ->hasFlag ($ this ->getConstant ('FILTER_NULL_ON_FAILURE ' ), $ flagsArg , $ scope )
157+ $ defaultType = $ this ->hasFlag ($ this ->getConstant ('FILTER_NULL_ON_FAILURE ' ), $ flagsType )
161158 ? new NullType ()
162159 : new ConstantBooleanType (false );
163- $ exactType = $ this ->determineExactType ($ inputType , $ filterValue , $ defaultType , $ flagsArg , $ scope );
160+ $ exactType = $ this ->determineExactType ($ inputType , $ filterValue , $ defaultType , $ flagsType );
164161 $ type = $ exactType ?? $ this ->getFilterTypeMap ()[$ filterValue ] ?? $ mixedType ;
165162
166163 $ typeOptionNames = $ this ->getFilterTypeOptions ()[$ filterValue ] ?? [];
167- $ otherTypes = $ this ->getOtherTypes ($ flagsArg , $ scope , $ typeOptionNames , $ defaultType );
164+ $ otherTypes = $ this ->getOtherTypes ($ flagsType , $ typeOptionNames , $ defaultType );
168165
169166 if ($ inputType ->isNonEmptyString ()->yes ()
170167 && $ type ->isString ()->yes ()
171- && !$ this ->canStringBeSanitized ($ filterValue , $ flagsArg , $ scope )) {
168+ && !$ this ->canStringBeSanitized ($ filterValue , $ flagsType )) {
172169 $ accessory = new AccessoryNonEmptyStringType ();
173170 if ($ inputType ->isNonFalsyString ()->yes ()) {
174171 $ accessory = new AccessoryNonFalsyStringType ();
@@ -196,14 +193,14 @@ public function getTypeFromFunctionCall(
196193 $ type = TypeCombinator::union ($ type , $ otherTypes ['default ' ]);
197194 }
198195
199- if ($ this ->hasFlag ($ this ->getConstant ('FILTER_FORCE_ARRAY ' ), $ flagsArg , $ scope )) {
196+ if ($ this ->hasFlag ($ this ->getConstant ('FILTER_FORCE_ARRAY ' ), $ flagsType )) {
200197 return new ArrayType (new MixedType (), $ type );
201198 }
202199
203200 return $ type ;
204201 }
205202
206- private function determineExactType (Type $ in , int $ filterValue , Type $ defaultType , ?Arg $ flagsArg , Scope $ scope ): ?Type
203+ private function determineExactType (Type $ in , int $ filterValue , Type $ defaultType , ?Type $ flagsType ): ?Type
207204 {
208205 if (($ filterValue === $ this ->getConstant ('FILTER_VALIDATE_BOOLEAN ' ) && $ in ->isBoolean ()->yes ())
209206 || ($ filterValue === $ this ->getConstant ('FILTER_VALIDATE_INT ' ) && $ in ->isInteger ()->yes ())
@@ -213,8 +210,8 @@ private function determineExactType(Type $in, int $filterValue, Type $defaultTyp
213210
214211 if ($ filterValue === $ this ->getConstant ('FILTER_VALIDATE_INT ' ) && $ in instanceof ConstantStringType) {
215212 $ value = $ in ->getValue ();
216- $ allowOctal = $ this ->hasFlag ($ this ->getConstant ('FILTER_FLAG_ALLOW_OCTAL ' ), $ flagsArg , $ scope );
217- $ allowHex = $ this ->hasFlag ($ this ->getConstant ('FILTER_FLAG_ALLOW_HEX ' ), $ flagsArg , $ scope );
213+ $ allowOctal = $ this ->hasFlag ($ this ->getConstant ('FILTER_FLAG_ALLOW_OCTAL ' ), $ flagsType );
214+ $ allowHex = $ this ->hasFlag ($ this ->getConstant ('FILTER_FLAG_ALLOW_HEX ' ), $ flagsType );
218215
219216 if ($ allowOctal && preg_match ('/\A0[oO][0-7]+\z/ ' , $ value ) === 1 ) {
220217 $ octalValue = octdec ($ value );
@@ -240,14 +237,14 @@ private function determineExactType(Type $in, int $filterValue, Type $defaultTyp
240237 * @param list<string> $typeOptionNames
241238 * @return array{default: Type, range?: Type}
242239 */
243- private function getOtherTypes (?Node \ Arg $ flagsArg , Scope $ scope , array $ typeOptionNames , Type $ defaultType ): array
240+ private function getOtherTypes (?Type $ flagsType , array $ typeOptionNames , Type $ defaultType ): array
244241 {
245242 $ falseType = new ConstantBooleanType (false );
246- if ($ flagsArg === null ) {
243+ if ($ flagsType === null ) {
247244 return ['default ' => $ falseType ];
248245 }
249246
250- $ typeOptions = $ this ->getOptions ($ flagsArg , $ scope , 'default ' , ...$ typeOptionNames );
247+ $ typeOptions = $ this ->getOptions ($ flagsType , 'default ' , ...$ typeOptionNames );
251248 $ defaultType = $ typeOptions ['default ' ] ?? $ defaultType ;
252249 $ otherTypes = ['default ' => $ defaultType ];
253250 $ range = [];
@@ -278,16 +275,15 @@ private function getOtherTypes(?Node\Arg $flagsArg, Scope $scope, array $typeOpt
278275 /**
279276 * @return array<string, ?Type>
280277 */
281- private function getOptions (Node \ Arg $ expression , Scope $ scope , string ...$ optionNames ): array
278+ private function getOptions (Type $ flagsType , string ...$ optionNames ): array
282279 {
283280 $ options = [];
284281
285- $ exprType = $ scope ->getType ($ expression ->value );
286- if (!$ exprType instanceof ConstantArrayType) {
282+ if (!$ flagsType instanceof ConstantArrayType) {
287283 return $ options ;
288284 }
289285
290- $ optionsType = $ exprType ->getOffsetValueType (new ConstantStringType ('options ' ));
286+ $ optionsType = $ flagsType ->getOffsetValueType (new ConstantStringType ('options ' ));
291287 if (!$ optionsType instanceof ConstantArrayType) {
292288 return $ options ;
293289 }
@@ -300,13 +296,13 @@ private function getOptions(Node\Arg $expression, Scope $scope, string ...$optio
300296 return $ options ;
301297 }
302298
303- private function hasFlag (int $ flag , ?Node \ Arg $ expression , Scope $ scope ): bool
299+ private function hasFlag (int $ flag , ?Type $ flagsType ): bool
304300 {
305- if ($ expression === null ) {
301+ if ($ flagsType === null ) {
306302 return false ;
307303 }
308304
309- $ type = $ this ->getFlagsValue ($ scope -> getType ( $ expression -> value ) );
305+ $ type = $ this ->getFlagsValue ($ flagsType );
310306
311307 return $ type instanceof ConstantIntegerType && ($ type ->getValue () & $ flag ) === $ flag ;
312308 }
@@ -320,7 +316,7 @@ private function getFlagsValue(Type $exprType): Type
320316 return $ exprType ->getOffsetValueType ($ this ->flagsString );
321317 }
322318
323- private function canStringBeSanitized (int $ filterValue , ?Node \ Arg $ flagsArg , Scope $ scope ): bool
319+ private function canStringBeSanitized (int $ filterValue , ?Type $ flagsType ): bool
324320 {
325321 // If it is a validation filter, the string will not be changed
326322 if (($ filterValue & self ::VALIDATION_FILTER_BITMASK ) !== 0 ) {
@@ -330,9 +326,9 @@ private function canStringBeSanitized(int $filterValue, ?Node\Arg $flagsArg, Sco
330326 // FILTER_DEFAULT will not sanitize, unless it has FILTER_FLAG_STRIP_LOW,
331327 // FILTER_FLAG_STRIP_HIGH, or FILTER_FLAG_STRIP_BACKTICK
332328 if ($ filterValue === $ this ->getConstant ('FILTER_DEFAULT ' )) {
333- return $ this ->hasFlag ($ this ->getConstant ('FILTER_FLAG_STRIP_LOW ' ), $ flagsArg , $ scope )
334- || $ this ->hasFlag ($ this ->getConstant ('FILTER_FLAG_STRIP_HIGH ' ), $ flagsArg , $ scope )
335- || $ this ->hasFlag ($ this ->getConstant ('FILTER_FLAG_STRIP_BACKTICK ' ), $ flagsArg , $ scope );
329+ return $ this ->hasFlag ($ this ->getConstant ('FILTER_FLAG_STRIP_LOW ' ), $ flagsType )
330+ || $ this ->hasFlag ($ this ->getConstant ('FILTER_FLAG_STRIP_HIGH ' ), $ flagsType )
331+ || $ this ->hasFlag ($ this ->getConstant ('FILTER_FLAG_STRIP_BACKTICK ' ), $ flagsType );
336332 }
337333
338334 return true ;
0 commit comments