Replace tokenized URL with available token values
@return string
@param $url array|string
@param $args array
542540
function build($url,$args=[]) {
		$args+=$this->hive['PARAMS'];
		if (is_array($url))
			foreach ($url as &$var) {
				$var=$this->build($var,$args);
				unset($var);
			}
		else {
			$i=0;
			$url=preg_replace_callback('/@(\w+)|(\*)/',
				function($match) use(&$i,$args) {
					if (isset($match[1]) &&
						array_key_exists($match[1],$args))
						return $args[$match[1]];
					if (isset($match[2]) &&
						array_key_exists($match[2],$args)) {
						if (!is_array($args[$match[2]]))
							return $args[$match[2]];
						$i++;
						return $args[$match[2]][$i-1];
					}
					return $match[0];
				},$url);
		}
		return $url;
	}
592026
public function sendRequest($url, $args)
    {
        $ch = curl_init();
        $curlConfig = array(
            CURLOPT_URL            => $url,
            CURLOPT_POST           => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POSTFIELDS     => json_encode($args)
        );
        // print the array that was sent
        //echo "<pre>";
        //var_dump($args);
        curl_setopt_array($ch, $curlConfig);
        $result = curl_exec($ch);
        curl_close($ch);
    }
893400
private function _parseUrl($url) {
    $parse = parse_url($url);
    if (empty($parse) || !is_array($parse)) {
      throw new Exception("Host is empty.");
    }

    if (!isset($parse['port']) || !$parse['port']) {
      $parse['port'] = '80';
    }

    $parse['host'] = str_replace(
        array('http://', 'https://'),
        array('', 'ssl://'),
        $parse['scheme'] . "://"
    ) . $parse['host'];

    $parse["path"] = isset($parse["path"]) ? $parse["path"] : '/';
    $query = isset($parse['query']) ? $parse['query'] : '';

    $path = str_replace(array('\\', '//'), '/', $parse['path']);
    $parse['path'] = $query ? $path . "?" . $query : $path;

    return $parse;
  }
981566
public function buildQueryString($args = array()) {
		$args = array_merge($args, array("token" => $this->token));
		
		$query = "";
		if (isset($args)) {
			while (list($key, $val) = each($args)) {
				if ( strlen($query) > 0 ) {
					$query .= "&";
				} else {
					$query .= "?";
				}
				$query .= $key . '=' . $val;
			}
		}
		return $query;
	}
419492
private function buildUrl($url)
    {
        // URI template (absolute or relative)
        if (!is_array($url)) {
            return strpos($url, '://')
                ? (string) $url
                : (string) $this->baseUrl->combine($url);
        }

        if (!isset($url[1])) {
            throw new \InvalidArgumentException('You must provide a hash of '
                . 'varname options in the second element of a URL array.');
        }

        // Absolute URL
        if (strpos($url[0], '://')) {
            return Utils::uriTemplate($url[0], $url[1]);
        }

        // Combine the relative URL with the base URL
        return (string) $this->baseUrl->combine(
            Utils::uriTemplate($url[0], $url[1])
        );
    }
1277247
public static function ReplaceWithFlags( $arg1, $arg2, $replacement, $flagString )
	{
		$input = $arg1 instanceof Undefined
		    ? ""
		    : $arg1 . "";

		if ( $arg2 instanceof Undefined )
		    throw XPath2Exception::withErrorCodeAndParams( "XPTY0004", Resources::XPTY0004, array( "empty-sequence()", "xs:string in fn:replace" ) );

	    $flagString = ExtFuncs::PrepareRegexFlags( $flagString );
	    $pattern = ExtFuncs::PrepareRegexPattern( $arg2 . "", $flagString );

		if ( ! ExtFuncs::IsValidReplacementString( $replacement ) )
		    throw XPath2Exception::withErrorCodeAndParam( "FORX0004", Resources::FORX0004, $replacement );

		if (  preg_match( "/$pattern/", "" ) )
		{
			throw XPath2Exception::withErrorCodeAndParam( "FORX0003", Resources::FORX0003, $pattern );
		}

		return preg_replace( "/$pattern/$flagString", ExtFuncs::UnescapeReplacementString( $replacement ), $input );
	}
455520
public function updateURLWithParameters($url, array $params)
    {
        if (empty($params)) {
            return $url;
        }

        $parts = parse_url($url);

        $scheme = isset($parts['scheme']) ? $parts['scheme'] : null;
        if ($scheme) {
            $scheme .= ':';
        }

        $host = isset($parts['host']) ? $parts['host'] : null;
        if ($host) {
            $host = "//$host";
        }
        $path = isset($parts['path']) ? $parts['path'] : null;

        //Merge parameters
        $query = isset($parts['query']) ? $parts['query'] : null;
        $params += $this->getParameterFromQuery($query);
        if (!empty($params)) {
            $query = '?' . http_build_query($params);
        }

        $fragment = isset($parts['fragment']) ? $parts['fragment'] : null;
        if ($fragment) {
            $fragment = "#$fragment";
        }

        return "{$scheme}{$host}{$path}{$query}$fragment";
    }
486994
public static function multibyteParseUrl($url)
    {
        $enc_url = preg_replace_callback(
            '%[^:/@?&=#]+%usD',
            function ($matches) {
                return urlencode($matches[0]);
            },
            $url
        );

        $parts = parse_url($enc_url);

        if($parts === false) {
            throw new \InvalidArgumentException('Malformed URL: ' . $url);
        }

        foreach($parts as $name => $value) {
            $parts[$name] = urldecode($value);
        }

        return $parts;
    }
206613
public static function normalize(string $url, array $parameters = []):string
    {
        $normalizedUrl = $url;
        if (!empty($parameters)) {
            $normalizedUrl .= (false !== strpos($url, '?') ? '&' : '?') . http_build_query($parameters, '', '&');
        }
        return $normalizedUrl;
    }
625394
public static function request(
		$url,
		$args = [],
		$headers = []
	) {
		$headers = array_merge(
			$headers,
			[
				'Accept'     => 'application/vnd.github.v3+json',
				'User-Agent' => 'WP-CLI',
			]
		);

		$token = getenv( 'GITHUB_TOKEN' );
		if ( $token ) {
			$headers['Authorization'] = 'token ' . $token;
		}

		$verb = 'GET';
		if ( isset( $headers['http_verb'] ) ) {
			$verb = $headers['http_verb'];
			unset( $headers['http_verb'] );
		}

		if ( 'POST' === $verb ) {
			$args = json_encode( $args );
		}

		$response = Utils\http_request( $verb, $url, $args, $headers );

		if ( 20 !== (int) substr( $response->status_code, 0, 2 ) ) {
			if ( isset( $args['throw_errors'] ) && false === $args['throw_errors'] ) {
				return false;
			}

			WP_CLI::error(
				sprintf(
					"Failed request to $url\nGitHub API returned: %s (HTTP code %d)",
					$response->body,
					$response->status_code
				)
			);
		}

		return [ json_decode( $response->body ), $response->headers ];
	}
1058008
protected function prepareUrl($url)
    {
        $replacement = ($this->removeHostFromUrl ? '' : '$1') . ($this->removeScriptFromUrl ? '' : '$2');

        return preg_replace('#(https?\://[^/]+)(/[^/\.]+\.php)?#', $replacement, $url);
    }
736546
private function filterQueryAndFragment($arg) : string
    {
        if (!is_string($arg)) {
            throw new \InvalidArgumentException('Query and fragment must be a string');
        }

        $unreservedCharacter = preg_quote($this->unReservedCharacter, '/');
        $characterSubDelimiter = preg_quote($this->characterSubDelimiter, '/');
        return preg_replace_callback(
            '/(?:[^' . $unreservedCharacter . $characterSubDelimiter . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/',
            [$this, 'rawURLEncodeMatchZero'],
            $arg
        );
    }
16574
public static function formatString($str, $args)
    {
        foreach ($args as $k => $v) {
            $str = preg_replace('/:'. $k. ':/', $v, $str);
        }
        return $str;
    }
517987
private function parseToken($token, $args, $locale)
    {
        // parsing pattern based on ICU grammar:
        // http://icu-project.org/apiref/icu4c/classMessageFormat.html#details
        $charset = 'UTF-8';
        $param = trim($token[0]);
        if (isset($args[$param])) {
            $arg = $args[$param];
        } else {
            return '{' . implode(',', $token) . '}';
        }
        $type = isset($token[1]) ? trim($token[1]) : 'none';
        switch ($type) {
            case 'date':
            case 'time':
            case 'spellout':
            case 'ordinal':
            case 'duration':
            case 'choice':
            case 'selectordinal':
                throw new \Exception("Message format '$type' is not supported. You have to install PHP intl extension to use this feature.");
            case 'number':
                if (is_int($arg) && (! isset($token[2]) || trim($token[2]) === 'integer')) {
                    return $arg;
                }
                throw new \Exception("Message format 'number' is only supported for integer values. You have to install PHP intl extension to use this feature.");
            case 'none':
                return $arg;
            case 'select':
                /** http://icu-project.org/apiref/icu4c/classicu_1_1SelectFormat.html
                 *  selectStyle = (selector '{' message '}')+
                 */
                if (! isset($token[2])) {
                    return false;
                }
                $select = self::tokenizePattern($token[2]);
                $c = count($select);
                $message = false;
                for ($i = 0; $i + 1 < $c; $i++) {
                    if (is_array($select[$i]) || ! is_array($select[$i + 1])) {
                        return false;
                    }
                    $selector = trim($select[$i++]);
                    if ($message === false && $selector === 'other' || $selector == $arg) {
                        $message = implode(',', $select[$i]);
                    }
                }
                if ($message !== false) {
                    return $this->fallbackFormat($message, $args, $locale);
                }
                break;
            case 'plural':
                /* http://icu-project.org/apiref/icu4c/classicu_1_1PluralFormat.html
                pluralStyle = [offsetValue] (selector '{' message '}')+
                offsetValue = "offset:" number
                selector = explicitValue | keyword
                explicitValue = '=' number  // adjacent, no white space in between
                keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+
                message: see MessageFormat
                */
                if (! isset($token[2])) {
                    return false;
                }
                $plural = self::tokenizePattern($token[2]);
                $c = count($plural);
                $message = false;
                $offset = 0;
                for ($i = 0; $i + 1 < $c; $i++) {
                    if (is_array($plural[$i]) || ! is_array($plural[$i + 1])) {
                        return false;
                    }
                    $selector = trim($plural[$i++]);

                    if ($i == 1 && strncmp($selector, 'offset:', 7) === 0) {
                        $offset = (int)trim(mb_substr($selector, 7,
                            ($pos = mb_strpos(str_replace(["\n", "\r", "\t"], ' ', $selector), ' ', 7, $charset)) - 7,
                            $charset));
                        $selector = trim(mb_substr($selector, $pos + 1, null, $charset));
                    }
                    if ($message === false && $selector === 'other' ||
                        $selector[0] === '=' && (int)mb_substr($selector, 1, null, $charset) === $arg ||
                        $selector === 'one' && $arg - $offset == 1
                    ) {
                        $message = implode(',', str_replace('#', $arg - $offset, $plural[$i]));
                    }
                }
                if ($message !== false) {
                    return $this->fallbackFormat($message, $args, $locale);
                }
                break;
        }

        return false;
    }
261506
public function generateUrl($url, $token, $options, $availableOptions)
    {

        // Append client id
        $url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?').'client_id='.$this->getClientId();

        // Append token if provided
        if ($token) {
            $url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?').'oauth_token='.$this->getToken($token);
        }

        // Add options to the URL
        foreach ($options as $key => $value) {
            $url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?').$key.'='.$value;
        }

        return $url;
    }
362795
protected function urlEncode($url)
    {
        $reserved = [
            ":" => '!%3A!ui',
            "/" => '!%2F!ui',
            "?" => '!%3F!ui',
            "#" => '!%23!ui',
            "[" => '!%5B!ui',
            "]" => '!%5D!ui',
            "@" => '!%40!ui',
            "!" => '!%21!ui',
            "$" => '!%24!ui',
            "&" => '!%26!ui',
            "'" => '!%27!ui',
            "(" => '!%28!ui',
            ")" => '!%29!ui',
            "*" => '!%2A!ui',
            "+" => '!%2B!ui',
            "," => '!%2C!ui',
            ";" => '!%3B!ui',
            "=" => '!%3D!ui',
            "%" => '!%25!ui'
        ];
        return preg_replace(array_values($reserved), array_keys($reserved), rawurlencode($url));
    }
787353
public function redirect($url, $args = [])
    {
        if (isset($args['time'])) {
            $this->header('Refresh', $args['time'] . ';url=' . $url);
        } else if (isset($args['httpCode'])) {
            $this->header('Location', $url, true, $args['httpCode']);
        } else {
            $this->header('Location', $url, true, 302);
        }
        return '';
    }