810 lines
25 KiB
PHP
Executable file
810 lines
25 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;
|
|
|
|
use JsonSerializable;
|
|
use League\Uri\Components\DataPath;
|
|
use League\Uri\Components\Domain;
|
|
use League\Uri\Components\HierarchicalPath;
|
|
use League\Uri\Components\Host;
|
|
use League\Uri\Components\Path;
|
|
use League\Uri\Components\Query;
|
|
use League\Uri\Contracts\PathInterface;
|
|
use League\Uri\Contracts\UriAccess;
|
|
use League\Uri\Contracts\UriInterface;
|
|
use League\Uri\Exceptions\SyntaxError;
|
|
use League\Uri\Idna\Converter as IdnConverter;
|
|
use League\Uri\IPv4\Converter as IPv4Converter;
|
|
use League\Uri\KeyValuePair\Converter as KeyValuePairConverter;
|
|
use Psr\Http\Message\UriFactoryInterface;
|
|
use Psr\Http\Message\UriInterface as Psr7UriInterface;
|
|
use Stringable;
|
|
|
|
use function get_object_vars;
|
|
use function ltrim;
|
|
use function rtrim;
|
|
use function str_ends_with;
|
|
use function str_starts_with;
|
|
|
|
class Modifier implements Stringable, JsonSerializable, UriAccess
|
|
{
|
|
final public function __construct(protected readonly Psr7UriInterface|UriInterface $uri)
|
|
{
|
|
}
|
|
|
|
public static function from(Stringable|string $uri, ?UriFactoryInterface $uriFactory = null): static
|
|
{
|
|
return new static(match (true) {
|
|
$uri instanceof UriAccess => $uri->getUri(),
|
|
$uri instanceof Psr7UriInterface, $uri instanceof UriInterface => $uri,
|
|
$uriFactory instanceof UriFactoryInterface => $uriFactory->createUri((string) $uri),
|
|
default => Uri::new($uri),
|
|
});
|
|
}
|
|
|
|
public function getUri(): Psr7UriInterface|UriInterface
|
|
{
|
|
return $this->uri;
|
|
}
|
|
|
|
public function getUriString(): string
|
|
{
|
|
return $this->uri->__toString();
|
|
}
|
|
|
|
public function jsonSerialize(): string
|
|
{
|
|
return $this->uri->__toString();
|
|
}
|
|
|
|
public function __toString(): string
|
|
{
|
|
return $this->uri->__toString();
|
|
}
|
|
|
|
/*********************************
|
|
* Query modifier methods
|
|
*********************************/
|
|
|
|
/**
|
|
* Change the encoding of the query.
|
|
*
|
|
*/
|
|
public function encodeQuery(KeyValuePairConverter|int $to, KeyValuePairConverter|int|null $from = null): static
|
|
{
|
|
$to = match (true) {
|
|
!$to instanceof KeyValuePairConverter => KeyValuePairConverter::fromEncodingType($to),
|
|
default => $to,
|
|
};
|
|
|
|
$from = match (true) {
|
|
null === $from => KeyValuePairConverter::fromRFC3986(),
|
|
!$from instanceof KeyValuePairConverter => KeyValuePairConverter::fromEncodingType($from),
|
|
default => $from,
|
|
};
|
|
|
|
if ($to == $from) {
|
|
return $this;
|
|
}
|
|
|
|
$originalQuery = $this->uri->getQuery();
|
|
$query = QueryString::buildFromPairs(QueryString::parseFromValue($originalQuery, $from), $to);
|
|
|
|
return match (true) {
|
|
null === $query,
|
|
'' === $query,
|
|
$originalQuery === $query => $this,
|
|
default => new static($this->uri->withQuery($query)),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Sort the URI query by keys.
|
|
*/
|
|
public function sortQuery(): static
|
|
{
|
|
return new static($this->uri->withQuery(
|
|
static::normalizeComponent(
|
|
Query::fromUri($this->uri)->sort()->value(),
|
|
$this->uri
|
|
)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Add the new query data to the existing URI query.
|
|
*/
|
|
public function appendQuery(Stringable|string|null $query): static
|
|
{
|
|
return new static($this->uri->withQuery(
|
|
static::normalizeComponent(
|
|
Query::fromUri($this->uri)->append($query)->value(),
|
|
$this->uri
|
|
)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Merge query paris with the existing URI query.
|
|
*
|
|
* @param iterable<int, array{0:string, 1:string|null}> $pairs
|
|
*/
|
|
public function appendQueryPairs(iterable $pairs): self
|
|
{
|
|
return $this->appendQuery(Query::fromPairs($pairs)->value());
|
|
}
|
|
|
|
/**
|
|
* Append PHP query parameters to the existing URI query.
|
|
*/
|
|
public function appendQueryParameters(object|array $parameters): self
|
|
{
|
|
return $this->appendQuery(Query::fromVariable($parameters)->value());
|
|
}
|
|
|
|
/**
|
|
* Merge a new query with the existing URI query.
|
|
*/
|
|
public function mergeQuery(Stringable|string|null $query): static
|
|
{
|
|
return new static($this->uri->withQuery(
|
|
static::normalizeComponent(
|
|
Query::fromUri($this->uri)->merge($query)->value(),
|
|
$this->uri
|
|
)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Merge query paris with the existing URI query.
|
|
*
|
|
* @param iterable<int, array{0:string, 1:string|null}> $pairs
|
|
*/
|
|
public function mergeQueryPairs(iterable $pairs): self
|
|
{
|
|
$currentPairs = [...Query::fromUri($this->uri)->pairs()];
|
|
$pairs = [...$pairs];
|
|
|
|
return match (true) {
|
|
[] === $pairs,
|
|
$currentPairs === $pairs => $this,
|
|
default => $this->mergeQuery(Query::fromPairs($pairs)->value()),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Merge PHP query parameters with the existing URI query.
|
|
*/
|
|
public function mergeQueryParameters(object|array $parameters): self
|
|
{
|
|
$parameters = match (true) {
|
|
is_object($parameters) => get_object_vars($parameters),
|
|
default => $parameters,
|
|
};
|
|
|
|
$currentParameters = Query::fromUri($this->uri)->parameters();
|
|
|
|
return match (true) {
|
|
[] === $parameters,
|
|
$currentParameters === $parameters => $this,
|
|
default => new static($this->uri->withQuery(
|
|
self::normalizeComponent(
|
|
Query::fromVariable([...$currentParameters, ...$parameters])->value(),
|
|
$this->uri
|
|
)
|
|
)),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Remove query data according to their key name.
|
|
*/
|
|
public function removeQueryPairsByKey(string ...$keys): static
|
|
{
|
|
$query = Query::fromUri($this->uri);
|
|
$newQuery = $query->withoutPairByKey(...$keys)->value();
|
|
|
|
return match ($query->value()) {
|
|
$newQuery => $this,
|
|
default => new static($this->uri->withQuery(static::normalizeComponent($newQuery, $this->uri))),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Remove query pair according to their value.
|
|
*/
|
|
public function removeQueryPairsByValue(Stringable|string|int|float|bool|null ...$values): static
|
|
{
|
|
$query = Query::fromUri($this->uri);
|
|
$newQuery = $query->withoutPairByValue(...$values)->value();
|
|
|
|
return match ($query->value()) {
|
|
$newQuery => $this,
|
|
default => new static($this->uri->withQuery(static::normalizeComponent($newQuery, $this->uri))),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Remove query pair according to their key/value name.
|
|
*/
|
|
public function removeQueryPairsByKeyValue(string $key, Stringable|string|int|bool|null $value): static
|
|
{
|
|
$query = Query::fromUri($this->uri);
|
|
$newQuery = $query->withoutPairByKeyValue($key, $value)->value();
|
|
|
|
return match ($newQuery) {
|
|
$query->value() => $this,
|
|
default => new static($this->uri->withQuery(static::normalizeComponent($newQuery, $this->uri))),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Remove query data according to their PHP parameter key name.
|
|
*/
|
|
public function removeQueryParameters(string ...$keys): static
|
|
{
|
|
$query = Query::fromUri($this->uri);
|
|
$newQuery = $query->withoutParameters(...$keys)->value();
|
|
|
|
return match ($newQuery) {
|
|
$query->value() => $this,
|
|
default => new static($this->uri->withQuery(static::normalizeComponent($newQuery, $this->uri))),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Remove empty pairs from the URL query component.
|
|
*
|
|
* A pair is considered empty if it's name is the empty string
|
|
* and its value is either the empty string or the null value
|
|
*/
|
|
public function removeEmptyQueryPairs(): static
|
|
{
|
|
return new static($this->uri->withQuery(
|
|
static::normalizeComponent(
|
|
Query::fromUri($this->uri)->withoutEmptyPairs()->value(),
|
|
$this->uri
|
|
)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Returns an instance where numeric indices associated to PHP's array like key are removed.
|
|
*
|
|
* This method MUST retain the state of the current instance, and return
|
|
* an instance that contains the query component normalized so that numeric indexes
|
|
* are removed from the pair key value.
|
|
*
|
|
* ie.: toto[3]=bar[3]&foo=bar becomes toto[]=bar[3]&foo=bar
|
|
*/
|
|
public function removeQueryParameterIndices(): static
|
|
{
|
|
$query = Query::fromUri($this->uri);
|
|
$newQuery = $query->withoutNumericIndices()->value();
|
|
|
|
return match ($newQuery) {
|
|
$query->value() => $this,
|
|
default => new static($this->uri->withQuery(static::normalizeComponent($newQuery, $this->uri))),
|
|
};
|
|
}
|
|
|
|
/*********************************
|
|
* Host modifier methods
|
|
*********************************/
|
|
|
|
/**
|
|
* Add the root label to the URI.
|
|
*/
|
|
public function addRootLabel(): static
|
|
{
|
|
$host = $this->uri->getHost();
|
|
|
|
return match (true) {
|
|
null === $host,
|
|
str_ends_with($host, '.') => $this,
|
|
default => new static($this->uri->withHost($host.'.')),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Append a label or a host to the current URI host.
|
|
*
|
|
* @throws SyntaxError If the host cannot be appended
|
|
*/
|
|
public function appendLabel(Stringable|string|null $label): static
|
|
{
|
|
$host = Host::fromUri($this->uri);
|
|
$label = Host::new($label);
|
|
|
|
return match (true) {
|
|
null === $label->value() => $this,
|
|
$host->isDomain() => new static($this->uri->withHost(static::normalizeComponent(Domain::new($host)->append($label)->toUnicode(), $this->uri))),
|
|
$host->isIpv4() => new static($this->uri->withHost($host->value().'.'.ltrim($label->value(), '.'))),
|
|
default => throw new SyntaxError('The URI host '.$host->toString().' cannot be appended.'),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Convert the URI host part to its ascii value.
|
|
*/
|
|
public function hostToAscii(): static
|
|
{
|
|
$currentHost = $this->uri->getHost();
|
|
$host = IdnConverter::toAsciiOrFail((string) $currentHost);
|
|
|
|
return match (true) {
|
|
null === $currentHost,
|
|
'' === $currentHost,
|
|
$host === $currentHost => $this,
|
|
default => new static($this->uri->withHost($host)),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Convert the URI host part to its unicode value.
|
|
*/
|
|
public function hostToUnicode(): static
|
|
{
|
|
$currentHost = $this->uri->getHost();
|
|
$host = IdnConverter::toUnicode((string) $currentHost)->domain();
|
|
|
|
return match (true) {
|
|
null === $currentHost,
|
|
'' === $currentHost,
|
|
$host === $currentHost => $this,
|
|
default => new static($this->uri->withHost($host)),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Normalizes the URI host content to a IPv4 dot-decimal notation if possible
|
|
* otherwise returns the uri instance unchanged.
|
|
*
|
|
* @see https://url.spec.whatwg.org/#concept-ipv4-parser
|
|
*/
|
|
public function hostToDecimal(): static
|
|
{
|
|
$currentHost = $this->uri->getHost();
|
|
$hostIp = self::ipv4Converter()->toDecimal($currentHost);
|
|
|
|
return match (true) {
|
|
null === $currentHost,
|
|
'' === $currentHost,
|
|
null === $hostIp,
|
|
$currentHost === $hostIp => $this,
|
|
default => new static($this->uri->withHost($hostIp)),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Normalizes the URI host content to a IPv4 octal notation if possible
|
|
* otherwise returns the uri instance unchanged.
|
|
*
|
|
* @see https://url.spec.whatwg.org/#concept-ipv4-parser
|
|
*/
|
|
public function hostToOctal(): static
|
|
{
|
|
$currentHost = $this->uri->getHost();
|
|
$hostIp = self::ipv4Converter()->toOctal($currentHost);
|
|
|
|
return match (true) {
|
|
null === $currentHost,
|
|
'' === $currentHost,
|
|
null === $hostIp,
|
|
$currentHost === $hostIp => $this,
|
|
default => new static($this->uri->withHost($hostIp)),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Normalizes the URI host content to a IPv4 octal notation if possible
|
|
* otherwise returns the uri instance unchanged.
|
|
*
|
|
* @see https://url.spec.whatwg.org/#concept-ipv4-parser
|
|
*/
|
|
public function hostToHexadecimal(): static
|
|
{
|
|
$currentHost = $this->uri->getHost();
|
|
$hostIp = self::ipv4Converter()->toHexadecimal($currentHost);
|
|
|
|
return match (true) {
|
|
null === $currentHost,
|
|
'' === $currentHost,
|
|
null === $hostIp,
|
|
$currentHost === $hostIp => $this,
|
|
default => new static($this->uri->withHost($hostIp)),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Prepend a label or a host to the current URI host.
|
|
*
|
|
* @throws SyntaxError If the host cannot be prepended
|
|
*/
|
|
public function prependLabel(Stringable|string|null $label): static
|
|
{
|
|
$host = Host::fromUri($this->uri);
|
|
$label = Host::new($label);
|
|
|
|
return match (true) {
|
|
null === $label->value() => $this,
|
|
$host->isIpv4() => new static($this->uri->withHost(rtrim($label->value(), '.').'.'.$host->value())),
|
|
$host->isDomain() => new static($this->uri->withHost(static::normalizeComponent(Domain::new($host)->prepend($label)->toUnicode(), $this->uri))),
|
|
default => throw new SyntaxError('The URI host '.$host->toString().' cannot be prepended.'),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Remove host labels according to their offset.
|
|
*/
|
|
public function removeLabels(int ...$keys): static
|
|
{
|
|
return new static($this->uri->withHost(
|
|
static::normalizeComponent(
|
|
Domain::fromUri($this->uri)->withoutLabel(...$keys)->toUnicode(),
|
|
$this->uri
|
|
)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Remove the root label to the URI.
|
|
*/
|
|
public function removeRootLabel(): static
|
|
{
|
|
$host = $this->uri->getHost();
|
|
|
|
return match (true) {
|
|
null === $host,
|
|
'' === $host,
|
|
!str_ends_with($host, '.') => $this,
|
|
default => new static($this->uri->withHost(substr($host, 0, -1))),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Slice the host from the URI.
|
|
*/
|
|
public function sliceLabels(int $offset, ?int $length = null): static
|
|
{
|
|
$currentHost = $this->uri->getHost();
|
|
$host = Domain::new($currentHost)->slice($offset, $length);
|
|
|
|
return match (true) {
|
|
$host->value() === $currentHost,
|
|
$host->toUnicode() === $currentHost => $this,
|
|
default => new static($this->uri->withHost($host->toUnicode())),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Remove the host zone identifier.
|
|
*/
|
|
public function removeZoneId(): static
|
|
{
|
|
$host = Host::fromUri($this->uri);
|
|
|
|
return match (true) {
|
|
$host->hasZoneIdentifier() => new static($this->uri->withHost(
|
|
static::normalizeComponent(
|
|
Host::fromUri($this->uri)->withoutZoneIdentifier()->value(),
|
|
$this->uri
|
|
)
|
|
)),
|
|
default => $this,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Replace a label of the current URI host.
|
|
*/
|
|
public function replaceLabel(int $offset, Stringable|string|null $label): static
|
|
{
|
|
return new static($this->uri->withHost(
|
|
static::normalizeComponent(
|
|
Domain::fromUri($this->uri)->withLabel($offset, $label)->toUnicode(),
|
|
$this->uri
|
|
)
|
|
));
|
|
}
|
|
|
|
/*********************************
|
|
* Path modifier methods
|
|
*********************************/
|
|
|
|
/**
|
|
* Add a new base path to the URI path.
|
|
*/
|
|
public function addBasePath(Stringable|string $path): static
|
|
{
|
|
/** @var HierarchicalPath $path */
|
|
$path = HierarchicalPath::new($path)->withLeadingSlash();
|
|
/** @var HierarchicalPath $currentPath */
|
|
$currentPath = HierarchicalPath::fromUri($this->uri)->withLeadingSlash();
|
|
|
|
return new static(match (true) {
|
|
!str_starts_with($currentPath->toString(), $path->toString()) => $this->uri->withPath($path->append($currentPath)->toString()),
|
|
default => static::normalizePath($this->uri, $currentPath),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Add a leading slash to the URI path.
|
|
*/
|
|
public function addLeadingSlash(): static
|
|
{
|
|
$path = $this->uri->getPath();
|
|
|
|
return match (true) {
|
|
str_starts_with($path, '/') => $this,
|
|
default => new static($this->uri->withPath('/'.$path)),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Add a trailing slash to the URI path.
|
|
*/
|
|
public function addTrailingSlash(): static
|
|
{
|
|
$path = $this->uri->getPath();
|
|
|
|
return match (true) {
|
|
str_ends_with($path, '/') => $this,
|
|
default => new static($this->uri->withPath($path.'/')),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Append a new segment or a new path to the URI path.
|
|
*/
|
|
public function appendSegment(Stringable|string $segment): static
|
|
{
|
|
return new static(static::normalizePath($this->uri, HierarchicalPath::fromUri($this->uri)->append($segment)));
|
|
}
|
|
|
|
/**
|
|
* Convert the Data URI path to its ascii form.
|
|
*/
|
|
public function dataPathToAscii(): static
|
|
{
|
|
return new static($this->uri->withPath(DataPath::fromUri($this->uri)->toAscii()->toString()));
|
|
}
|
|
|
|
/**
|
|
* Convert the Data URI path to its binary (base64encoded) form.
|
|
*/
|
|
public function dataPathToBinary(): static
|
|
{
|
|
return new static($this->uri->withPath(DataPath::fromUri($this->uri)->toBinary()->toString()));
|
|
}
|
|
|
|
/**
|
|
* Prepend a new segment or a new path to the URI path.
|
|
*/
|
|
public function prependSegment(Stringable|string $segment): static
|
|
{
|
|
return new static(static::normalizePath($this->uri, HierarchicalPath::fromUri($this->uri)->prepend($segment)));
|
|
}
|
|
|
|
/**
|
|
* Remove a base path from the URI path.
|
|
*/
|
|
public function removeBasePath(Stringable|string $path): static
|
|
{
|
|
$basePath = HierarchicalPath::new($path)->withLeadingSlash()->toString();
|
|
$currentPath = HierarchicalPath::fromUri($this->uri)->withLeadingSlash()->toString();
|
|
$newPath = substr($currentPath, strlen($basePath));
|
|
|
|
return match (true) {
|
|
'/' === $basePath,
|
|
!str_starts_with($currentPath, $basePath),
|
|
!str_starts_with($newPath, '/') => $this,
|
|
default => new static($this->uri->withPath($newPath)),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Remove dot segments from the URI path.
|
|
*/
|
|
public function removeDotSegments(): static
|
|
{
|
|
return new static($this->uri->withPath(Path::fromUri($this->uri)->withoutDotSegments()->toString()));
|
|
}
|
|
|
|
/**
|
|
* Remove empty segments from the URI path.
|
|
*/
|
|
public function removeEmptySegments(): static
|
|
{
|
|
return new static($this->uri->withPath(HierarchicalPath::fromUri($this->uri)->withoutEmptySegments()->toString()));
|
|
}
|
|
|
|
/**
|
|
* Remove the leading slash from the URI path.
|
|
*/
|
|
public function removeLeadingSlash(): static
|
|
{
|
|
return new static(static::normalizePath($this->uri, Path::fromUri($this->uri)->withoutLeadingSlash()));
|
|
}
|
|
|
|
/**
|
|
* Remove the trailing slash from the URI path.
|
|
*/
|
|
public function removeTrailingSlash(): static
|
|
{
|
|
$path = $this->uri->getPath();
|
|
|
|
return match (true) {
|
|
!str_ends_with($path, '/') => $this,
|
|
default => new static($this->uri->withPath(substr($path, 0, -1))),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Remove path segments from the URI path according to their offsets.
|
|
*/
|
|
public function removeSegments(int ...$keys): static
|
|
{
|
|
return new static($this->uri->withPath(HierarchicalPath::fromUri($this->uri)->withoutSegment(...$keys)->toString()));
|
|
}
|
|
|
|
/**
|
|
* Replace the URI path basename.
|
|
*/
|
|
public function replaceBasename(Stringable|string $basename): static
|
|
{
|
|
return new static(static::normalizePath($this->uri, HierarchicalPath::fromUri($this->uri)->withBasename($basename)));
|
|
}
|
|
|
|
/**
|
|
* Replace the data URI path parameters.
|
|
*/
|
|
public function replaceDataUriParameters(Stringable|string $parameters): static
|
|
{
|
|
return new static($this->uri->withPath(DataPath::fromUri($this->uri)->withParameters($parameters)->toString()));
|
|
}
|
|
|
|
/**
|
|
* Replace the URI path dirname.
|
|
*/
|
|
public function replaceDirname(Stringable|string $dirname): static
|
|
{
|
|
return new static(static::normalizePath($this->uri, HierarchicalPath::fromUri($this->uri)->withDirname($dirname)));
|
|
}
|
|
|
|
/**
|
|
* Replace the URI path basename extension.
|
|
*/
|
|
public function replaceExtension(Stringable|string $extension): static
|
|
{
|
|
return new static($this->uri->withPath(HierarchicalPath::fromUri($this->uri)->withExtension($extension)->toString()));
|
|
}
|
|
|
|
/**
|
|
* Replace a segment from the URI path according its offset.
|
|
*/
|
|
public function replaceSegment(int $offset, Stringable|string $segment): static
|
|
{
|
|
return new static($this->uri->withPath(HierarchicalPath::fromUri($this->uri)->withSegment($offset, $segment)->toString()));
|
|
}
|
|
|
|
/**
|
|
* Slice the host from the URI.
|
|
*/
|
|
public function sliceSegments(int $offset, ?int $length = null): static
|
|
{
|
|
return new static(static::normalizePath($this->uri, HierarchicalPath::fromUri($this->uri)->slice($offset, $length)));
|
|
}
|
|
|
|
/**
|
|
* Normalize a URI path.
|
|
*
|
|
* Make sure the path always has a leading slash if an authority is present
|
|
* and the path is not the empty string.
|
|
*/
|
|
final protected static function normalizePath(Psr7UriInterface|UriInterface $uri, PathInterface $path): Psr7UriInterface|UriInterface
|
|
{
|
|
$pathString = $path->toString();
|
|
$authority = $uri->getAuthority();
|
|
|
|
return match (true) {
|
|
'' === $pathString,
|
|
'/' === $pathString[0],
|
|
null === $authority,
|
|
'' === $authority => $uri->withPath($pathString),
|
|
default => $uri->withPath('/'.$pathString),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Normalize the URI component value depending on the subject interface.
|
|
*
|
|
* null value MUST be converted to the empty string if a Psr7 UriInterface is being manipulated.
|
|
*/
|
|
final protected static function normalizeComponent(?string $component, Psr7UriInterface|UriInterface $uri): ?string
|
|
{
|
|
return match (true) {
|
|
$uri instanceof Psr7UriInterface => (string) $component,
|
|
default => $component,
|
|
};
|
|
}
|
|
|
|
final protected static function ipv4Converter(): IPv4Converter
|
|
{
|
|
static $converter;
|
|
|
|
$converter = $converter ?? IPv4Converter::fromEnvironment();
|
|
|
|
return $converter;
|
|
}
|
|
|
|
/**
|
|
* DEPRECATION WARNING! This method will be removed in the next major point release.
|
|
*
|
|
* @deprecated Since version 7.2.0
|
|
* @codeCoverageIgnore
|
|
* @see Modifier::removeQueryParameters()
|
|
*
|
|
* Remove query data according to their key name.
|
|
*/
|
|
public function removeParams(string ...$keys): static
|
|
{
|
|
return $this->removeQueryParameters(...$keys);
|
|
}
|
|
|
|
/**
|
|
* DEPRECATION WARNING! This method will be removed in the next major point release.
|
|
*
|
|
* @deprecated Since version 7.2.0
|
|
* @codeCoverageIgnore
|
|
* @see Modifier::removeEmptyQueryPairs()
|
|
*
|
|
* Remove empty pairs from the URL query component.
|
|
*
|
|
* A pair is considered empty if it's name is the empty string
|
|
* and its value is either the empty string or the null value
|
|
*/
|
|
public function removeEmptyPairs(): static
|
|
{
|
|
return $this->removeEmptyQueryPairs();
|
|
}
|
|
|
|
/**
|
|
* DEPRECATION WARNING! This method will be removed in the next major point release.
|
|
*
|
|
* @deprecated Since version 7.2.0
|
|
* @codeCoverageIgnore
|
|
* @see Modifier::removeQueryPairsByKey()
|
|
*
|
|
* Remove query data according to their key name.
|
|
*/
|
|
public function removePairs(string ...$keys): static
|
|
{
|
|
return $this->removeQueryPairsByKey(...$keys);
|
|
}
|
|
|
|
/**
|
|
* DEPRECATION WARNING! This method will be removed in the next major point release.
|
|
*
|
|
* @deprecated Since version 7.2.0
|
|
* @codeCoverageIgnore
|
|
* @see Modifier::removeQueryPairsByKey()
|
|
*
|
|
* Remove query data according to their key name.
|
|
*/
|
|
public function removeQueryPairs(string ...$keys): static
|
|
{
|
|
return $this->removeQueryPairsByKey(...$keys);
|
|
}
|
|
}
|