|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
namespace Yggverse\Net;
|
|
|
|
|
|
|
|
class Address
|
|
|
|
{
|
|
|
|
private ?string $_scheme = null;
|
|
|
|
private ?string $_host = null;
|
|
|
|
private ?string $_user = null;
|
|
|
|
private ?string $_pass = null;
|
|
|
|
private ?int $_port = null;
|
|
|
|
private ?string $_path = null;
|
|
|
|
private ?string $_query = null;
|
|
|
|
private ?string $_fragment = null;
|
|
|
|
|
|
|
|
private string $_separator = '/';
|
|
|
|
|
|
|
|
private array $_segments = [];
|
|
|
|
|
|
|
|
public function __construct(?string $address = null)
|
|
|
|
{
|
|
|
|
if ($address)
|
|
|
|
{
|
|
|
|
if ($scheme = parse_url($address, PHP_URL_SCHEME))
|
|
|
|
{
|
|
|
|
$this->setScheme(
|
|
|
|
(string) $scheme
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($user = parse_url($address, PHP_URL_USER))
|
|
|
|
{
|
|
|
|
$this->setUser(
|
|
|
|
(string) $user
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($pass = parse_url($address, PHP_URL_PASS))
|
|
|
|
{
|
|
|
|
$this->setPass(
|
|
|
|
(string) $pass
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($host = parse_url($address, PHP_URL_HOST))
|
|
|
|
{
|
|
|
|
$this->setHost(
|
|
|
|
(string) $host
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($port = parse_url($address, PHP_URL_PORT))
|
|
|
|
{
|
|
|
|
$this->setPort(
|
|
|
|
(int) $port
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($path = parse_url($address, PHP_URL_PATH))
|
|
|
|
{
|
|
|
|
$this->setPath(
|
|
|
|
(string) $path
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($query = parse_url($address, PHP_URL_QUERY))
|
|
|
|
{
|
|
|
|
$this->setQuery(
|
|
|
|
(string) $query
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($fragment = parse_url($address, PHP_URL_FRAGMENT))
|
|
|
|
{
|
|
|
|
$this->setFragment(
|
|
|
|
(string) $fragment
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function isAbsolute(): bool
|
|
|
|
{
|
|
|
|
return ($this->_scheme && $this->_host);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function isRelative(): bool
|
|
|
|
{
|
|
|
|
return !$this->isAbsolute();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getScheme(): ?string
|
|
|
|
{
|
|
|
|
return $this->_scheme;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setScheme(?string $value): void
|
|
|
|
{
|
|
|
|
$this->_scheme = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getHost(): ?string
|
|
|
|
{
|
|
|
|
return $this->_host;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setHost(?string $value): void
|
|
|
|
{
|
|
|
|
$this->_host = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getUser(): ?string
|
|
|
|
{
|
|
|
|
return $this->_user;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setUser(?string $value): void
|
|
|
|
{
|
|
|
|
$this->_user = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPass(): ?string
|
|
|
|
{
|
|
|
|
return $this->_pass;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setPass(?string $value): void
|
|
|
|
{
|
|
|
|
$this->_pass = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPort(): ?int
|
|
|
|
{
|
|
|
|
return $this->_port;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setPort(?int $value): void
|
|
|
|
{
|
|
|
|
$this->_port = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPath(): ?string
|
|
|
|
{
|
|
|
|
return $this->_path;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setPath(?string $value): void
|
|
|
|
{
|
|
|
|
if (false !== strpos($value, '\\'))
|
|
|
|
{
|
|
|
|
$this->setSeparator(
|
|
|
|
'\\'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->_segments = explode(
|
|
|
|
$this->_separator,
|
|
|
|
$value
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->_path = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getSegments(): array
|
|
|
|
{
|
|
|
|
return $this->_segments;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getQuery(): ?string
|
|
|
|
{
|
|
|
|
return $this->_query;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setQuery(?string $value): void
|
|
|
|
{
|
|
|
|
$this->_query = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getFragment(): ?string
|
|
|
|
{
|
|
|
|
return $this->_fragment;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setFragment(?string $value): void
|
|
|
|
{
|
|
|
|
$this->_fragment = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getSeparator(): string
|
|
|
|
{
|
|
|
|
return $this->_separator;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setSeparator(?string $value): void
|
|
|
|
{
|
|
|
|
$this->_separator = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function get(
|
|
|
|
bool $scheme = true,
|
|
|
|
bool $user = true,
|
|
|
|
bool $pass = true,
|
|
|
|
bool $host = true,
|
|
|
|
bool $port = true,
|
|
|
|
bool $path = true,
|
|
|
|
bool $query = true,
|
|
|
|
bool $fragment = true,
|
|
|
|
): string
|
|
|
|
{
|
|
|
|
$address = '';
|
|
|
|
|
|
|
|
if ($scheme && $this->getScheme())
|
|
|
|
{
|
|
|
|
$address .= sprintf(
|
|
|
|
'%s:%s%s',
|
|
|
|
$this->getScheme(),
|
|
|
|
$this->getSeparator(),
|
|
|
|
$this->getSeparator()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($user && $this->getUser())
|
|
|
|
{
|
|
|
|
if ($pass && $this->getPass())
|
|
|
|
{
|
|
|
|
$address .= sprintf(
|
|
|
|
'%s:%s@',
|
|
|
|
$this->getUser(),
|
|
|
|
$this->getPass()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$address .= sprintf(
|
|
|
|
'%s@',
|
|
|
|
$this->getUser()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($host && $this->getHost())
|
|
|
|
{
|
|
|
|
$address .= $this->getHost();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($port && $this->getPort())
|
|
|
|
{
|
|
|
|
$address .= sprintf(
|
|
|
|
':%d',
|
|
|
|
$this->getPort()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($path && $this->getPath())
|
|
|
|
{
|
|
|
|
if (!str_starts_with($this->getPath(), $this->getSeparator()))
|
|
|
|
{
|
|
|
|
$address .= $this->getSeparator();
|
|
|
|
}
|
|
|
|
|
|
|
|
$address .= $this->getPath();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($query && $this->getQuery())
|
|
|
|
{
|
|
|
|
$address .= sprintf(
|
|
|
|
'?%s',
|
|
|
|
$this->getQuery()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($fragment && $this->getFragment())
|
|
|
|
{
|
|
|
|
$address .= sprintf(
|
|
|
|
'#%s',
|
|
|
|
$this->getFragment()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $address;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function toAbsolute(
|
|
|
|
\Yggverse\Net\Address $base
|
|
|
|
): bool
|
|
|
|
{
|
|
|
|
if ($this->isAbsolute())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($base->isRelative())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->setScheme(
|
|
|
|
$base->getScheme()
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->setUser(
|
|
|
|
$base->getUser()
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->setPass(
|
|
|
|
$base->getPass()
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->setHost(
|
|
|
|
$base->getHost()
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->setPort(
|
|
|
|
$base->getPort()
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->setSeparator(
|
|
|
|
$base->getSeparator()
|
|
|
|
);
|
|
|
|
|
|
|
|
if (str_starts_with((string) $this->getPath(), $this->getSeparator()))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($path = $this->getPath())
|
|
|
|
{
|
|
|
|
$prefix = array_reverse(
|
|
|
|
$base->getSegments()
|
|
|
|
);
|
|
|
|
|
|
|
|
array_shift(
|
|
|
|
$prefix
|
|
|
|
);
|
|
|
|
|
|
|
|
$navigate = true;
|
|
|
|
|
|
|
|
$postfix = [];
|
|
|
|
|
|
|
|
foreach ($this->getSegments() as $index => $segment)
|
|
|
|
{
|
|
|
|
if ($segment == '.')
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($navigate && $segment == '..')
|
|
|
|
{
|
|
|
|
if (empty($prefix[$index]))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
unset(
|
|
|
|
$prefix[$index]
|
|
|
|
);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$navigate = false;
|
|
|
|
|
|
|
|
$postfix[] = $segment;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->setPath(
|
|
|
|
implode(
|
|
|
|
$this->getSeparator(),
|
|
|
|
array_merge(
|
|
|
|
array_reverse(
|
|
|
|
$prefix
|
|
|
|
),
|
|
|
|
$postfix
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// @TODO deprecated, legacy needs only
|
|
|
|
public function getAbsolute(
|
|
|
|
\Yggverse\Net\Address $base
|
|
|
|
): ?string
|
|
|
|
{
|
|
|
|
if ($this->toAbsolute($base))
|
|
|
|
{
|
|
|
|
return $this->get();
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|