setProtocol(); $this->setHost(); $this->setPort(); $this->setUser(); $this->setPathParts(); $this->setArguments(); $this->setAnchor(); if ($url !== null && $url !== '') { $this->parse($url); } } /** * Build the URL from its components * * @return string The URL */ public function __toString (): string { return $this->build(); } /** * Ensure the return value is null if the given is an empty string * * @param string|null $value The value to check * * @return string|null The value checked */ protected static final function ensureNull (?string $value): ?string { return $value === '' ? null : $value; } /** * Parse a URL to its components * * @param string $url The URL to parse * * @return void */ protected function parse (string $url): void { $info = parse_url($url); $this->setProtocol($info['scheme'] ?? null); $this->setHost($info['host'] ?? null); $this->setPort($info['port'] ?? null); $this->setUser($info['user'] ?? null); $this->setPass($info['pass'] ?? null); $this->setPath($info['path'] ?? null); $this->setArgumentsFromString($info['query'] ?? null); $this->setAnchor($info['fragment'] ?? null); } /** * Build the URL from its components * * @return string The URL */ public function build (): string { $url = ''; if ($this->hasProtocol()) { $url .= $this->getProtocol() . '://'; } if ($this->hasUser()) { $url .= $this->getUser(); } if ($this->hasPass()) { $url .= ':' . $this->getPass(); } if ($this->hasHost()) { $url .= ($this->hasUser() || $this->hasPass() ? '@' : '') . $this->getHost(); } if ($this->hasPort()) { $url .= ':' . $this->getPort(); } if ($this->hasPath()) { $url .= ($this->hasHost() && !$this->isPathAbsolute() ? '/' : '') . $this->getPath(); } if ($this->hasArguments()) { $url .= '?' . $this->getArgumentsAsString(); } if ($this->hasAnchor()) { $url .= '#' . $this->getAnchor(); } return $url; } /** * Is the URL protocol set ? * * @return bool Is the URL protocol set ? */ public function hasProtocol (): bool { return $this->protocol !== null; } /** * The URL protocol * * @return string|null The URL protocol */ public function getProtocol (): ?string { return $this->protocol; } /** * Set the URL protocol * * @param string|null $protocol The new URL protocol * * @return $this */ public function setProtocol (?string $protocol = null): self { $this->protocol = self::ensureNull(mb_strtolower($protocol)); return $this; } /** * Is the URL host set ? * * @return bool Is the URL host set ? */ public function hasHost (): bool { return $this->host !== null; } /** * The URL host * * @return string|null The URL host */ public function getHost (): ?string { return $this->host; } /** * Set the URL host * * @param string|null $host The new URL host * * @return $this */ public function setHost (?string $host = null): self { $this->host = self::ensureNull(mb_strtolower($host)); return $this; } /** * Is the URL port set ? * * @return bool Is the URL port set ? */ public function hasPort (): bool { return $this->port !== null; } /** * The URL port * * @return int|null The URL port */ public function getPort (): ?int { return $this->port; } /** * Set the URL port * * @param int|null $port The new URL port * * @return $this */ public function setPort (?int $port = null): self { $this->port = $port; return $this; } /** * Is the URL username set ? * * @return bool Is the URL username set ? */ public function hasUser (): bool { return $this->user !== null; } /** * The URL username * * @return string|null The URL username */ public function getUser (): ?string { return $this->user; } /** * Set the URL username * * @param string|null $user The new URL username * * @return $this */ public function setUser (?string $user = null): self { $this->user = self::ensureNull($user); return $this; } /** * Is the URL password set ? * * @return bool Is the URL password set ? */ public function hasPass (): bool { return $this->pass !== null; } /** * The URL password * * @return string|null The URL password */ public function getPass (): ?string { return $this->pass; } /** * Set the URL password * * @param string|null $pass The new URL password * * @return $this */ public function setPass (?string $pass = null): self { $this->pass = self::ensureNull($pass); return $this; } /** * Is the URL path set ? * * @return bool Is the URL path set ? */ public function hasPath (): bool { return $this->hasPathParts(); } /** * Is the URL path parts set ? * * @return bool Is the URL path set ? */ public function hasPathParts (): bool { return count($this->pathParts) > 0; } /** * Is the URL path absolute ? * * @return bool Is the URL path absolute ? */ public function isPathAbsolute (): bool { return $this->hasPathParts() && $this->pathParts[0] === ''; } /** * The URL path * * @return string|null The URL path */ public function getPath (): ?string { return $this->hasPathParts() ? preg_replace('#/{2,}#', '/', $this->getPathParts()->join('/')) : null; } /** * The URL path parts * * @return ICollection The URL path parts */ public function getPathParts (): ICollection { return $this->pathParts; } /** * Set the URL path * * @param string|null $path The new URL path * * @return $this */ public function setPath (?string $path = null): self { return $this->setPathParts(ImmutableCollection::split($path ?? '', '/')); } /** * Set the URL path parts * * @param IImmutableCollection|null $pathParts The new URL path parts * * @return $this */ public function setPathParts (?IImmutableCollection $pathParts = null): self { $this->pathParts = new Collection($pathParts); return $this; } /** * Is the URL arguments set ? * * @return bool Is the URL arguments set ? */ public function hasArguments (): bool { return count($this->arguments) > 0; } /** * The URL arguments * * @return ICollection The URL arguments */ public function getArguments (): ICollection { return $this->arguments; } /** * The URL arguments as a string * * @param int $encoding_type The ISO-norm to use for encoding * * @return string The URL arguments as a string */ public function getArgumentsAsString (int $encoding_type = PHP_QUERY_RFC1738): string { return http_build_query($this->getArguments()->toArray(), '', null, $encoding_type); } /** * Set the URL arguments * * @param IImmutableCollection|null $arguments The new URL arguments * * @return $this */ public function setArguments (?IImmutableCollection $arguments = null): self { $this->arguments = new Collection($arguments); return $this; } /** * Set the URL arguments from a string * * @param string|null $arguments The new URL arguments string * * @return $this */ public function setArgumentsFromString (?string $arguments = null): self { $argumentsArray = []; if ($arguments !== null && $arguments !== '') { parse_str($arguments, $argumentsArray); } return $this->setArguments(new Collection($argumentsArray)); } /** * Is the URL anchor set ? * * @return bool Is the URL anchor set ? */ public function hasAnchor (): bool { return $this->anchor !== null; } /** * The URL anchor * * @return string|null The URL anchor */ public function getAnchor (): ?string { return $this->anchor; } /** * Set the URL anchor * * @param string|null $anchor The new URL anchor * * @return $this */ public function setAnchor (?string $anchor = null): self { $this->anchor = self::ensureNull($anchor); return $this; } }