Pandabot/vendor/league/uri-components/Components/Domain.php

388 lines
10 KiB
PHP
Executable file

<?php
/**
* League.Uri (https://uri.thephpleague.com)
*
* (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace League\Uri\Components;
use Iterator;
use League\Uri\Contracts\AuthorityInterface;
use League\Uri\Contracts\DomainHostInterface;
use League\Uri\Contracts\HostInterface;
use League\Uri\Contracts\UriComponentInterface;
use League\Uri\Contracts\UriInterface;
use League\Uri\Exceptions\OffsetOutOfBounds;
use League\Uri\Exceptions\SyntaxError;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use Stringable;
use TypeError;
use function array_count_values;
use function array_filter;
use function array_keys;
use function array_reverse;
use function array_shift;
use function count;
use function explode;
use function implode;
use function sprintf;
final class Domain extends Component implements DomainHostInterface
{
private const SEPARATOR = '.';
private readonly HostInterface $host;
/** @var string[] */
private readonly array $labels;
private function __construct(Stringable|string|null $host)
{
$host = match (true) {
$host instanceof HostInterface => $host,
$host instanceof UriComponentInterface => Host::new($host->value()),
default => Host::new($host),
};
if (!$host->isDomain()) {
throw new SyntaxError(sprintf('`%s` is an invalid domain name.', $host->value() ?? 'null'));
}
$this->host = $host;
$this->labels = array_reverse(explode(self::SEPARATOR, $this->host->value() ?? ''));
}
/**
* Returns a new instance from a string or a stringable object.
*/
public static function new(Stringable|string|null $value = null): self
{
return new self($value);
}
/**
* Returns a new instance from an iterable structure.
*/
public static function fromLabels(Stringable|string ...$labels): self
{
return new self(match ([]) {
$labels => null,
default => implode(self::SEPARATOR, array_reverse(array_map(
fn ($label) => self::filterComponent($label),
$labels
))),
});
}
/**
* Create a new instance from a URI object.
*/
public static function fromUri(Stringable|string $uri): self
{
return self::new(Host::fromUri($uri));
}
/**
* Create a new instance from an Authority object.
*/
public static function fromAuthority(Stringable|string $authority): self
{
return self::new(Host::fromAuthority($authority));
}
public function value(): ?string
{
return $this->host->value();
}
public function toAscii(): ?string
{
return $this->host->toAscii();
}
public function toUnicode(): ?string
{
return $this->host->toUnicode();
}
public function isIp(): bool
{
return false;
}
public function isDomain(): bool
{
return true;
}
public function isRegisteredName(): bool
{
return true;
}
public function getIpVersion(): ?string
{
return null;
}
public function getIp(): ?string
{
return null;
}
public function count(): int
{
return count($this->labels);
}
public function getIterator(): Iterator
{
yield from $this->labels;
}
public function get(int $offset): ?string
{
if ($offset < 0) {
$offset += count($this->labels);
}
return $this->labels[$offset] ?? null;
}
public function keys(?string $label = null): array
{
return match (null) {
$label => array_keys($this->labels),
default => array_keys($this->labels, $label, true),
};
}
public function isAbsolute(): bool
{
return count($this->labels) > 1 && '' === $this->labels[array_key_first($this->labels)];
}
public function prepend(Stringable|string|int|null $label): DomainHostInterface
{
$label = self::filterComponent($label);
$value = $this->value();
return match (true) {
null === $label => $this,
null === $value => new self($label),
str_ends_with($label, self::SEPARATOR) => new self($label.$value),
default => new self($label.self::SEPARATOR.$value),
};
}
public function append(Stringable|string|int|null $label): DomainHostInterface
{
$label = self::filterComponent($label);
$value = $this->value();
return match (true) {
null === $label => $this,
null === $value => new self($label),
!$this->isAbsolute() => new self($value.self::SEPARATOR.$label),
str_ends_with($label, self::SEPARATOR) => new self($value.$label),
default => new self($value.$label.self::SEPARATOR),
};
}
public function withRootLabel(): DomainHostInterface
{
$key = array_key_first($this->labels);
return match ($this->labels[$key]) {
'' => $this,
default => $this->append(''),
};
}
public function slice(int $offset, ?int $length = null): self
{
$nbLabels = count($this->labels);
if ($offset < -$nbLabels || $offset > $nbLabels) {
throw new OffsetOutOfBounds(sprintf('No label can be found with at : `%s`.', $offset));
}
$labels = array_slice($this->labels, $offset, $length, true);
return match ($labels) {
$this->labels => $this,
default => self::fromLabels(...$labels),
};
}
public function withoutRootLabel(): DomainHostInterface
{
$key = array_key_first($this->labels);
if ('' !== $this->labels[$key]) {
return $this;
}
$labels = $this->labels;
array_shift($labels);
return self::fromLabels(...$labels);
}
/**
* @throws OffsetOutOfBounds
*/
public function withLabel(int $key, Stringable|string|int|null $label): DomainHostInterface
{
$nbLabels = count($this->labels);
if ($key < - $nbLabels - 1 || $key > $nbLabels) {
throw new OffsetOutOfBounds(sprintf('No label can be added with the submitted key : `%s`.', $key));
}
if (0 > $key) {
$key += $nbLabels;
}
if ($nbLabels === $key) {
return $this->append($label);
}
if (-1 === $key) {
return $this->prepend($label);
}
if (!$label instanceof HostInterface && null !== $label) {
$label = Host::new((string) $label)->value();
}
if ($label === $this->labels[$key]) {
return $this;
}
$labels = $this->labels;
$labels[$key] = $label;
return new self(implode(self::SEPARATOR, array_reverse($labels)));
}
public function withoutLabel(int ...$keys): DomainHostInterface
{
if ([] === $keys) {
return $this;
}
$nb_labels = count($this->labels);
foreach ($keys as &$offset) {
if (- $nb_labels > $offset || $nb_labels - 1 < $offset) {
throw new OffsetOutOfBounds(sprintf('No label can be removed with the submitted key : `%s`.', $offset));
}
if (0 > $offset) {
$offset += $nb_labels;
}
}
unset($offset);
$deleted_keys = array_keys(array_count_values($keys));
$filter = static fn ($key): bool => !in_array($key, $deleted_keys, true);
return self::fromLabels(...array_filter($this->labels, $filter, ARRAY_FILTER_USE_KEY));
}
/**
* DEPRECATION WARNING! This method will be removed in the next major point release.
*
* @deprecated Since version 7.0.0
* @see Domain::getIterator()
*
* @codeCoverageIgnore
*
* Returns a new instance from a string or a stringable object.
*/
public function labels(): array
{
return $this->labels;
}
/**
* DEPRECATION WARNING! This method will be removed in the next major point release.
*
* @deprecated Since version 7.0.0
* @see Domain::new()
*
* @codeCoverageIgnore
*
* Returns a new instance from a string or a stringable object.
*/
public static function createFromString(Stringable|string $host): self
{
return self::new($host);
}
/**
* DEPRECATION WARNING! This method will be removed in the next major point release.
*
* @deprecated Since version 7.0.0
* @see Domain::fromLabels()
*
* @codeCoverageIgnore
*
* Returns a new instance from an iterable structure.
*
* @throws TypeError If a label is the null value
*/
public static function createFromLabels(iterable $labels): self
{
return self::fromLabels(...$labels);
}
/**
* DEPRECATION WARNING! This method will be removed in the next major point release.
*
* @deprecated Since version 7.0.0
* @see Domain::fromUri()
*
* @codeCoverageIgnore
*
* Create a new instance from a URI object.
*/
public static function createFromUri(Psr7UriInterface|UriInterface $uri): self
{
return self::fromUri($uri);
}
/**
* DEPRECATION WARNING! This method will be removed in the next major point release.
*
* @deprecated Since version 7.0.0
* @see Domain::fromAuthority()
*
* @codeCoverageIgnore
*
* Create a new instance from an Authority object.
*/
public static function createFromAuthority(AuthorityInterface|Stringable|string $authority): self
{
return self::fromAuthority($authority);
}
/**
* DEPRECATION WARNING! This method will be removed in the next major point release.
*
* @deprecated Since version 7.0.0
* @see Domain::new()
*
* @codeCoverageIgnore
*
* Returns a new instance from an iterable structure.
*/
public static function createFromHost(HostInterface $host): self
{
return self::new($host);
}
}