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.
PhpUrlInfo/src/UrlInfo/UrlInfo.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;
}
}