You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
418 lines
10 KiB
PHP
418 lines
10 KiB
PHP
<?php
|
|
|
|
namespace jrosset\UrlInfo;
|
|
|
|
use jrosset\Collections\Collection;
|
|
use jrosset\Collections\ICollection;
|
|
use jrosset\Collections\IImmutableCollection;
|
|
use jrosset\Collections\ImmutableCollection;
|
|
|
|
/**
|
|
* An utils class about URL parts
|
|
*/
|
|
class UrlInfo {
|
|
/**
|
|
* @var string|null The URL protocol
|
|
*/
|
|
private ?string $protocol;
|
|
/**
|
|
* @var string|null The URL host
|
|
*/
|
|
private ?string $host;
|
|
/**
|
|
* @var int|null The URL port
|
|
*/
|
|
private ?int $port;
|
|
/**
|
|
* @var string|null The URL username
|
|
*/
|
|
private ?string $user;
|
|
/**
|
|
* @var string|null The URL password
|
|
*/
|
|
private ?string $pass;
|
|
/**
|
|
* @var ICollection The parts of the URL path
|
|
*/
|
|
private ICollection $pathParts;
|
|
/**
|
|
* @var ICollection The URL arguments
|
|
*/
|
|
private ICollection $arguments;
|
|
/**
|
|
* @var string|null The URL anchor
|
|
*/
|
|
private ?string $anchor;
|
|
|
|
/**
|
|
* Initialize the class
|
|
*
|
|
* @param string|null $url The initial URL to parse
|
|
*/
|
|
public function __construct (?string $url = null) {
|
|
$this->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;
|
|
}
|
|
} |