You are here

public static function UriResolver::relativize in Lockr 7.3

Returns the target URI as a relative reference from the base URI.

This method is the counterpart to resolve():

(string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))

One use-case is to use the current request URI as base URI and then generate relative links in your documents to reduce the document size or offer self-contained downloadable document archives.

$base = new Uri('http://example.com/a/b/'); echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'. echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'. echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'. echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'.

This method also accepts a target that is already relative and will try to relativize it further. Only a relative-path reference will be returned as-is.

echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well

Parameters

UriInterface $base Base URI:

UriInterface $target Target URI:

Return value

UriInterface The relative URI reference

File

vendor/guzzlehttp/psr7/src/UriResolver.php, line 137

Class

UriResolver
Resolves a URI reference in the context of a base URI and the opposite way.

Namespace

GuzzleHttp\Psr7

Code

public static function relativize(UriInterface $base, UriInterface $target) {
  if ($target
    ->getScheme() !== '' && ($base
    ->getScheme() !== $target
    ->getScheme() || $target
    ->getAuthority() === '' && $base
    ->getAuthority() !== '')) {
    return $target;
  }
  if (Uri::isRelativePathReference($target)) {

    // As the target is already highly relative we return it as-is. It would be possible to resolve
    // the target with `$target = self::resolve($base, $target);` and then try make it more relative
    // by removing a duplicate query. But let's not do that automatically.
    return $target;
  }
  if ($target
    ->getAuthority() !== '' && $base
    ->getAuthority() !== $target
    ->getAuthority()) {
    return $target
      ->withScheme('');
  }

  // We must remove the path before removing the authority because if the path starts with two slashes, the URI
  // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also
  // invalid.
  $emptyPathUri = $target
    ->withScheme('')
    ->withPath('')
    ->withUserInfo('')
    ->withPort(null)
    ->withHost('');
  if ($base
    ->getPath() !== $target
    ->getPath()) {
    return $emptyPathUri
      ->withPath(self::getRelativePath($base, $target));
  }
  if ($base
    ->getQuery() === $target
    ->getQuery()) {

    // Only the target fragment is left. And it must be returned even if base and target fragment are the same.
    return $emptyPathUri
      ->withQuery('');
  }

  // If the base URI has a query but the target has none, we cannot return an empty path reference as it would
  // inherit the base query component when resolving.
  if ($target
    ->getQuery() === '') {
    $segments = explode('/', $target
      ->getPath());
    $lastSegment = end($segments);
    return $emptyPathUri
      ->withPath($lastSegment === '' ? './' : $lastSegment);
  }
  return $emptyPathUri;
}