diff options
author | Andrew Dolgov <[email protected]> | 2022-07-24 14:03:04 +0300 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2022-07-24 14:03:04 +0300 |
commit | 5006c754c42a09f5b88b258c2da4b9eff7508357 (patch) | |
tree | 841425d4e163d746642d70b8ac0df381343bbf2b /plugins/af_readability/vendor/league/uri/src/UriResolver.php | |
parent | f7b3c50828d4604ac5999daf3c3405e65c877e2f (diff) |
readability: add missing dependencies
Diffstat (limited to 'plugins/af_readability/vendor/league/uri/src/UriResolver.php')
-rw-r--r-- | plugins/af_readability/vendor/league/uri/src/UriResolver.php | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/plugins/af_readability/vendor/league/uri/src/UriResolver.php b/plugins/af_readability/vendor/league/uri/src/UriResolver.php new file mode 100644 index 000000000..1090383c8 --- /dev/null +++ b/plugins/af_readability/vendor/league/uri/src/UriResolver.php @@ -0,0 +1,376 @@ +<?php + +/** + * League.Uri (https://uri.thephpleague.com) + * + * (c) Ignace Nyamagana Butera <[email protected]> + * + * 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 League\Uri\Contracts\UriInterface; +use Psr\Http\Message\UriInterface as Psr7UriInterface; +use TypeError; +use function array_pop; +use function array_reduce; +use function count; +use function end; +use function explode; +use function gettype; +use function implode; +use function in_array; +use function sprintf; +use function str_repeat; +use function strpos; +use function substr; + +final class UriResolver +{ + /** + * @var array<string,int> + */ + const DOT_SEGMENTS = ['.' => 1, '..' => 1]; + + /** + * @codeCoverageIgnore + */ + private function __construct() + { + } + + /** + * Resolve an URI against a base URI using RFC3986 rules. + * + * If the first argument is a UriInterface the method returns a UriInterface object + * If the first argument is a Psr7UriInterface the method returns a Psr7UriInterface object + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + * + * @return Psr7UriInterface|UriInterface + */ + public static function resolve($uri, $base_uri) + { + self::filterUri($uri); + self::filterUri($base_uri); + $null = $uri instanceof Psr7UriInterface ? '' : null; + + if ($null !== $uri->getScheme()) { + return $uri + ->withPath(self::removeDotSegments($uri->getPath())); + } + + if ($null !== $uri->getAuthority()) { + return $uri + ->withScheme($base_uri->getScheme()) + ->withPath(self::removeDotSegments($uri->getPath())); + } + + $user = $null; + $pass = null; + $userInfo = $base_uri->getUserInfo(); + if (null !== $userInfo) { + [$user, $pass] = explode(':', $userInfo, 2) + [1 => null]; + } + + [$uri_path, $uri_query] = self::resolvePathAndQuery($uri, $base_uri); + + return $uri + ->withPath(self::removeDotSegments($uri_path)) + ->withQuery($uri_query) + ->withHost($base_uri->getHost()) + ->withPort($base_uri->getPort()) + ->withUserInfo((string) $user, $pass) + ->withScheme($base_uri->getScheme()) + ; + } + + /** + * Filter the URI object. + * + * @param mixed $uri an URI object + * + * @throws TypeError if the URI object does not implements the supported interfaces. + */ + private static function filterUri($uri): void + { + if (!$uri instanceof UriInterface && !$uri instanceof Psr7UriInterface) { + throw new TypeError(sprintf('The uri must be a valid URI object received `%s`', gettype($uri))); + } + } + + /** + * Remove dot segments from the URI path. + */ + private static function removeDotSegments(string $path): string + { + if (false === strpos($path, '.')) { + return $path; + } + + $old_segments = explode('/', $path); + $new_path = implode('/', array_reduce($old_segments, [UriResolver::class, 'reducer'], [])); + if (isset(self::DOT_SEGMENTS[end($old_segments)])) { + $new_path .= '/'; + } + + // @codeCoverageIgnoreStart + // added because some PSR-7 implementations do not respect RFC3986 + if (0 === strpos($path, '/') && 0 !== strpos($new_path, '/')) { + return '/'.$new_path; + } + // @codeCoverageIgnoreEnd + + return $new_path; + } + + /** + * Remove dot segments. + * + * @return array<int, string> + */ + private static function reducer(array $carry, string $segment): array + { + if ('..' === $segment) { + array_pop($carry); + + return $carry; + } + + if (!isset(self::DOT_SEGMENTS[$segment])) { + $carry[] = $segment; + } + + return $carry; + } + + /** + * Resolve an URI path and query component. + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + * + * @return array{0:string, 1:string|null} + */ + private static function resolvePathAndQuery($uri, $base_uri): array + { + $target_path = $uri->getPath(); + $target_query = $uri->getQuery(); + $null = $uri instanceof Psr7UriInterface ? '' : null; + $baseNull = $base_uri instanceof Psr7UriInterface ? '' : null; + + if (0 === strpos($target_path, '/')) { + return [$target_path, $target_query]; + } + + if ('' === $target_path) { + if ($null === $target_query) { + $target_query = $base_uri->getQuery(); + } + + $target_path = $base_uri->getPath(); + //@codeCoverageIgnoreStart + //because some PSR-7 Uri implementations allow this RFC3986 forbidden construction + if ($baseNull !== $base_uri->getAuthority() && 0 !== strpos($target_path, '/')) { + $target_path = '/'.$target_path; + } + //@codeCoverageIgnoreEnd + + return [$target_path, $target_query]; + } + + $base_path = $base_uri->getPath(); + if ($baseNull !== $base_uri->getAuthority() && '' === $base_path) { + $target_path = '/'.$target_path; + } + + if ('' !== $base_path) { + $segments = explode('/', $base_path); + array_pop($segments); + if ([] !== $segments) { + $target_path = implode('/', $segments).'/'.$target_path; + } + } + + return [$target_path, $target_query]; + } + + /** + * Relativize an URI according to a base URI. + * + * This method MUST retain the state of the submitted URI instance, and return + * an URI instance of the same type that contains the applied modifications. + * + * This method MUST be transparent when dealing with error and exceptions. + * It MUST not alter of silence them apart from validating its own parameters. + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + * + * @return Psr7UriInterface|UriInterface + */ + public static function relativize($uri, $base_uri) + { + self::filterUri($uri); + self::filterUri($base_uri); + $uri = self::formatHost($uri); + $base_uri = self::formatHost($base_uri); + if (!self::isRelativizable($uri, $base_uri)) { + return $uri; + } + + $null = $uri instanceof Psr7UriInterface ? '' : null; + $uri = $uri->withScheme($null)->withPort(null)->withUserInfo($null)->withHost($null); + $target_path = $uri->getPath(); + if ($target_path !== $base_uri->getPath()) { + return $uri->withPath(self::relativizePath($target_path, $base_uri->getPath())); + } + + if (self::componentEquals('getQuery', $uri, $base_uri)) { + return $uri->withPath('')->withQuery($null); + } + + if ($null === $uri->getQuery()) { + return $uri->withPath(self::formatPathWithEmptyBaseQuery($target_path)); + } + + return $uri->withPath(''); + } + + /** + * Tells whether the component value from both URI object equals. + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + */ + private static function componentEquals(string $method, $uri, $base_uri): bool + { + return self::getComponent($method, $uri) === self::getComponent($method, $base_uri); + } + + /** + * Returns the component value from the submitted URI object. + * + * @param Psr7UriInterface|UriInterface $uri + */ + private static function getComponent(string $method, $uri): ?string + { + $component = $uri->$method(); + if ($uri instanceof Psr7UriInterface && '' === $component) { + return null; + } + + return $component; + } + + /** + * Filter the URI object. + * + * @param Psr7UriInterface|UriInterface $uri + * + * @throws TypeError if the URI object does not implements the supported interfaces. + * + * @return Psr7UriInterface|UriInterface + */ + private static function formatHost($uri) + { + if (!$uri instanceof Psr7UriInterface) { + return $uri; + } + + $host = $uri->getHost(); + if ('' === $host) { + return $uri; + } + + return $uri->withHost((string) Uri::createFromComponents(['host' => $host])->getHost()); + } + + /** + * Tell whether the submitted URI object can be relativize. + * + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + */ + private static function isRelativizable($uri, $base_uri): bool + { + return !UriInfo::isRelativePath($uri) + && self::componentEquals('getScheme', $uri, $base_uri) + && self::componentEquals('getAuthority', $uri, $base_uri); + } + + /** + * Relative the URI for a authority-less target URI. + */ + private static function relativizePath(string $path, string $basepath): string + { + $base_segments = self::getSegments($basepath); + $target_segments = self::getSegments($path); + $target_basename = array_pop($target_segments); + array_pop($base_segments); + foreach ($base_segments as $offset => $segment) { + if (!isset($target_segments[$offset]) || $segment !== $target_segments[$offset]) { + break; + } + unset($base_segments[$offset], $target_segments[$offset]); + } + $target_segments[] = $target_basename; + + return self::formatPath( + str_repeat('../', count($base_segments)).implode('/', $target_segments), + $basepath + ); + } + + /** + * returns the path segments. + * + * @return string[] + */ + private static function getSegments(string $path): array + { + if ('' !== $path && '/' === $path[0]) { + $path = substr($path, 1); + } + + return explode('/', $path); + } + + /** + * Formatting the path to keep a valid URI. + */ + private static function formatPath(string $path, string $basepath): string + { + if ('' === $path) { + return in_array($basepath, ['', '/'], true) ? $basepath : './'; + } + + if (false === ($colon_pos = strpos($path, ':'))) { + return $path; + } + + $slash_pos = strpos($path, '/'); + if (false === $slash_pos || $colon_pos < $slash_pos) { + return "./$path"; + } + + return $path; + } + + /** + * Formatting the path to keep a resolvable URI. + */ + private static function formatPathWithEmptyBaseQuery(string $path): string + { + $target_segments = self::getSegments($path); + /** @var string $basename */ + $basename = end($target_segments); + + return '' === $basename ? './' : $basename; + } +} |