<?php
/**
 * @psalm-template TKey as array-key
 * @psalm-template TArray as array<TKey, mixed>
 *
 * @param TArray $arr
 * @param mixed $search_value
 * @param bool  $strict
 *
 * @return (TArray is non-empty-array ? non-empty-list<TKey> : list<TKey>)
 * @psalm-pure
 */
function array_keys(array $arr, $search_value = null, bool $strict = false)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array $arr2
 * @param array ...$arr3
 *
 * @return array<TKey, TValue>
 * @psalm-pure
 */
function array_intersect(array $arr, array $arr2, array ...$arr3)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array $arr2
 * @param array ...$arr3
 *
 * @return array<TKey, TValue>
 * @psalm-pure
 */
function array_intersect_key(array $arr, array $arr2, array ...$arr3)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array $arr2
 * @param array ...$arr3
 * @param callable(TKey): int $keyCompareFunc
 *
 * @return array<TKey, TValue>
 *
 * @psalm-pure
 */
function array_intersect_ukey(array $arr, array $arr2, array ...$arr3, callable $keyCompareFunc): array
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array $arr2
 * @param array ...$arr3
 *
 * @return array<TKey, TValue>
 * @psalm-pure
 */
function array_intersect_assoc(array $arr, array $arr2, array ...$arr3)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array $arr2
 * @param array ...$arr3
 * @param callable(TKey): int $keyCompareFunc
 *
 * @return array<TKey, TValue>
 *
 * @psalm-pure
 */
function array_intersect_uassoc(array $arr, array $arr2, array ...$arr3, callable $keyCompareFunc): array {}
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<mixed, TKey> $arr
 * @param array<mixed, TValue> $arr2
 *
 * @return array<TKey, TValue>|false
 * @psalm-ignore-falsable-return
 * @psalm-pure
 */
function array_combine(array $arr, array $arr2)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array $arr2
 * @param array ...$arr3
 *
 * @return array<TKey, TValue>
 * @psalm-pure
 */
function array_diff(array $arr, array $arr2, array ...$arr3)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array $arr2
 * @param array ...$arr3
 *
 * @return array<TKey, TValue>
 * @psalm-pure
 */
function array_diff_key(array $arr, array $arr2, array ...$arr3)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array $arr2
 * @param array ...$arr3
 * @param callable(TKey, TKey): int $keyCompareFunc
 *
 * @return array<TKey, TValue>
 * @psalm-pure
 */
function array_diff_ukey(array $arr, array $arr2, array ...$arr3, callable $keyCompareFunc): array {}
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array $arr2
 * @param array ...$arr3
 *
 * @return array<TKey, TValue>
 * @psalm-pure
 */
function array_diff_assoc(array $arr, array $arr2, array ...$arr3)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array $arr2
 * @param array ...$arr3
 * @param callable(TKey, TKey): int $keyCompareFunc
 *
 * @return array<TKey, TValue>
 * @psalm-pure
 */
function array_diff_uassoc(array $arr, array $arr2, array ... $arr3, callable $keyCompareFunc): array {}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 *
 * @return array<TValue, TKey>
 * @psalm-pure
 */
function array_flip(array $arr)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TArray as array<TKey, mixed>
 *
 * @param TArray $arr
 *
 * @return (TArray is array<empty, empty> ? null : TKey|null)
 * @psalm-pure
 * @psalm-ignore-nullable-return
 */
function key($arr)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TArray as array<TKey, mixed>
 *
 * @param TArray $arr
 *
 * @return (TArray is array<empty, empty> ? null : (TArray is non-empty-array ? TKey : TKey|null))
 * @psalm-pure
 */
function array_key_first($arr)
{
}

/**
 * @psalm-template TKey as array-key
 * @psalm-template TArray as array<TKey, mixed>
 *
 * @param TArray $arr
 *
 * @return (TArray is array<empty, empty> ? null : (TArray is non-empty-array ? TKey : TKey|null))
 * @psalm-pure
 */
function array_key_last($arr)
{
}

/**
 * @psalm-template T
 *
 * @param mixed           $needle
 * @param array<T, mixed> $haystack
 * @param bool            $strict
 *
 * @return T|false
 * @psalm-pure
 */
function array_search($needle, array $haystack, bool $strict = false)
{
}

/**
 * @psalm-template T
 *
 * @param T[] $arr
 * @param-out list<T> $arr
 */
function shuffle(array &$arr): bool
{
}

/**
 * @psalm-template T
 *
 * @param T[] $arr
 * @param-out list<T> $arr
 */
function sort(array &$arr, int $sort_flags = SORT_REGULAR): bool
{
}

/**
 * @psalm-template T
 *
 * @param T[] $arr
 * @param-out list<T> $arr
 */
function rsort(array &$arr, int $sort_flags = SORT_REGULAR): bool
{
}

/**
 * @psalm-template T
 *
 * @param T[] $arr
 * @param callable(T,T):int $callback
 * @param-out list<T> $arr
 */
function usort(array &$arr, callable $callback): bool
{
}

/**
 * @psalm-template TKey
 * @psalm-template T
 *
 * @param array<TKey,T> $arr
 * @param callable(T,T):int $callback
 * @param-out array<TKey,T> $arr
 */
function uasort(array &$arr, callable $callback): bool
{
}

/**
 * @psalm-template TKey
 * @psalm-template T
 *
 * @param array<TKey,T> $arr
 * @param callable(TKey,TKey):int $callback
 * @param-out array<TKey,T> $arr
 */
function uksort(array &$arr, callable $callback): bool
{
}

/**
 * @psalm-pure
 *
 * @psalm-template K of array-key
 * @psalm-template T
 *
 * @param array<K,T> $arr
 *
 * @return array<K,T>
 */
function array_change_key_case(array $arr, int $case = CASE_LOWER)
{
}

/**
 * @psalm-pure
 *
 * @psalm-template TKey as array-key
 *
 * @param TKey $key
 * @param array<TKey, mixed> $search
 *
 * @return bool
 */
function array_key_exists($key, array $search) : bool
{
}

/**
 * @psalm-pure
 *
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey, TValue> $arr
 * @param array<TKey, TValue> ...$arr2
 *
 * @return array<TKey, TValue>
 */
function array_merge_recursive(array $arr, array ...$arr2)
{
}

/**
 * @psalm-pure
 *
 * @psalm-template TKey as array-key
 * @psalm-template TValue
 *
 * @param array<TKey> $keys
 * @param TValue $value
 *
 * @return array<TKey, TValue>
 */
function array_fill_keys(array $keys, $value): array
{
}

/**
 * @psalm-pure
 *
 * @psalm-template TKey
 *
 * @param string $pattern
 * @param array<TKey,string> $input
 * @param 0|1 $flags 1=PREG_GREP_INVERT
 * @return array<TKey,string>
 */
function preg_grep($pattern, array $input, $flags = 0)
{
}

/**
 * @param resource $handle
 * @param-out closed-resource $handle
 */
function fclose(&$handle) : bool
{
}

/**
 * @param string $reference
 * @param-out null $reference
 */
function sodium_memzero(string &$reference): void
{
}

/**
 * @param mixed $var
 * @param bool $return
 * @return ($return is true ? string : void)
 *
 * @psalm-taint-specialize
 * @psalm-flow ($var) -> return
 */
function var_export($var, bool $return = false) {}

/**
 * @param mixed $var
 * @param bool $return
 * @return ($return is true ? string : true)
 *
 * @psalm-taint-specialize
 * @psalm-flow ($var) -> return
 */
function print_r($var, bool $return = false) {}

/**
 * @psalm-pure
 *
 * @param mixed $var
 * @return ($return is true ? string : bool)
 */
function highlight_file($var, bool $return = false) {}

/**
 * @psalm-pure
 *
 * @param mixed $var
 * @return ($return is true ? string : bool)
 *
 * @psalm-flow ($var) -> return
 */
function highlight_string($var, bool $return = false) {}

/**
 * @psalm-pure
 *
 * @return ($get_as_float is true ? float : string)
 */
function microtime(bool $get_as_float = false) {}

/**
 * @psalm-pure
 *
 * @return ($return_float is true ? float : array<string, int>)
 */
function gettimeofday(bool $return_float = false) {}

/**
 * @psalm-pure
 *
 * @param numeric $number
 * @return ($number is int ? int : ($number is float ? float : int|float))
 */
function abs($number) {}

/**
 * @psalm-pure
 *
 * @template T as string|int|float
 * @template TStep as int|float
 * @param T $start
 * @param T $end
 * @param TStep $step
 * @return (
 *     T is int
 *     ? (TStep is int ? list<int> : list<int|float>)
 *     : (
 *         T is float
 *         ? list<float>
 *         : (
 *              T is string
 *              ? list<string>
 *              : (
 *                   T is int|float
 *                   ? list<int|float>
 *                   : list<int|float|string>
 *              )
 *         )
 *     )
 * )
 */
function range($start, $end, $step = 1) {}

/**
 * @psalm-pure
 *
 * @return (
 *     $format is 'd'|'j'|'N'|'w'|'z'|'W'|'m'|'n'|'t'|'L'|'o'|'Y'|'y'|'B'|'g'|'G'|'h'|'H'|'i'|'s'|'u'|'v'|'Z'|'U'|'I'
 *     ? numeric-string
 *     : ($timestamp is numeric ? string : string|false)
 * )
 */
function date(string $format, int $timestamp = 0) {}

/**
 * @psalm-pure
 *
 * @param mixed $vars
 * @param-out string|int|float $vars
 * @return (func_num_args() is 2 ? list<float|int|string> : int)
 */
function sscanf(string $str, string $format, &...$vars) {}

/**
 * @psalm-pure
 *
 * @return (
 *     func_num_args() is 1
 *     ? array{dirname: string, basename: string, extension?: string, filename: string}
 *     : string
 * )
 */
function pathinfo(string $path, int $options = \PATHINFO_DIRNAME) {}

/**
 * @psalm-pure
 *
 * @return (func_num_args() is 0 ? array<string, string> : string|false)
 */
function getenv(string $varname = '', bool $local_only = false) {}

/**
 * @psalm-pure
 *
 * @return (
 *     $str is non-empty-string ? non-empty-lowercase-string : lowercase-string
 * )
 *
 * @psalm-flow ($str) -> return
 */
function strtolower(string $str) : string {}

/**
 * @psalm-pure
 *
 * @psalm-flow ($str) -> return
 */
function strtoupper(string $str) : string {}

/**
 * @psalm-pure
 *
 * @param string $haystack
 *
 * @psalm-return positive-int|0|false
 */
function strpos($haystack, $needle, int $offset = 0) : int {}

/**
 * @psalm-pure
 *
 * @psalm-flow ($str) -> return
 */
function trim(string $str, string $character_mask = " \t\n\r\0\x0B") : string {}

/**
 * @psalm-pure
 *
 * @psalm-flow ($str) -> return
 */
function ltrim(string $str, string $character_mask = " \t\n\r\0\x0B") : string {}

/**
 * @psalm-pure
 *
 * @psalm-flow ($str) -> return
 */
function rtrim(string $str, string $character_mask = " \t\n\r\0\x0B") : string {}

/**
 * @psalm-pure
 *
 * @param string|array $glue
 *
 * @return (
 *     $glue is non-empty-string
 *     ? ($pieces is non-empty-array
 *         ? non-empty-string
 *         : string)
 *     : string
 * )
 *
 * @psalm-flow ($glue) -> return
 * @psalm-flow ($pieces) -(array-fetch)-> return
 */
function implode($glue, array $pieces = []) : string {}

/**
 * @psalm-pure
 *
 * @psalm-flow ($string) -(array-assignment)-> return
 */
function explode(string $delimiter, string $string, int $limit = -1) : array {}

/**
 * @psalm-pure
 *
 * @psalm-flow ($subject) -(array-assignment)-> return
 *
 * @template TFlags as 0|1|2|3|4|5|6|7
 *
 * @param TFlags $flags
 *
 * @return (TFlags is 0|2 ? non-empty-list<string>|false : (TFlags is 1|3 ? list<string>|false : list<array{string,int}>|false))
 *
 * @psalm-ignore-falsable-return
 */
function preg_split(string $pattern, string $subject, int $limit = -1, int $flags = 0) {}

/**
 * @param array $input
 *
 * @return (
 *     $input is array<int>
 *     ? int
 *     : ($input is array<float>
 *         ? float
 *         : float|int
 *     )
 * )
 */
function array_sum(array $input) {}

/**
 * @param array $input
 *
 * @return (
 *     $input is array<int>
 *     ? int
 *     : ($input is array<float>
 *         ? float
 *         : float|int
 *     )
 * )
 */
function array_product(array $input) {}

/**
 * @psalm-pure
 *
 * @psalm-taint-escape html
 * @psalm-flow ($str) -> return
 */
function strip_tags(string $str, ?string $allowable_tags = null) : string {}

/**
 * @psalm-pure
 *
 * @psalm-taint-escape html
 *
 * @psalm-flow ($string) -> return
 */
function htmlentities(string $string, ?int $quote_style = null, ?string $charset = null, bool $double_encode = true) : string {}

/**
 * @psalm-pure
 *
 * @psalm-taint-unescape html
 *
 * @psalm-flow ($string) -> return
 */
function html_entity_decode(string $string, ?int $quote_style = null, ?string $charset = null) : string {}

/**
 * @psalm-pure
 *
 * @psalm-taint-escape html
 * @psalm-taint-escape sql
 *
 * @psalm-flow ($string) -> return
 */
function htmlspecialchars(string $string, int $flags = ENT_COMPAT | ENT_HTML401, string $encoding = 'UTF-8', bool $double_encode = true) : string {}

/**
 * @psalm-pure
 *
 * @psalm-taint-unescape html
 * @psalm-taint-unescape sql
 *
 * @psalm-flow ($string) -> return
 */
function htmlspecialchars_decode(string $string, ?int $quote_style = null) : string {}

/**
 * @psalm-pure
 *
 * @param string|array<string|int|float> $search
 * @param string|array<string|int|float> $replace
 * @param string|array<string|int|float> $subject
 * @param int $count
 * @return ($subject is array ? array<string> : string)
 *
 * @psalm-flow ($replace, $subject) -> return
 */
function str_replace($search, $replace, $subject, &$count = null) {}

/**
 * @psalm-pure
 *
 * @param string|string[] $search
 * @param string|array<string|int|float> $replace
 * @param string|array<string|int|float> $subject
 * @param int $count
 * @return ($subject is array ? array<string> : string)
 *
 * @psalm-flow ($replace, $subject) -> return
 */
function preg_replace($search, $replace, $subject, int $limit = -1, &$count = null) {}

/**
 * @param string|string[] $search
 * @param callable(array<int, string>):string $replace
 * @param string|array<string|int|float> $subject
 * @param int $count
 * @return ($subject is array ? array<string> : string)
 *
 * @psalm-taint-specialize
 * @psalm-flow ($subject) -> return
 */
function preg_replace_callback($search, $replace, $subject, int $limit = -1, &$count = null) {}

/**
 * @psalm-pure
 * @template TFlags as int
 *
 * @param string $pattern
 * @param string $subject
 * @param mixed $matches
 * @param TFlags $flags
 * @param-out (
 *          TFlags is 1
 *          ? array<list<string>>
 *          : (TFlags is 2
 *              ? list<array<string>>
 *              : (TFlags is 256|257
 *                  ? array<list<array{string, int}>>
 *                  : (TFlags is 258
 *                      ? list<array<array{string, int}>>
 *                      : (TFlags is 512|513
 *                          ? array<list<?string>>
 *                          : (TFlags is 514
 *                              ? list<array<?string>>
 *                              : (TFlags is 770
 *                                  ? list<array<array{?string, int}>>
 *                                  : array
 *                              )
 *                          )
 *                      )
 *                  )
 *              )
 *          )
 *        ) $matches
 * @return int|false
 * @psalm-ignore-falsable-return
 */
function preg_match_all($pattern, $replace, &$matches = [], int $flags = 1, int $offset = 0) {}

/**
 * @psalm-pure
 *
 * @return string|false
 * @psalm-ignore-falsable-return
 *
 * @psalm-flow ($string) -> return
 */
function substr(string $string, int $start, ?int $length = null) {}

/**
 * @psalm-pure
 *
 * @psalm-flow ($str) -> return
 */
function preg_quote(string $str, ?string $delimiter = null) : string {}

/**
 * @psalm-pure
 *
 * @param string|int|float $args
 *
 * @psalm-flow ($format, $args) -> return
 */
function sprintf(string $format, ...$args) : string {}

/**
 * @psalm-pure
 *
 * @return string|false
 * @psalm-ignore-falsable-return
 *
 * @psalm-flow ($path) -> return
 */
function realpath(string $path) {}

/**
 * @psalm-pure
 *
 * @param numeric-string $left_operand
 * @param numeric-string $right_operand
 * @return ($right_operand is "0" ? null : numeric-string)
 */
function bcdiv(string $left_operand, string $right_operand, int $scale = 0): ?string {}

/**
 * @psalm-pure
 *
 * @param scalar|null|object $var
 * @return string The string value of var.
 *
 * @psalm-flow ($var) -> return
 */
function strval ($var): string {}

/**
 * @return ($input is non-empty-string ? non-empty-list<string> : non-empty-list<string>|array{null})
 * @psalm-pure
 */
function str_getcsv(string $input, string $delimiter = ',', string $enclosure = '"', string $escape = '\\\\')
{
}

/**
 * @return ($min is positive-int ? positive-int : int)
 */
function random_int(int $min, int $max): int {}

/**
 * @template TKey as array-key
 *
 * @param array<mixed, TKey> $array
 *
 * @return array<TKey, positive-int>
 *
 * @psalm-pure
 */
function array_count_values(array $array): array {}
