layfi-earn/vendor/illuminate/support/Uri.php

392 lines
9.7 KiB
PHP
Raw Permalink Normal View History

2025-01-27 20:49:47 +08:00
<?php
namespace Illuminate\Support;
use Closure;
use Illuminate\Contracts\Routing\UrlRoutable;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\Dumpable;
use Illuminate\Support\Traits\Tappable;
use League\Uri\Contracts\UriInterface;
use League\Uri\Uri as LeagueUri;
use SensitiveParameter;
use Stringable;
class Uri implements Htmlable, Responsable, Stringable
{
use Conditionable, Dumpable, Tappable;
/**
* The URI instance.
*/
protected UriInterface $uri;
/**
* The URL generator resolver.
*/
protected static ?Closure $urlGeneratorResolver = null;
/**
* Create a new parsed URI instance.
*/
public function __construct(UriInterface|Stringable|string $uri = '')
{
$this->uri = $uri instanceof UriInterface ? $uri : LeagueUri::new((string) $uri);
}
/**
* Create a new URI instance.
*/
public static function of(UriInterface|Stringable|string $uri = ''): static
{
return new static($uri);
}
/**
* Get a URI instance of an absolute URL for the given path.
*/
public static function to(string $path): static
{
return new static(call_user_func(static::$urlGeneratorResolver)->to($path));
}
/**
* Get a URI instance for a named route.
*
* @param \BackedEnum|string $name
* @param mixed $parameters
* @param bool $absolute
* @return static
*
* @throws \Symfony\Component\Routing\Exception\RouteNotFoundException|\InvalidArgumentException
*/
public static function route($name, $parameters = [], $absolute = true): static
{
return new static(call_user_func(static::$urlGeneratorResolver)->route($name, $parameters, $absolute));
}
/**
* Create a signed route URI instance for a named route.
*
* @param \BackedEnum|string $name
* @param mixed $parameters
* @param \DateTimeInterface|\DateInterval|int|null $expiration
* @param bool $absolute
* @return static
*
* @throws \InvalidArgumentException
*/
public static function signedRoute($name, $parameters = [], $expiration = null, $absolute = true): static
{
return new static(call_user_func(static::$urlGeneratorResolver)->signedRoute($name, $parameters, $expiration, $absolute));
}
/**
* Create a temporary signed route URI instance for a named route.
*
* @param \BackedEnum|string $name
* @param \DateTimeInterface|\DateInterval|int $expiration
* @param array $parameters
* @param bool $absolute
* @return static
*/
public static function temporarySignedRoute($name, $expiration, $parameters = [], $absolute = true): static
{
return static::signedRoute($name, $parameters, $expiration, $absolute);
}
/**
* Get the URI's scheme.
*/
public function scheme(): ?string
{
return $this->uri->getScheme();
}
/**
* Get the user from the URI.
*/
public function user(bool $withPassword = false): ?string
{
return $withPassword
? $this->uri->getUserInfo()
: $this->uri->getUsername();
}
/**
* Get the password from the URI.
*/
public function password(): ?string
{
return $this->uri->getPassword();
}
/**
* Get the URI's host.
*/
public function host(): ?string
{
return $this->uri->getHost();
}
/**
* Get the URI's port.
*/
public function port(): ?int
{
return $this->uri->getPort();
}
/**
* Get the URI's path.
*
* Empty or missing paths are returned as a single "/".
*/
public function path(): ?string
{
$path = trim((string) $this->uri->getPath(), '/');
return $path === '' ? '/' : $path;
}
/**
* Get the URI's query string.
*/
public function query(): UriQueryString
{
return new UriQueryString($this);
}
/**
* Get the URI's fragment.
*/
public function fragment(): ?string
{
return $this->uri->getFragment();
}
/**
* Specify the scheme of the URI.
*/
public function withScheme(Stringable|string $scheme): static
{
return new static($this->uri->withScheme($scheme));
}
/**
* Specify the user and password for the URI.
*/
public function withUser(Stringable|string|null $user, #[SensitiveParameter] Stringable|string|null $password = null): static
{
return new static($this->uri->withUserInfo($user, $password));
}
/**
* Specify the host of the URI.
*/
public function withHost(Stringable|string $host): static
{
return new static($this->uri->withHost($host));
}
/**
* Specify the port of the URI.
*/
public function withPort(int|null $port): static
{
return new static($this->uri->withPort($port));
}
/**
* Specify the path of the URI.
*/
public function withPath(Stringable|string $path): static
{
return new static($this->uri->withPath(Str::start((string) $path, '/')));
}
/**
* Merge new query parameters into the URI.
*/
public function withQuery(array $query, bool $merge = true): static
{
foreach ($query as $key => $value) {
if ($value instanceof UrlRoutable) {
$query[$key] = $value->getRouteKey();
}
}
if ($merge) {
$mergedQuery = $this->query()->all();
foreach ($query as $key => $value) {
data_set($mergedQuery, $key, $value);
}
$newQuery = $mergedQuery;
} else {
$newQuery = [];
foreach ($query as $key => $value) {
data_set($newQuery, $key, $value);
}
}
return new static($this->uri->withQuery(Arr::query($newQuery)));
}
/**
* Merge new query parameters into the URI if they are not already in the query string.
*/
public function withQueryIfMissing(array $query): static
{
$currentQuery = $this->query();
foreach ($query as $key => $value) {
if (! $currentQuery->missing($key)) {
Arr::forget($query, $key);
}
}
return $this->withQuery($query);
}
/**
* Push a value onto the end of a query string parameter that is a list.
*/
public function pushOntoQuery(string $key, mixed $value): static
{
$currentValue = data_get($this->query()->all(), $key);
$values = Arr::wrap($value);
return $this->withQuery([$key => match (true) {
is_array($currentValue) && array_is_list($currentValue) => array_values(array_unique([...$currentValue, ...$values])),
is_array($currentValue) => [...$currentValue, ...$values],
! is_null($currentValue) => [$currentValue, ...$values],
default => $values,
}]);
}
/**
* Remove the given query parameters from the URI.
*/
public function withoutQuery(array|string $keys): static
{
return $this->replaceQuery(Arr::except($this->query()->all(), $keys));
}
/**
* Specify new query parameters for the URI.
*/
public function replaceQuery(array $query): static
{
return $this->withQuery($query, merge: false);
}
/**
* Specify the fragment of the URI.
*/
public function withFragment(string $fragment): static
{
return new static($this->uri->withFragment($fragment));
}
/**
* Create a redirect HTTP response for the given URI.
*/
public function redirect(int $status = 302, array $headers = []): RedirectResponse
{
return new RedirectResponse($this->value(), $status, $headers);
}
/**
* Create an HTTP response that represents the object.
*
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
public function toResponse($request)
{
return new RedirectResponse($this->value());
}
/**
* Get content as a string of HTML.
*
* @return string
*/
public function toHtml()
{
return $this->value();
}
/**
* Get the decoded string representation of the URI.
*/
public function decode(): string
{
if (empty($this->query()->toArray())) {
return $this->value();
}
return Str::replace(Str::after($this->value(), '?'), $this->query()->decode(), $this->value());
}
/**
* Get the string representation of the URI.
*/
public function value(): string
{
return (string) $this;
}
/**
* Determine if the URI is currently an empty string.
*/
public function isEmpty(): bool
{
return trim($this->value()) === '';
}
/**
* Dump the string representation of the URI.
*
* @param mixed ...$args
* @return $this
*/
public function dump(...$args)
{
dump($this->value(), ...$args);
return $this;
}
/**
* Set the URL generator resolver.
*/
public static function setUrlGeneratorResolver(Closure $urlGeneratorResolver): void
{
static::$urlGeneratorResolver = $urlGeneratorResolver;
}
/**
* Get the underlying URI instance.
*/
public function getUri(): UriInterface
{
return $this->uri;
}
/**
* Get the string representation of the URI.
*/
public function __toString(): string
{
return $this->uri->toString();
}
}