src/Phan/filter_var.php_polyfill
<?php
/**
* Implements only the subset of filter_var() used by Phan.
*
* @author Tyson Andre
*/
if (!function_exists('filter_var')) {
$define_polyfill_const = function(string $name, int $value) {
if (!defined($name)) {
define($name, $value);
}
};
$define_polyfill_const('FILTER_CALLBACK', 1024);
$define_polyfill_const('FILTER_DEFAULT', 516);
$define_polyfill_const('FILTER_FLAG_ALLOW_FRACTION', 4096);
$define_polyfill_const('FILTER_FLAG_ALLOW_HEX', 2);
$define_polyfill_const('FILTER_FLAG_ALLOW_OCTAL', 1);
$define_polyfill_const('FILTER_FLAG_ALLOW_SCIENTIFIC', 16384);
$define_polyfill_const('FILTER_FLAG_ALLOW_THOUSAND', 8192);
$define_polyfill_const('FILTER_FLAG_EMAIL_UNICODE', 1048576);
$define_polyfill_const('FILTER_FLAG_EMPTY_STRING_NULL', 256);
$define_polyfill_const('FILTER_FLAG_ENCODE_AMP', 64);
$define_polyfill_const('FILTER_FLAG_ENCODE_HIGH', 32);
$define_polyfill_const('FILTER_FLAG_ENCODE_LOW', 16);
$define_polyfill_const('FILTER_FLAG_HOSTNAME', 1048576);
$define_polyfill_const('FILTER_FLAG_HOST_REQUIRED', 131072);
$define_polyfill_const('FILTER_FLAG_IPV4', 1048576);
$define_polyfill_const('FILTER_FLAG_IPV6', 2097152);
$define_polyfill_const('FILTER_FLAG_NONE', 0);
$define_polyfill_const('FILTER_FLAG_NO_ENCODE_QUOTES', 128);
$define_polyfill_const('FILTER_FLAG_NO_PRIV_RANGE', 8388608);
$define_polyfill_const('FILTER_FLAG_NO_RES_RANGE', 4194304);
$define_polyfill_const('FILTER_FLAG_PATH_REQUIRED', 262144);
$define_polyfill_const('FILTER_FLAG_QUERY_REQUIRED', 524288);
$define_polyfill_const('FILTER_FLAG_SCHEME_REQUIRED', 65536);
$define_polyfill_const('FILTER_FLAG_STRIP_BACKTICK', 512);
$define_polyfill_const('FILTER_FLAG_STRIP_HIGH', 8);
$define_polyfill_const('FILTER_FLAG_STRIP_LOW', 4);
$define_polyfill_const('FILTER_FORCE_ARRAY', 67108864);
$define_polyfill_const('FILTER_NULL_ON_FAILURE', 134217728);
$define_polyfill_const('FILTER_REQUIRE_ARRAY', 16777216);
$define_polyfill_const('FILTER_REQUIRE_SCALAR', 33554432);
$define_polyfill_const('FILTER_SANITIZE_ADD_SLASHES', 523);
$define_polyfill_const('FILTER_SANITIZE_EMAIL', 517);
$define_polyfill_const('FILTER_SANITIZE_ENCODED', 514);
$define_polyfill_const('FILTER_SANITIZE_FULL_SPECIAL_CHARS', 522);
$define_polyfill_const('FILTER_SANITIZE_MAGIC_QUOTES', 521);
$define_polyfill_const('FILTER_SANITIZE_NUMBER_FLOAT', 520);
$define_polyfill_const('FILTER_SANITIZE_NUMBER_INT', 519);
$define_polyfill_const('FILTER_SANITIZE_SPECIAL_CHARS', 515);
$define_polyfill_const('FILTER_SANITIZE_STRING', 513);
$define_polyfill_const('FILTER_SANITIZE_STRIPPED', 513);
$define_polyfill_const('FILTER_SANITIZE_URL', 518);
$define_polyfill_const('FILTER_UNSAFE_RAW', 516);
$define_polyfill_const('FILTER_VALIDATE_BOOLEAN', 258);
$define_polyfill_const('FILTER_VALIDATE_DOMAIN', 277);
$define_polyfill_const('FILTER_VALIDATE_EMAIL', 274);
$define_polyfill_const('FILTER_VALIDATE_FLOAT', 259);
$define_polyfill_const('FILTER_VALIDATE_INT', 257);
$define_polyfill_const('FILTER_VALIDATE_IP', 275);
$define_polyfill_const('FILTER_VALIDATE_MAC', 276);
$define_polyfill_const('FILTER_VALIDATE_REGEXP', 272);
$define_polyfill_const('FILTER_VALIDATE_URL', 273);
/**
*
* @throws AssertionError for unimplemented filters
*
* @phan-file-suppress PhanNativePHPSyntaxCheckPlugin
* @suppress PhanRedefineFunctionInternal
* @return mixed
*/
function filter_var($value, int $filter = FILTER_DEFAULT, $options = null) {
switch ($filter) {
case FILTER_DEFAULT:
if (is_array($value)) {
return false;
}
if (is_object($value)) {
if (!method_exists($value, '__toString')) {
return false;
}
}
return (string) $value;
case FILTER_VALIDATE_INT:
if (is_int($value)) {
return $value;
}
if (is_array($value)) {
return false;
}
if (is_object($value)) {
if (!method_exists($value, '__toString')) {
return false;
}
}
// handle "\v\n\r\t 0123 "
$value = trim((string)$value, " \t\r\n\v");
if ($options !== null) {
if (!is_int($options)) {
throw new AssertionError("filter_var() polyfill: unsupported type for options with FILTER_VALIDATE_INT");
}
// Octal and hex are supported by the real filter_var() for non-negative numbers
if ($options & FILTER_FLAG_ALLOW_OCTAL) {
if (preg_match('/^0[0-7]*$/iD', $value)) {
// @phan-suppress-next-line PhanPossiblyFalseTypeArgumentInternal
$result = octdec(substr($value, 2));
return is_int($result) ? $result : false;
}
}
if ($options & FILTER_FLAG_ALLOW_HEX) {
if (preg_match('/^0x[0-9a-f]+$/iD', $value)) {
// @phan-suppress-next-line PhanPossiblyFalseTypeArgumentInternal
$result = hexdec(substr($value, 2));
return is_int($result) ? $result : false;
}
}
}
if (!preg_match('/^[-+]?(0|[1-9][0-9]*)$/D', $value)) {
return false;
}
$result = (int)$value;
if ((string)$result !== $value) {
return false;
}
return $result;
case FILTER_VALIDATE_FLOAT:
if ($options !== null) {
throw new AssertionError("filter_var() polyfill: Unsupported \$options");
}
if (!is_numeric($value)) {
return false;
}
return (float)$value;
case FILTER_VALIDATE_IP:
if ($options !== null) {
throw new AssertionError("filter_var() polyfill: Unsupported \$options");
}
if (is_array($value)) {
return false;
}
if (is_object($value)) {
if (!method_exists($value, '__toString')) {
return false;
}
}
$result = (string)$value;
// TODO: This is incomplete and doesn't bother validating integer ranges or details.
if (strpos($result, ':')) {
// ipv6
if (!preg_match('/^[0-9a-f:.]+\.)$/i', $result)) {
return false;
}
return $result;
} else {
// ipv4
if (!preg_match('/^([0-9]+\.){3}[0-9]+$/D', $result)) {
return false;
}
return $result;
}
default:
throw new AssertionError("filter_var() polyfill: Unsupported filter $filter");
}
}
} /* end function_exists check */