Improve FilterVar with FILTER_VALIDATE_* options

The `filter_var` function is more of a sanitizer, but we as
a validation library do not care for that use case.

We should treat its sanitizings as a signal for checking if
the type after sanitization matches the option provided.

This fixes #1387
This commit is contained in:
Alexandre Gomes Gaigalas 2023-02-16 01:23:21 -03:00
parent a3e016bec9
commit 689026fc7b
3 changed files with 18 additions and 11 deletions

View file

@ -22,6 +22,7 @@ v::filterVar(FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)->validate('@local');
Version | Description Version | Description
---------|------------- ---------|-------------
2.3.0 | `v::filterVar(FILTER_VALIDATE_INT)->validate(0)` is no longer false
2.0.15 | Allow validating domains 2.0.15 | Allow validating domains
0.8.0 | Created 0.8.0 | Created

View file

@ -15,7 +15,8 @@ namespace Respect\Validation\Rules;
use Respect\Validation\Exceptions\ComponentException; use Respect\Validation\Exceptions\ComponentException;
use function in_array; use function array_key_exists;
use function filter_var;
use function is_array; use function is_array;
use function is_int; use function is_int;
@ -36,14 +37,14 @@ use const FILTER_VALIDATE_URL;
final class FilterVar extends AbstractEnvelope final class FilterVar extends AbstractEnvelope
{ {
private const ALLOWED_FILTERS = [ private const ALLOWED_FILTERS = [
FILTER_VALIDATE_BOOLEAN, FILTER_VALIDATE_BOOLEAN => 'is_bool',
FILTER_VALIDATE_DOMAIN, FILTER_VALIDATE_DOMAIN => 'is_string',
FILTER_VALIDATE_EMAIL, FILTER_VALIDATE_EMAIL => 'is_string',
FILTER_VALIDATE_FLOAT, FILTER_VALIDATE_FLOAT => 'is_float',
FILTER_VALIDATE_INT, FILTER_VALIDATE_INT => 'is_int',
FILTER_VALIDATE_IP, FILTER_VALIDATE_IP => 'is_string',
FILTER_VALIDATE_REGEXP, FILTER_VALIDATE_REGEXP => 'is_string',
FILTER_VALIDATE_URL, FILTER_VALIDATE_URL => 'is_string',
]; ];
/** /**
@ -55,7 +56,7 @@ final class FilterVar extends AbstractEnvelope
*/ */
public function __construct(int $filter, $options = null) public function __construct(int $filter, $options = null)
{ {
if (!in_array($filter, self::ALLOWED_FILTERS)) { if (!array_key_exists($filter, self::ALLOWED_FILTERS)) {
throw new ComponentException('Cannot accept the given filter'); throw new ComponentException('Cannot accept the given filter');
} }
@ -64,6 +65,10 @@ final class FilterVar extends AbstractEnvelope
$arguments[] = $options; $arguments[] = $options;
} }
parent::__construct(new Callback('filter_var', ...$arguments)); parent::__construct(new Callback(static function ($input) use ($filter, $arguments) {
return (self::ALLOWED_FILTERS[$filter])(
filter_var($input, ...$arguments)
);
}));
} }
} }

View file

@ -60,6 +60,7 @@ final class FilterVarTest extends RuleTestCase
[new FilterVar(FILTER_VALIDATE_BOOLEAN), 'On'], [new FilterVar(FILTER_VALIDATE_BOOLEAN), 'On'],
[new FilterVar(FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED), 'http://example.com?foo=bar'], [new FilterVar(FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED), 'http://example.com?foo=bar'],
[new FilterVar(FILTER_VALIDATE_DOMAIN), 'example.com'], [new FilterVar(FILTER_VALIDATE_DOMAIN), 'example.com'],
[new FilterVar(FILTER_VALIDATE_INT), '0'],
]; ];
} }