You are here

public function UrlGenerator::generateFromRoute in Drupal 8

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/Routing/UrlGenerator.php \Drupal\Core\Routing\UrlGenerator::generateFromRoute()
  2. 10 core/lib/Drupal/Core/Routing/UrlGenerator.php \Drupal\Core\Routing\UrlGenerator::generateFromRoute()

Generates a URL or path for a specific route based on the given parameters.

Parameters that reference placeholders in the route pattern will be substituted for them in the pattern. Extra params are added as query strings to the URL.

@internal Should not be used in user code. Use \Drupal\Core\Url instead.

Parameters

string|\Symfony\Component\Routing\Route $name: The route name or a route object.

array $parameters: An associative array of parameter names and values.

array $options: (optional) An associative array of additional options, with the following elements:

  • 'query': An array of query key/value-pairs (without any URL-encoding) to append to the URL.
  • 'fragment': A fragment identifier (named anchor) to append to the URL. Do not include the leading '#' character.
  • 'absolute': Defaults to FALSE. Whether to force the output to be an absolute link (beginning with http:). Useful for links that will be displayed outside the site, such as in an RSS feed.
  • 'language': An optional language object used to look up the alias for the URL. If $options['language'] is omitted, it defaults to the current language for the language type LanguageInterface::TYPE_URL.
  • 'https': Whether this URL should point to a secure location. If not defined, the current scheme is used, so the user stays on HTTP or HTTPS respectively. TRUE enforces HTTPS and FALSE enforces HTTP.
  • 'base_url': Only used internally by a path processor, for example, to modify the base URL when a language dependent URL requires so.
  • 'prefix': Only used internally, to modify the path when a language dependent URL requires so.

bool $collect_bubbleable_metadata: (optional) Defaults to FALSE. When TRUE, both the generated URL and its associated bubbleable metadata are returned.

Return value

string|\Drupal\Core\GeneratedUrl The generated URL for the given route. When $collect_bubbleable_metadata is TRUE, a GeneratedUrl object is returned, containing the generated URL plus bubbleable metadata.

Throws

\Symfony\Component\Routing\Exception\RouteNotFoundException Thrown when the named route does not exist.

\Symfony\Component\Routing\Exception\MissingMandatoryParametersException Thrown when some parameters are missing that are mandatory for the route.

\Symfony\Component\Routing\Exception\InvalidParameterException Thrown when a parameter value for a placeholder is not correct because it does not match the requirement.

Overrides UrlGeneratorInterface::generateFromRoute

1 call to UrlGenerator::generateFromRoute()
UrlGenerator::generate in core/lib/Drupal/Core/Routing/UrlGenerator.php
Generates a URL or path for a specific route based on the given parameters.

File

core/lib/Drupal/Core/Routing/UrlGenerator.php, line 265

Class

UrlGenerator
Generates URLs from route names and parameters.

Namespace

Drupal\Core\Routing

Code

public function generateFromRoute($name, $parameters = [], $options = [], $collect_bubbleable_metadata = FALSE) {
  $options += [
    'prefix' => '',
  ];
  if (!isset($options['query']) || !is_array($options['query'])) {
    $options['query'] = [];
  }
  $route = $this
    ->getRoute($name);
  $generated_url = $collect_bubbleable_metadata ? new GeneratedUrl() : NULL;
  $fragment = '';
  if (isset($options['fragment'])) {
    if (($fragment = trim($options['fragment'])) != '') {
      $fragment = '#' . $fragment;
    }
  }

  // Generate a relative URL having no path, just query string and fragment.
  if ($route
    ->getOption('_no_path')) {
    $query = $options['query'] ? '?' . UrlHelper::buildQuery($options['query']) : '';
    $url = $query . $fragment;
    return $collect_bubbleable_metadata ? $generated_url
      ->setGeneratedUrl($url) : $url;
  }
  $options += $route
    ->getOption('default_url_options') ?: [];
  $options += [
    'prefix' => '',
    'path_processing' => TRUE,
  ];
  $name = $this
    ->getRouteDebugMessage($name);
  $this
    ->processRoute($name, $route, $parameters, $generated_url);
  $path = $this
    ->getInternalPathFromRoute($name, $route, $parameters, $options['query']);

  // Outbound path processors might need the route object for the path, e.g.
  // to get the path pattern.
  $options['route'] = $route;
  if ($options['path_processing']) {
    $path = $this
      ->processPath($path, $options, $generated_url);
  }

  // Ensure the resulting path has at most one leading slash, to prevent it
  // becoming an external URL without a protocol like //example.com.
  if (strpos($path, '//') === 0) {
    $path = '/' . ltrim($path, '/');
  }

  // The contexts base URL is already encoded
  // (see Symfony\Component\HttpFoundation\Request).
  $path = str_replace($this->decodedChars[0], $this->decodedChars[1], rawurlencode($path));

  // Drupal paths rarely include dots, so skip this processing if possible.
  if (strpos($path, '/.') !== FALSE) {

    // the path segments "." and ".." are interpreted as relative reference when
    // resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3
    // so we need to encode them as they are not used for this purpose here
    // otherwise we would generate a URI that, when followed by a user agent
    // (e.g. browser), does not match this route
    $path = strtr($path, [
      '/../' => '/%2E%2E/',
      '/./' => '/%2E/',
    ]);
    if ('/..' === substr($path, -3)) {
      $path = substr($path, 0, -2) . '%2E%2E';
    }
    elseif ('/.' === substr($path, -2)) {
      $path = substr($path, 0, -1) . '%2E';
    }
  }
  if (!empty($options['prefix'])) {
    $path = ltrim($path, '/');
    $prefix = empty($path) ? rtrim($options['prefix'], '/') : $options['prefix'];
    $path = '/' . str_replace('%2F', '/', rawurlencode($prefix)) . $path;
  }
  $query = $options['query'] ? '?' . UrlHelper::buildQuery($options['query']) : '';

  // The base_url might be rewritten from the language rewrite in domain mode.
  if (isset($options['base_url'])) {
    $base_url = $options['base_url'];
    if (isset($options['https'])) {
      if ($options['https'] === TRUE) {
        $base_url = str_replace('http://', 'https://', $base_url);
      }
      elseif ($options['https'] === FALSE) {
        $base_url = str_replace('https://', 'http://', $base_url);
      }
    }
    $url = $base_url . $path . $query . $fragment;
    return $collect_bubbleable_metadata ? $generated_url
      ->setGeneratedUrl($url) : $url;
  }
  $base_url = $this->context
    ->getBaseUrl();
  $absolute = !empty($options['absolute']);
  if (!$absolute || !($host = $this->context
    ->getHost())) {
    $url = $base_url . $path . $query . $fragment;
    return $collect_bubbleable_metadata ? $generated_url
      ->setGeneratedUrl($url) : $url;
  }

  // Prepare an absolute URL by getting the correct scheme, host and port from
  // the request context.
  if (isset($options['https'])) {
    $scheme = $options['https'] ? 'https' : 'http';
  }
  else {
    $scheme = $this->context
      ->getScheme();
  }
  $scheme_req = $route
    ->getSchemes();
  if ($scheme_req && ($req = $scheme_req[0]) && $scheme !== $req) {
    $scheme = $req;
  }
  $port = '';
  if ('http' === $scheme && 80 != $this->context
    ->getHttpPort()) {
    $port = ':' . $this->context
      ->getHttpPort();
  }
  elseif ('https' === $scheme && 443 != $this->context
    ->getHttpsPort()) {
    $port = ':' . $this->context
      ->getHttpsPort();
  }
  if ($collect_bubbleable_metadata) {
    $generated_url
      ->addCacheContexts([
      'url.site',
    ]);
  }
  $url = $scheme . '://' . $host . $port . $base_url . $path . $query . $fragment;
  return $collect_bubbleable_metadata ? $generated_url
    ->setGeneratedUrl($url) : $url;
}