You are here

protected static function Url::fromInternalUri in Drupal 10

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/Url.php \Drupal\Core\Url::fromInternalUri()
  2. 9 core/lib/Drupal/Core/Url.php \Drupal\Core\Url::fromInternalUri()

Creates a new Url object for 'internal:' URIs.

Important note: the URI minus the scheme can NOT simply be validated by a \Drupal\Core\Path\PathValidatorInterface implementation. The semantics of the 'internal:' URI scheme are different:

  • PathValidatorInterface accepts paths without a leading slash (e.g. 'node/add') as well as 2 special paths: '<front>' and '<none>', which are mapped to the correspondingly named routes.
  • 'internal:' URIs store paths with a leading slash that represents the root — i.e. the front page — (e.g. 'internal:/node/add'), and doesn't have any exceptions.

To clarify, a few examples of path plus corresponding 'internal:' URI:

  • 'node/add' -> 'internal:/node/add'
  • 'node/add?foo=bar' -> 'internal:/node/add?foo=bar'
  • 'node/add#kitten' -> 'internal:/node/add#kitten'
  • '<front>' -> 'internal:/'
  • '<front>foo=bar' -> 'internal:/?foo=bar'
  • '<front>#kitten' -> 'internal:/#kitten'
  • '<none>' -> 'internal:'
  • '<none>foo=bar' -> 'internal:?foo=bar'
  • '<none>#kitten' -> 'internal:#kitten'

Therefore, when using a PathValidatorInterface to validate 'internal:' URIs, we must map:

  • 'internal:' (path component is '') to the special '<none>' path
  • 'internal:/' (path component is '/') to the special '<front>' path
  • 'internal:/some-path' (path component is '/some-path') to 'some-path'

Parameters

array $uri_parts: Parts from a URI of the form internal:{path} as from parse_url().

array $options: An array of options, see \Drupal\Core\Url::fromUri() for details.

Return value

static A new Url object for an 'internal:' URI.

Throws

\InvalidArgumentException Thrown when the URI's path component doesn't have a leading slash.

1 call to Url::fromInternalUri()
Url::fromUri in core/lib/Drupal/Core/Url.php
Creates a new Url object from a URI.

File

core/lib/Drupal/Core/Url.php, line 403

Class

Url
Defines an object that holds information about a URL.

Namespace

Drupal\Core

Code

protected static function fromInternalUri(array $uri_parts, array $options) {

  // Both PathValidator::getUrlIfValidWithoutAccessCheck() and 'base:' URIs
  // only accept/contain paths without a leading slash, unlike 'internal:'
  // URIs, for which the leading slash means "relative to Drupal root" and
  // "relative to Symfony app root" (just like in Symfony/Drupal 8 routes).
  if (empty($uri_parts['path'])) {
    $uri_parts['path'] = '<none>';
  }
  elseif ($uri_parts['path'] === '/') {
    $uri_parts['path'] = '<front>';
  }
  else {
    if ($uri_parts['path'][0] !== '/') {
      throw new \InvalidArgumentException("The internal path component '{$uri_parts['path']}' is invalid. Its path component must have a leading slash, e.g. internal:/foo.");
    }

    // Remove the leading slash.
    $uri_parts['path'] = substr($uri_parts['path'], 1);
    if (UrlHelper::isExternal($uri_parts['path'])) {
      throw new \InvalidArgumentException("The internal path component '{$uri_parts['path']}' is external. You are not allowed to specify an external URL together with internal:/.");
    }
  }
  $url = \Drupal::pathValidator()
    ->getUrlIfValidWithoutAccessCheck($uri_parts['path']) ?: static::fromUri('base:' . $uri_parts['path'], $options);

  // Allow specifying additional options.
  $url
    ->setOptions($options + $url
    ->getOptions());
  return $url;
}