Commit 7342df62 authored by alexpott's avatar alexpott

Issue #2335661 by Wim Leers, pwolanin, dawehner, Fabianx, larowlan, catch,...

Issue #2335661 by Wim Leers, pwolanin, dawehner, Fabianx, larowlan, catch, Berdir: Outbound path & route processors must specify cacheability metadata
parent 2d35b92e
......@@ -34,8 +34,8 @@ services:
arguments: ['@request_stack']
tags:
- { name: cache.context }
cache_context.url.host:
class: Drupal\Core\Cache\HostCacheContext
cache_context.url.site:
class: Drupal\Core\Cache\SiteCacheContext
arguments: ['@request_stack']
tags:
- { name: cache.context }
......@@ -1319,7 +1319,6 @@ services:
- { name: twig.extension, priority: 100 }
calls:
- [setGenerators, ['@url_generator']]
- [setLinkGenerator, ['@link_generator']]
# @todo Figure out what to do about debugging functions.
# @see http://drupal.org/node/1804998
twig.extension.debug:
......
......@@ -504,17 +504,22 @@ public static function urlGenerator() {
* (optional) An associative array of parameter names and values.
* @param array $options
* (optional) An associative array of additional options.
* @param bool $collect_cacheability_metadata
* (optional) Defaults to FALSE. When TRUE, both the generated URL and its
* associated cacheability metadata are returned.
*
* @return string
* The generated URL for the given route.
* @return string|\Drupal\Core\GeneratedUrl
* A string containing a URL to the given path.
* When $collect_cacheability_metadata is TRUE, a GeneratedUrl object is
* returned, containing the generated URL plus cacheability metadata.
*
* @see \Drupal\Core\Routing\UrlGeneratorInterface::generateFromRoute()
* @see \Drupal\Core\Url
* @see \Drupal\Core\Url::fromRoute()
* @see \Drupal\Core\Url::fromUri()
*/
public static function url($route_name, $route_parameters = array(), $options = array()) {
return static::getContainer()->get('url_generator')->generateFromRoute($route_name, $route_parameters, $options);
public static function url($route_name, $route_parameters = array(), $options = array(), $collect_cacheability_metadata = FALSE) {
return static::getContainer()->get('url_generator')->generateFromRoute($route_name, $route_parameters, $options, $collect_cacheability_metadata);
}
/**
......@@ -537,15 +542,20 @@ public static function linkGenerator() {
* The link text for the anchor tag.
* @param \Drupal\Core\Url $url
* The URL object used for the link.
* @param bool $collect_cacheability_metadata
* (optional) Defaults to FALSE. When TRUE, both the generated URL and its
* associated cacheability metadata are returned.
*
* @return string
* @return string|\Drupal\Core\GeneratedLink
* An HTML string containing a link to the given route and parameters.
* When $collect_cacheability_metadata is TRUE, a GeneratedLink object is
* returned, containing the generated link plus cacheability metadata.
*
* @see \Drupal\Core\Utility\LinkGeneratorInterface::generate()
* @see \Drupal\Core\Url
*/
public static function l($text, Url $url) {
return static::getContainer()->get('link_generator')->generate($text, $url);
public static function l($text, Url $url, $collect_cacheability_metadata = FALSE) {
return static::getContainer()->get('link_generator')->generate($text, $url, $collect_cacheability_metadata);
}
/**
......
......@@ -7,9 +7,8 @@
namespace Drupal\Core\Access;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface;
use Drupal\Core\Access\CsrfTokenGenerator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
/**
......@@ -37,7 +36,7 @@ function __construct(CsrfTokenGenerator $csrf_token) {
/**
* {@inheritdoc}
*/
public function processOutbound($route_name, Route $route, array &$parameters) {
public function processOutbound($route_name, Route $route, array &$parameters, CacheableMetadata $cacheable_metadata = NULL) {
if ($route->hasRequirement('_csrf_token')) {
$path = ltrim($route->getPath(), '/');
// Replace the path parameters with values from the parameters array.
......@@ -47,6 +46,11 @@ public function processOutbound($route_name, Route $route, array &$parameters) {
// Adding this to the parameters means it will get merged into the query
// string when the route is compiled.
$parameters['token'] = $this->csrfToken->get($path);
if ($cacheable_metadata) {
// Tokens are per user and per session, so not cacheable.
// @todo Improve in https://www.drupal.org/node/2351015.
$cacheable_metadata->setCacheMaxAge(0);
}
}
}
......
<?php
/**
* @file
* Contains \Drupal\Core\Cache\HostCacheContext.
*/
namespace Drupal\Core\Cache;
/**
* Defines the HostCacheContext service, for "per host" caching.
*
* A "host" is defined as the combination of URI scheme, domain name and port.
*
* @see Symfony\Component\HttpFoundation::getSchemeAndHttpHost()
*/
class HostCacheContext extends RequestStackCacheContextBase {
/**
* {@inheritdoc}
*/
public static function getLabel() {
return t('Host');
}
/**
* {@inheritdoc}
*/
public function getContext() {
return $this->requestStack->getCurrentRequest()->getSchemeAndHttpHost();
}
}
<?php
/**
* @file
* Contains \Drupal\Core\Cache\SiteCacheContext.
*/
namespace Drupal\Core\Cache;
/**
* Defines the SiteCacheContext service, for "per site" caching.
*
* A "site" is defined as the combination of URI scheme, domain name, port and
* base path. It allows for varying between the *same* site being accessed via
* different entry points. (Different sites in a multisite setup have separate
* databases.) For example: http://example.com and http://www.example.com.
*
* @see \Symfony\Component\HttpFoundation\Request::getSchemeAndHttpHost()
* @see \Symfony\Component\HttpFoundation\Request::getBaseUrl()
*/
class SiteCacheContext extends RequestStackCacheContextBase {
/**
* {@inheritdoc}
*/
public static function getLabel() {
return t('Site');
}
/**
* {@inheritdoc}
*/
public function getContext() {
$request = $this->requestStack->getCurrentRequest();
return $request->getSchemeAndHttpHost() . $request->getBaseUrl();
}
}
<?php
/**
* @file
* Contains \Drupal\Core\GeneratedLink.
*/
namespace Drupal\Core;
use Drupal\Core\Cache\CacheableMetadata;
/**
* Used to return generated links, along with associated cacheability metadata.
*
* Note: not to be confused with \Drupal\Core\Link, which is for passing around
* ungenerated links (typically link text + route name + route parameters).
*/
class GeneratedLink extends CacheableMetadata {
/**
* The HTML string value containing a link.
*
* @var string
*/
protected $generatedLink = '';
/**
* Gets the generated link.
*
* @return string
*/
public function getGeneratedLink() {
return $this->generatedLink ;
}
/**
* Sets the generated link.
*
* @param string $generated_link
* The generated link.
*
* @return $this
*/
public function setGeneratedLink($generated_link) {
$this->generatedLink = $generated_link;
return $this;
}
}
<?php
/**
* @file
* Contains \Drupal\Core\GeneratedUrl.
*/
namespace Drupal\Core;
use Drupal\Core\Cache\CacheableMetadata;
/**
* Used to return generated URLs, along with associated cacheability metadata.
*
* Note: not to be confused with \Drupal\Core\Url, which is for passing around
* ungenerated URLs (typically route name + route parameters).
*/
class GeneratedUrl extends CacheableMetadata {
/**
* The string value of the URL.
*
* @var string
*/
protected $generatedUrl = '';
/**
* Gets the generated URL.
*
* @return string
*/
public function getGeneratedUrl() {
return $this->generatedUrl ;
}
/**
* Sets the generated URL.
*
* @param string $generated_url
* The generated URL.
*
* @return $this
*/
public function setGeneratedUrl($generated_url) {
$this->generatedUrl = $generated_url;
return $this;
}
}
......@@ -121,9 +121,18 @@ public function setUrl(Url $url) {
/**
* Generates the HTML for this Link object.
*
* @param bool $collect_cacheability_metadata
* (optional) Defaults to FALSE. When TRUE, both the generated link and its
* associated cacheability metadata are returned.
*
* @return string|\Drupal\Core\GeneratedLink
* The link HTML markup.
* When $collect_cacheability_metadata is TRUE, a GeneratedLink object is
* returned, containing the generated link plus cacheability metadata.
*/
public function toString() {
return $this->getLinkGenerator()->generateFromLink($this);
public function toString($collect_cacheability_metadata = FALSE) {
return $this->getLinkGenerator()->generateFromLink($this, $collect_cacheability_metadata);
}
}
......@@ -7,8 +7,8 @@
namespace Drupal\Core\PathProcessor;
use Drupal\Core\Cache\CacheableMetadata;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
/**
* Defines an interface for classes that process the outbound path.
......@@ -20,17 +20,17 @@ interface OutboundPathProcessorInterface {
*
* @param string $path
* The path to process.
*
* @param array $options
* An array of options such as would be passed to the generator's
* generateFromPath() method.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The HttpRequest object representing the current request.
* @param \Drupal\Core\Cache\CacheableMetadata $cacheable_metadata
* (optional) Object to collect path processors' cacheability.
*
* @return
* The processed path.
*/
public function processOutbound($path, &$options = array(), Request $request = NULL);
public function processOutbound($path, &$options = array(), Request $request = NULL, CacheableMetadata $cacheable_metadata = NULL);
}
......@@ -7,6 +7,7 @@
namespace Drupal\Core\PathProcessor;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Path\AliasManagerInterface;
use Symfony\Component\HttpFoundation\Request;
......@@ -43,7 +44,7 @@ public function processInbound($path, Request $request) {
/**
* Implements Drupal\Core\PathProcessor\OutboundPathProcessorInterface::processOutbound().
*/
public function processOutbound($path, &$options = array(), Request $request = NULL) {
public function processOutbound($path, &$options = array(), Request $request = NULL, CacheableMetadata $cacheable_metadata = NULL) {
if (empty($options['alias'])) {
$langcode = isset($options['language']) ? $options['language']->getId() : NULL;
$path = $this->aliasManager->getAliasByPath($path, $langcode);
......
......@@ -7,11 +7,14 @@
namespace Drupal\Core\PathProcessor;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Processes the inbound path by resolving it to the front page if empty.
*
* @todo - remove ::processOutbound() when we remove UrlGenerator::fromPath().
*/
class PathProcessorFront implements InboundPathProcessorInterface, OutboundPathProcessorInterface {
......@@ -45,7 +48,7 @@ public function processInbound($path, Request $request) {
/**
* Implements Drupal\Core\PathProcessor\OutboundPathProcessorInterface::processOutbound().
*/
public function processOutbound($path, &$options = array(), Request $request = NULL) {
public function processOutbound($path, &$options = array(), Request $request = NULL, CacheableMetadata $cacheable_metadata = NULL) {
// The special path '<front>' links to the default front page.
if ($path == '<front>') {
$path = '';
......
......@@ -7,6 +7,7 @@
namespace Drupal\Core\PathProcessor;
use Drupal\Core\Cache\CacheableMetadata;
use Symfony\Component\HttpFoundation\Request;
/**
......@@ -107,10 +108,10 @@ public function addOutbound(OutboundPathProcessorInterface $processor, $priority
/**
* Implements Drupal\Core\PathProcessor\OutboundPathProcessorInterface::processOutbound().
*/
public function processOutbound($path, &$options = array(), Request $request = NULL) {
public function processOutbound($path, &$options = array(), Request $request = NULL, CacheableMetadata $cacheable_metadata = NULL) {
$processors = $this->getOutbound();
foreach ($processors as $processor) {
$path = $processor->processOutbound($path, $options, $request);
$path = $processor->processOutbound($path, $options, $request, $cacheable_metadata);
}
return $path;
}
......
......@@ -9,6 +9,8 @@
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\Html as HtmlUtility;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Url as CoreUrl;
/**
* Provides a link render element.
......@@ -75,9 +77,14 @@ public static function preRenderLink($element) {
$element = static::preRenderAjaxForm($element);
}
if (!empty($element['#url'])) {
if (!empty($element['#url']) && $element['#url'] instanceof CoreUrl) {
$options = NestedArray::mergeDeep($element['#url']->getOptions(), $element['#options']);
$element['#markup'] = \Drupal::l($element['#title'], $element['#url']->setOptions($options));
/** @var \Drupal\Core\Utility\LinkGenerator $link_generator */
$link_generator = \Drupal::service('link_generator');
$generated_link = $link_generator->generate($element['#title'], $element['#url']->setOptions($options), TRUE);
$element['#markup'] = $generated_link->getGeneratedLink();
$generated_link->merge(CacheableMetadata::createFromRenderArray($element))
->applyTo($element);
}
return $element;
}
......
......@@ -7,6 +7,7 @@
namespace Drupal\Core\RouteProcessor;
use Drupal\Core\Cache\CacheableMetadata;
use Symfony\Component\Routing\Route;
/**
......@@ -24,10 +25,12 @@ interface OutboundRouteProcessorInterface {
* @param array $parameters
* An array of parameters to be passed to the route compiler. Passed by
* reference.
* @param \Drupal\Core\Cache\CacheableMetadata $cacheable_metadata
* (optional) Object to collect route processors' cacheability.
*
* @return
* The processed path.
*/
public function processOutbound($route_name, Route $route, array &$parameters);
public function processOutbound($route_name, Route $route, array &$parameters, CacheableMetadata $cacheable_metadata = NULL);
}
......@@ -7,6 +7,7 @@
namespace Drupal\Core\RouteProcessor;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Routing\RouteMatchInterface;
use Symfony\Component\Routing\Route;
......@@ -35,7 +36,7 @@ public function __construct(RouteMatchInterface $route_match) {
/**
* {@inheritdoc}
*/
public function processOutbound($route_name, Route $route, array &$parameters) {
public function processOutbound($route_name, Route $route, array &$parameters, CacheableMetadata $cacheable_metadata = NULL) {
if ($route_name === '<current>') {
if ($current_route = $this->routeMatch->getRouteObject()) {
$route->setPath($current_route->getPath());
......@@ -43,6 +44,9 @@ public function processOutbound($route_name, Route $route, array &$parameters) {
$route->setOptions($current_route->getOptions());
$route->setDefaults($current_route->getDefaults());
$parameters = array_merge($parameters, $this->routeMatch->getRawParameters()->all());
if ($cacheable_metadata) {
$cacheable_metadata->addCacheContexts(['route']);
}
}
else {
// If we have no current route match available, point to the frontpage.
......
......@@ -7,6 +7,7 @@
namespace Drupal\Core\RouteProcessor;
use Drupal\Core\Cache\CacheableMetadata;
use Symfony\Component\Routing\Route;
/**
......@@ -50,10 +51,10 @@ public function addOutbound(OutboundRouteProcessorInterface $processor, $priorit
/**
* {@inheritdoc}
*/
public function processOutbound($route_name, Route $route, array &$parameters) {
public function processOutbound($route_name, Route $route, array &$parameters, CacheableMetadata $cacheable_metadata = NULL) {
$processors = $this->getOutbound();
foreach ($processors as $processor) {
$processor->processOutbound($route_name, $route, $parameters);
$processor->processOutbound($route_name, $route, $parameters, $cacheable_metadata);
}
}
......
......@@ -7,6 +7,7 @@
namespace Drupal\Core\Routing;
use Drupal\Core\Cache\CacheableMetadata;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RequestContext as SymfonyRequestContext;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
......@@ -50,7 +51,7 @@ protected function getRoute($name) {
/**
* {@inheritdoc}
*/
protected function processRoute($name, Route $route, array &$parameters) {
protected function processRoute($name, Route $route, array &$parameters, CacheableMetadata $cacheable_metadata = NULL) {
}
/**
......@@ -75,7 +76,7 @@ public function getContext() {
/**
* Overrides Drupal\Core\Routing\UrlGenerator::processPath().
*/
protected function processPath($path, &$options = array()) {
protected function processPath($path, &$options = array(), CacheableMetadata $cacheable_metadata = NULL) {
return $path;
}
}
......@@ -7,6 +7,8 @@
namespace Drupal\Core\Routing;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\GeneratedUrl;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RequestContext as SymfonyRequestContext;
use Symfony\Component\Routing\Route as SymfonyRoute;
......@@ -275,11 +277,13 @@ public function generate($name, $parameters = array(), $absolute = FALSE) {
/**
* {@inheritdoc}
*/
public function generateFromRoute($name, $parameters = array(), $options = array()) {
public function generateFromRoute($name, $parameters = array(), $options = array(), $collect_cacheability_metadata = FALSE) {
$generated_url = $collect_cacheability_metadata ? new GeneratedUrl() : NULL;
$options += array('prefix' => '');
$route = $this->getRoute($name);
$name = $this->getRouteDebugMessage($name);
$this->processRoute($name, $route, $parameters);
$this->processRoute($name, $route, $parameters, $generated_url);
$query_params = [];
// Symfony adds any parameters that are not path slugs as query strings.
......@@ -288,7 +292,7 @@ public function generateFromRoute($name, $parameters = array(), $options = array
}
$path = $this->getInternalPathFromRoute($name, $route, $parameters, $query_params);
$path = $this->processPath($path, $options);
$path = $this->processPath($path, $options, $generated_url);
if (!empty($options['prefix'])) {
$path = ltrim($path, '/');
......@@ -316,7 +320,8 @@ public function generateFromRoute($name, $parameters = array(), $options = array
}
}
return $base_url . $path . $fragment;
$url = $base_url . $path . $fragment;
return $collect_cacheability_metadata ? $generated_url->setGeneratedUrl($url) : $url;
}
$base_url = $this->context->getBaseUrl();
......@@ -325,10 +330,11 @@ public function generateFromRoute($name, $parameters = array(), $options = array
if (!$absolute || !$host = $this->context->getHost()) {
if ($route->getOption('_only_fragment')) {
return $fragment;
return $collect_cacheability_metadata ? $generated_url->setGeneratedUrl($fragment) : $fragment;
}
return $base_url . $path . $fragment;
$url = $base_url . $path . $fragment;
return $collect_cacheability_metadata ? $generated_url->setGeneratedUrl($url) : $url;
}
// Prepare an absolute URL by getting the correct scheme, host and port from
......@@ -349,13 +355,20 @@ public function generateFromRoute($name, $parameters = array(), $options = array
} elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) {
$port = ':' . $this->context->getHttpsPort();
}
return $scheme . '://' . $host . $port . $base_url . $path . $fragment;
if ($collect_cacheability_metadata) {
$generated_url->addCacheContexts(['url.site']);
}
$url = $scheme . '://' . $host . $port . $base_url . $path . $fragment;
return $collect_cacheability_metadata ? $generated_url->setGeneratedUrl($url) : $url;
}
/**
* {@inheritdoc}
*/
public function generateFromPath($path = NULL, $options = array()) {
public function generateFromPath($path = NULL, $options = array(), $collect_cacheability_metadata = FALSE) {
$generated_url = $collect_cacheability_metadata ? new GeneratedUrl() : NULL;
$request = $this->requestStack->getCurrentRequest();
$current_base_path = $request->getBasePath() . '/';
$current_base_url = $request->getSchemeAndHttpHost() . $current_base_path;
......@@ -418,10 +431,11 @@ public function generateFromPath($path = NULL, $options = array()) {
}
}
// Reassemble.
return $path . $options['fragment'];
$url = $path . $options['fragment'];
return $collect_cacheability_metadata ? $generated_url->setGeneratedUrl($url) : $url;
}
else {
$path = ltrim($this->processPath($path, $options), '/');
$path = ltrim($this->processPath($path, $options, $generated_url), '/');
}
if (!isset($options['script'])) {
......@@ -449,15 +463,20 @@ public function generateFromPath($path = NULL, $options = array()) {
$base = $options['absolute'] ? $options['base_url'] : $current_base_path;
$prefix = empty($path) ? rtrim($options['prefix'], '/') : $options['prefix'];
if ($options['absolute'] && $collect_cacheability_metadata) {
$generated_url->addCacheContexts(['url.site']);
}
$path = str_replace('%2F', '/', rawurlencode($prefix . $path));
$query = $options['query'] ? ('?' . UrlHelper::buildQuery($options['query'])) : '';
return $base . $options['script'] . $path . $query . $options['fragment'];
$url = $base . $options['script'] . $path . $query . $options['fragment'];
return $collect_cacheability_metadata ? $generated_url->setGeneratedUrl($url) : $url;
}
/**
* Passes the path to a processor manager to allow alterations.
*/
protected function processPath($path, &$options = array()) {
protected function processPath($path, &$options = array(), CacheableMetadata $cacheable_metadata = NULL) {
// Router-based paths may have a querystring on them.
if ($query_pos = strpos($path, '?')) {
// We don't need to do a strict check here because position 0 would mean we
......@@ -469,7 +488,7 @@ protected function processPath($path, &$options = array()) {
$actual_path = $path;
$query_string = '';
}
$path = '/' . $this->pathProcessor->processOutbound(trim($actual_path, '/'), $options, $this->requestStack->getCurrentRequest());
$path = '/' . $this->pathProcessor->processOutbound(trim($actual_path, '/'), $options, $this->requestStack->getCurrentRequest(), $cacheable_metadata);
$path .= $query_string;
return $path;
}
......@@ -483,9 +502,11 @@ protected function processPath($path, &$options = array()) {
* The route object to process.
* @param array $parameters
* An array of parameters to be passed to the route compiler.
* @param \Drupal\Core\Cache\CacheableMetadata $cacheable_metadata
* (optional) Object to collect route processors' cacheability.
*/
protected function processRoute($name, SymfonyRoute $route, array &$parameters) {
$this->routeProcessor->processOutbound($name, $route, $parameters);
protected function processRoute($name, SymfonyRoute $route, array &$parameters, CacheableMetadata $cacheable_metadata = NULL) {
$this->routeProcessor->processOutbound($name, $route, $parameters, $cacheable_metadata);
}
/**
......
......@@ -70,9 +70,14 @@ interface UrlGeneratorInterface extends VersatileGeneratorInterface {
* set if _url() is invoked by Drupal\Core\Entity\Entity::uri().
* - 'entity': The entity object (such as a node) for which the URL is being
* generated. Only set if _url() is invoked by Drupal\Core\Entity\Entity::uri().
* @param bool $collect_cacheability_metadata
* (optional) Defaults to FALSE. When TRUE, both the generated URL and its
* associated cacheability metadata are returned.
*
* @return
* @return string|\Drupal\Core\GeneratedUrl
* A string containing a URL to the given path.
* When $collect_cacheability_metadata is TRUE, a GeneratedUrl object is
* returned, containing the generated URL plus cacheability metadata.
*
* @throws \Drupal\Core\Routing\GeneratorNotInitializedException.
*
......@@ -85,8 +90,9 @@ interface UrlGeneratorInterface extends VersatileGeneratorInterface {
* @see static::generateFromRoute()
* @see \Drupal\Core\Utility\UnroutedUrlAssembler
* @see \Drupal\Core\Url
* @see \Drupal\Core\GeneratedUrl
*/
public function generateFromPath($path = NULL, $options = array());
public function generateFromPath($path = NULL, $options = array(), $collect_cacheability_metadata = FALSE);
/**
* Gets the internal path (system path) of a route.
......@@ -100,7 +106,7 @@ public function generateFromPath($path = NULL, $options = array());
* @return string
* The internal Drupal path corresponding to the route.
*
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 8.0.0
* System paths should not be used - use route names and parameters.
*/
public function getPathFromRoute($name, $parameters = array());
......@@ -136,9 +142,14 @@ public function getPathFromRoute($name, $parameters = array());
* 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.
* @param bool $collect_cacheability_metadata
* (optional) Defaults to FALSE. When TRUE, both the generated URL and its
* associated cacheability metadata are returned.
*
* @return string
* @return string|\Drupal\Core\GeneratedUrl
* The generated URL for the given route.
* When $collect_cacheability_metadata is TRUE, a GeneratedUrl object is
* returned, containing the generated URL plus cacheability metadata.
*
* @throws \Symfony\Component\Routing\Exception\RouteNotFoundException
* Thrown when the named route does not exist.
......@@ -148,6 +159,6 @@ public function getPathFromRoute($name, $parameters = array());
* Thrown when a parameter value for a placeholder is not correct because it
* does not match the requirement.
*/