public static function unparseQueryString(array $input, bool $decode = false,
        string $ignoredKeys = null, bool $stripTags = true, bool $normalizeArrays = true): string
    {
        if ($ignoredKeys != '') {
            $ignoredKeys = explode(',', $ignoredKeys);
            foreach ($input as $key => $_) {
                if (in_array($key, $ignoredKeys)) {
                    unset($input[$key]);
                }
            }
        }

        // fix skipped NULL values by http_build_query()
        static $filter; if ($filter == null) {
            $filter = function ($var) use (&$filter) {
                foreach ($var as $key => $value) {
                    $var[$key] = is_array($value) ? $filter($value) : strval($value);
                }
                return $var;
            };
        }

        $query = http_build_query($filter($input));
        if ($decode) {
            $query = urldecode($query);
        }
        if ($stripTags && strpos($query, '%3C')) {
            $query = preg_replace('~%3C[\w]+(%2F)?%3E~ismU', '', $query);
        }
        if ($normalizeArrays && strpos($query, '%5D')) {
            $query = preg_replace('~([\w\.\-]+)%5B([\w\.\-]+)%5D(=)?~iU', '\1[\2]\3', $query);
        }

        return trim($query);
    }