src/Net/Host.php
<?php
/**
* This file is a part of the datatypes package.
*
* https://github.com/themichaelhall/datatypes
*/
declare(strict_types=1);
namespace DataTypes\Net;
use DataTypes\Net\Exceptions\HostInvalidArgumentException;
use DataTypes\Net\Exceptions\HostnameInvalidArgumentException;
/**
* Class representing a host.
*
* @since 1.0.0
*/
class Host implements HostInterface
{
/**
* Returns true if the host equals other host, false otherwise.
*
* @since 1.2.0
*
* @param HostInterface $host The other host.
*
* @return bool True if the host equals other host, false otherwise.
*/
public function equals(HostInterface $host): bool
{
if ($this->getIPAddress() !== null && $host->getIPAddress() !== null) {
return $this->getIPAddress()->equals($host->getIPAddress());
}
return $this->getHostname()->equals($host->getHostname());
}
/**
* Returns the hostname of the host.
*
* @since 1.0.0
*
* @return HostnameInterface The hostname of the host.
*/
public function getHostname(): HostnameInterface
{
if ($this->hostname === null) {
$ipAddressParts = $this->ipAddress->getParts();
return Hostname::fromParts([
strval($ipAddressParts[3]),
strval($ipAddressParts[2]),
strval($ipAddressParts[1]),
strval($ipAddressParts[0]),
'in-addr',
], 'arpa');
}
return $this->hostname;
}
/**
* Returns The IP address of the host or null if the host has no IP address.
*
* @since 1.0.0
*
* @return IPAddressInterface|null The IP address of the host or null if the host has no IP address.
*/
public function getIPAddress(): ?IPAddressInterface
{
return $this->ipAddress;
}
/**
* Returns the host as a string.
*
* @since 1.0.0
*
* @return string The host as a string.
*/
public function __toString(): string
{
if ($this->ipAddress !== null) {
return $this->ipAddress->__toString();
}
return $this->hostname->__toString();
}
/**
* Creates a host from a hostname.
*
* @since 1.0.0
*
* @param HostnameInterface $hostname The hostname.
*
* @return HostInterface The host.
*/
public static function fromHostname(HostnameInterface $hostname): HostInterface
{
return new self($hostname, null);
}
/**
* Creates a host from an IP address.
*
* @since 1.0.0
*
* @param IPAddressInterface $ipAddress
*
* @return HostInterface The host.
*/
public static function fromIPAddress(IPAddressInterface $ipAddress): HostInterface
{
return new self(null, $ipAddress);
}
/**
* Checks if a host is valid.
*
* @since 1.0.0
*
* @param string $string The host.
*
* @return bool True if the host parameter is a valid host, false otherwise.
*/
public static function isValid(string $string): bool
{
return self::doParse($string) !== null;
}
/**
* Parses a host.
*
* @since 1.0.0
*
* @param string $string The host.
*
* @throws HostInvalidArgumentException If the host parameter is not a valid host.
*
* @return HostInterface The Host instance.
*/
public static function parse(string $string): HostInterface
{
$result = self::doParse($string, $error);
if ($result === null) {
throw new HostInvalidArgumentException($error);
}
return $result;
}
/**
* Parses a host.
*
* @since 1.0.0
*
* @param string $string The host.
*
* @return HostInterface|null The Host instance if the host parameter is a valid host, null otherwise.
*/
public static function tryParse(string $string): ?HostInterface
{
return self::doParse($string);
}
/**
* Constructs a host from either a hostname or an IP address.
*
* @param HostnameInterface|null $hostname The hostname.
* @param IPAddressInterface|null $ipAddress The IP address.
*/
private function __construct(?HostnameInterface $hostname, ?IPAddressInterface $ipAddress)
{
$this->hostname = $hostname;
$this->ipAddress = $ipAddress;
}
/**
* Tries to parse a host and returns the result or error text.
*
* @param string $str The host to parse.
* @param string|null $error The error text if parsing was not successful, undefined otherwise.
*
* @return self|null The host if parsing was successful, null otherwise.
*/
private static function doParse(string $str, ?string &$error = null): ?self
{
if ($str === '') {
$error = 'Host "' . $str . '" is empty.';
return null;
}
$hostname = null;
$ipAddress = null;
try {
$hostname = Hostname::parse($str);
} catch (HostnameInvalidArgumentException $e) {
$error = 'Host "' . $str . '" is invalid: ' . $e->getMessage();
$ipAddress = IPAddress::tryParse($str);
if ($ipAddress === null) {
return null;
}
}
return new self($hostname, $ipAddress);
}
/**
* @var HostnameInterface|null The hostname.
*/
private ?HostnameInterface $hostname;
/**
* @var IPAddressInterface|null The IP address.
*/
private ?IPAddressInterface $ipAddress;
}