diff --git a/src/parser/PhutilURI.php b/src/parser/PhutilURI.php --- a/src/parser/PhutilURI.php +++ b/src/parser/PhutilURI.php @@ -27,7 +27,7 @@ const TYPE_URI = 'uri'; const TYPE_GIT = 'git'; - public function __construct($uri) { + public function __construct($uri, $params = array()) { if ($uri instanceof PhutilURI) { $this->protocol = $uri->protocol; $this->user = $uri->user; @@ -41,7 +41,7 @@ return; } - $uri = (string)$uri; + $uri = phutil_string_cast($uri); $type = self::TYPE_URI; @@ -134,6 +134,8 @@ $this->fragment = idx($parts, 'fragment', ''); $this->type = $type; + + $this->initializeQueryParams($uri, $params); } public function __toString() { @@ -297,6 +299,35 @@ return $this->insertQueryParam($key, $value); } + public function removeAllQueryParams() { + $this->query = array(); + return $this; + } + + public function removeQueryParam($remove_key) { + list($remove_key) = phutil_http_parameter_pair($remove_key, ''); + + foreach ($this->query as $idx => $pair) { + list($key, $value) = $pair; + + if ($key !== $remove_key) { + continue; + } + + unset($this->query[$idx]); + } + + $this->query = array_values($this->query); + + return $this; + } + + public function replaceQueryParam($replace_key, $replace_value) { + $this->removeQueryParam($replace_key); + $this->appendQueryParam($replace_key, $replace_value); + return $this; + } + private function insertQueryParam($key, $value, $idx = null) { list($key, $value) = phutil_http_parameter_pair($key, $value); @@ -309,6 +340,38 @@ return $this; } + private function initializeQueryParams($uri, array $params) { + $have_params = array(); + foreach ($this->query as $pair) { + list($key) = $pair; + $have_params[$key] = true; + } + + foreach ($params as $key => $value) { + if (isset($have_params[$key])) { + throw new InvalidArgumentException( + pht( + 'Parameters specified when initializing PhutilURI collide with '. + 'parameters in the query string: both the query string (for "%s") '. + 'and the parameter map specify a parameter named "%s". When '. + 'initializing a URI, parameters may not be duplicated across the '. + 'query string and parameter map because intent (append or '. + 'replace?) is ambiguous. Instead, construct the URI without '. + 'parameters, then explicitly append or replace parameters.', + $uri, + $key)); + } + + if ($value === null) { + continue; + } + + $this->appendQueryParam($key, $value); + } + + return $this; + } + public function setProtocol($protocol) { $this->protocol = $protocol; return $this; diff --git a/src/utils/utils.php b/src/utils/utils.php --- a/src/utils/utils.php +++ b/src/utils/utils.php @@ -1623,7 +1623,7 @@ $ex); } - $key = (string)$key; + $key = phutil_string_cast($key); try { assert_stringlike($value); @@ -1635,7 +1635,7 @@ $ex); } - $value = (string)$value; + $value = phutil_string_cast($value); return array($key, $value); }