parse($uri); } public static function from(string|UriInterface $uri = "") : UriInterface { if ($uri instanceof UriInterface) { return $uri; } return new static($uri); } protected function parse(string $uri): void { if (false === $parts = parse_url($uri)) { throw new \InvalidArgumentException(sprintf("Malformed URIs was provided (%s)", $uri)); } $this->setScheme($parts['scheme'] ?? ""); $this->setUserInfo($parts['user'] ?? null, $parts['pass'] ?? null); $this->setHost($parts['host'] ?? ""); $this->setPort($parts['port'] ?? null); $this->setPath($parts['path'] ?? null); $this->setQuery($parts['query'] ?? []); $this->setFragment($parts['fragment'] ?? null); } public function getScheme() { return $this->scheme; } public function renderScheme() : string { return $this->scheme ? "{$this->scheme}:" : ""; } protected function setScheme(string $scheme) : self { $this->scheme = $scheme; return $this; } public function getAuthority() : string { return implode('', array_filter([ $this->getHost(), $this->renderUserInfo(), $this->renderPort(), $this->renderFragment() ])); } public function renderAuthority() : string { $authority = $this->getAuthority(); return $authority ? "//{$authority}" : $authority; } public function getUserInfo() : string { return $this->user . ( $this->password ? ":{$this->password}" : "" ); } public function renderUserInfo() : string { return ( $info = $this->getUserInfo() ) ? "{$info}@" : ""; } public function getHost() { return $this->host; } protected function setHost(string $host) : static { $this->host = $host; return $this; } public function getPort() { return $this->port; } public function renderPort(array $ignore = self::IGNORE_HTTP_PORT) : string { $port = $this->getPort(); return $port && ! in_array($port, $ignore) ? ":{$port}" : ""; } public function getPath() { $path = implode('/', array_map('rawurlencode', explode('/', $this->path))); return str_starts_with($this->path, '/') ? '/' . ltrim($this->path, '/.') : $this->path; } public function renderPath() : string { return $this->getPath(); } public function getQuery() { return http_build_query($this->query, "", null, PHP_QUERY_RFC3986); } public function renderQuery() : string { $query = $this->getQuery(); return $query ? "?{$query}" : ""; } public function getFragment() { return rawurlencode($this->fragment ? "#{$this->fragment}" : ""); } public function renderFragment() : string { return $this->getFragment(); } public function withScheme($scheme) { return (clone $this)->setScheme($scheme); } public function withUserInfo($user, $password = null) { return (clone $this)->setUserInfo($user, $password); } protected function setUserInfo(null|string $user, null|string $password) : static { $this->user = $user; $this->password = $password; return $this; } public function withHost($host) { return (clone $this)->setHost($host); } public function withPort($port) { return (clone $this)->setPort($port); } protected function setPort(null|int $port) : static { $this->port = $port; return $this; } public function withPath($path) { return (clone $this)->setPath($path); } protected function setPath(null|string $path) : static { $this->path = $path; return $this; } public function withQuery($query) { return $this->setQuery($query); } protected function setQuery(null|array|string $query) : static { if (is_string($query)) { parse_str($query, $parsed); } $this->query = $parsed ?? $query; return $this; } public function withFragment($fragment) { return (clone $this)->setFragment($fragment); } protected function setFragment(null|string $fragment) : static { $this->fragment = $fragment; return $this; } public function __toString() { return $this->render(); } public function render() : string { return implode('', array_filter([ $this->renderScheme(), $this->renderAuthority(), $this->renderPath(), $this->renderQuery(), $this->renderFragment() ])); } }