uiharu/src/Url.php

218 lines
6 KiB
PHP

<?php
namespace Uiharu;
use InvalidArgumentException;
final class Url {
private string $scheme = '';
private string $host = '';
private int $port = 0;
private string $user = '';
private string $pass = '';
private string $path = '';
private string $query = '';
private string $fragment = '';
private ?string $formatted = null;
public function __construct(array $parts) {
if(isset($parts['scheme']))
$this->scheme = strtolower($parts['scheme']);
if(isset($parts['host']))
$this->host = $parts['host'];
if(isset($parts['port']))
$this->port = $parts['port'];
if(isset($parts['user']))
$this->user = $parts['user'];
if(isset($parts['pass']))
$this->pass = $parts['pass'];
if(isset($parts['path']))
$this->path = $parts['path'];
if(isset($parts['query']))
$this->query = $parts['query'];
if(isset($parts['fragment']))
$this->fragment = $parts['fragment'];
}
public static function parse(string $urlString): Url {
$parts = parse_url($urlString);
if($parts === false)
throw new InvalidArgumentException('Invalid URL provided.');
return new Url($parts);
}
public function resetString(): void {
$this->formatted = null;
}
public function setScheme(string $scheme): void {
$this->scheme = $scheme;
$this->resetString();
}
public function discardFragment(): void {
$this->fragment = '';
$this->resetString();
}
public function hasScheme(): bool {
return $this->scheme !== '';
}
public function hasHost(): bool {
return $this->host !== '';
}
public function hasPort(): bool {
return $this->port !== 0;
}
public function hasUser(): bool {
return $this->user !== '';
}
public function hasPassword(): bool {
return $this->pass !== '';
}
public function hasPath(): bool {
return $this->path !== '';
}
public function hasQuery(): bool {
return $this->query !== '';
}
public function hasFragment(): bool {
return $this->fragment !== '';
}
public function getScheme(): string {
return $this->scheme;
}
public function getHost(): string {
return $this->host;
}
public function getPort(): int {
return $this->port;
}
public function getUser(): string {
return $this->user;
}
public function getPassword(): string {
return $this->pass;
}
public function getPath(): string {
return $this->path;
}
public function getQuery(): string {
return $this->query;
}
public function getFragment(): string {
return $this->fragment;
}
public function hasUserInfo(): bool {
return $this->hasUser()
|| $this->hasPassword();
}
public function hasAuthority(): bool {
return $this->hasUserInfo()
|| $this->hasHost();
}
public function getUserInfo(): string {
$userInfo = $this->user;
if($this->pass !== '')
$userInfo .= ':' . $this->pass;
return $userInfo;
}
public function getAuthority(): string {
$authority = '//';
if($this->hasUserInfo())
$authority .= $this->getUserInfo() . '@';
$authority .= $this->host;
if($this->port !== 0)
$authority .= ':' . $this->port;
return $authority;
}
public function calculateHash(bool $raw = true): string {
return hash('sha256', (string)$this, $raw);
}
public function isHTTP(): bool {
return $this->scheme === 'http';
}
public function isHTTPS(): bool {
return $this->scheme === 'https';
}
public function isWeb(): bool {
return $this->scheme === 'https'
|| $this->scheme === 'http';
}
public function __toString(): string {
if($this->formatted === null) {
$string = '';
if($this->hasScheme())
$string .= $this->getScheme() . ':';
$hasAuthority = $this->hasAuthority();
if($hasAuthority)
$string .= $this->getAuthority();
$hasPath = $this->hasPath();
$path = $this->getPath();
if($hasAuthority && (!$hasPath || $path[0] !== '/'))
$string .= '/';
elseif(!$hasAuthority && $path[1] === '/')
$path = '/' . trim($path, '/');
$string .= $path;
// is all this necessary...?
if($this->hasQuery()) {
$string .= '?';
$parts = explode('&', $this->getQuery());
foreach($parts as $part) {
$param = explode('=', $part, 2);
$string .= rawurlencode($param[0]);
if(isset($param[1]))
$string .= '=' . rawurlencode($param[1]);
$string .= '&';
}
$string = substr($string, 0, -1);
}
if($this->hasFragment())
$string .= '#' . rawurlencode($this->getFragment());
$this->formatted = $string;
}
return $this->formatted;
}
public function toV1(): array {
$parts = ['uri' => (string)$this];
if($this->hasScheme())
$parts['scheme'] = $this->getScheme();
if($this->hasHost())
$parts['host'] = $this->getHost();
if($this->hasPort())
$parts['port'] = $this->getPort();
if($this->hasUser())
$parts['user'] = $this->getUser();
if($this->hasPassword())
$parts['pass'] = $parts['password'] = $this->getPassword();
if($this->hasPath())
$parts['path'] = $this->getPath();
if($this->hasQuery())
$parts['query'] = $this->getQuery();
if($this->hasFragment())
$parts['fragment'] = $this->getFragment();
return $parts;
}
}