Network tools Library for PHP with native Yggdrasil / IPv6 support
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

384 lines
7.9 KiB

<?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 getAbsolute(
\Yggverse\Net\Address $base
): ?string
{
if ($this->isAbsolute())
{
return $this->get();
}
if ($base->isRelative())
{
return null;
}
$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 $this->get();
}
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 null;
}
unset(
$prefix[$index]
);
continue;
}
$navigate = false;
$postfix[] = $segment;
}
$this->setPath(
implode(
$this->getSeparator(),
array_merge(
array_reverse(
$prefix
),
$postfix
)
)
);
}
return $this->get();
}
}