WordPress Version: 6.3
/**
* Retrieves a modified URL query string.
*
* You can rebuild the URL and append query variables to the URL query by using this function.
* There are two ways to use this function; either a single key and value, or an associative array.
*
* Using a single key and value:
*
* add_query_arg( 'key', 'value', 'http://example.com' );
*
* Using an associative array:
*
* add_query_arg( array(
* 'key1' => 'value1',
* 'key2' => 'value2',
* ), 'http://example.com' );
*
* Omitting the URL from either use results in the current URL being used
* (the value of `$_SERVER['REQUEST_URI']`).
*
* Values are expected to be encoded appropriately with urlencode() or rawurlencode().
*
* Setting any query variable's value to boolean false removes the key (see remove_query_arg()).
*
* Important: The return value of add_query_arg() is not escaped by default. Output should be
* late-escaped with esc_url() or similar to help prevent vulnerability to cross-site scripting
* (XSS) attacks.
*
* @since 1.5.0
* @since 5.3.0 Formalized the existing and already documented parameters
* by adding `...$args` to the function signature.
*
* @param string|array $key Either a query variable key, or an associative array of query variables.
* @param string $value Optional. Either a query variable value, or a URL to act upon.
* @param string $url Optional. A URL to act upon.
* @return string New URL query string (unescaped).
*/
function add_query_arg(...$args)
{
if (is_array($args[0])) {
if (count($args) < 2 || false === $args[1]) {
$uri = $_SERVER['REQUEST_URI'];
} else {
$uri = $args[1];
}
} else if (count($args) < 3 || false === $args[2]) {
$uri = $_SERVER['REQUEST_URI'];
} else {
$uri = $args[2];
}
$frag = strstr($uri, '#');
if ($frag) {
$uri = substr($uri, 0, -strlen($frag));
} else {
$frag = '';
}
if (0 === stripos($uri, 'http://')) {
$protocol = 'http://';
$uri = substr($uri, 7);
} elseif (0 === stripos($uri, 'https://')) {
$protocol = 'https://';
$uri = substr($uri, 8);
} else {
$protocol = '';
}
if (str_contains($uri, '?')) {
list($base, $query) = explode('?', $uri, 2);
$base .= '?';
} elseif ($protocol || !str_contains($uri, '=')) {
$base = $uri . '?';
$query = '';
} else {
$base = '';
$query = $uri;
}
wp_parse_str($query, $qs);
$qs = urlencode_deep($qs);
// This re-URL-encodes things that were already in the query string.
if (is_array($args[0])) {
foreach ($args[0] as $k => $v) {
$qs[$k] = $v;
}
} else {
$qs[$args[0]] = $args[1];
}
foreach ($qs as $k => $v) {
if (false === $v) {
unset($qs[$k]);
}
}
$ret = build_query($qs);
$ret = trim($ret, '?');
$ret = preg_replace('#=(&|$)#', '$1', $ret);
$ret = $protocol . $base . $ret . $frag;
$ret = rtrim($ret, '?');
$ret = str_replace('?#', '#', $ret);
return $ret;
}