3 namespace Drupal\Core\Render;
5 use Drupal\Core\GeneratedUrl;
6 use Drupal\Core\Routing\UrlGeneratorInterface;
7 use Symfony\Component\Routing\RequestContext as SymfonyRequestContext;
10 * Decorator for the URL generator, which bubbles bubbleable URL metadata.
12 * Implements a decorator for the URL generator that allows to automatically
13 * collect and bubble up bubbleable metadata associated with URLs due to
14 * outbound path and route processing. This approach helps keeping the render
15 * and the routing subsystems decoupled.
17 * @see \Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface
18 * @see \Drupal\Core\PathProcessor\OutboundPathProcessorInterface
19 * @see \Drupal\Core\Render\BubbleableMetadata
21 class MetadataBubblingUrlGenerator implements UrlGeneratorInterface {
24 * The non-bubbling URL generator.
26 * @var \Drupal\Core\Routing\UrlGeneratorInterface
28 protected $urlGenerator;
33 * @var \Drupal\Core\Render\RendererInterface
38 * Constructs a new bubbling URL generator service.
40 * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
41 * The non-bubbling URL generator.
42 * @param \Drupal\Core\Render\RendererInterface $renderer
45 public function __construct(UrlGeneratorInterface $url_generator, RendererInterface $renderer) {
46 $this->urlGenerator = $url_generator;
47 $this->renderer = $renderer;
53 public function setContext(SymfonyRequestContext $context) {
54 $this->urlGenerator->setContext($context);
60 public function getContext() {
61 return $this->urlGenerator->getContext();
67 public function getPathFromRoute($name, $parameters = []) {
68 return $this->urlGenerator->getPathFromRoute($name, $parameters);
72 * Bubbles the bubbleable metadata to the current render context.
74 * @param \Drupal\Core\GeneratedUrl $generated_url
75 * The generated URL whose bubbleable metadata to bubble.
76 * @param array $options
77 * (optional) The URL options. Defaults to none.
79 protected function bubble(GeneratedUrl $generated_url, array $options = []) {
80 // Bubbling metadata makes sense only if the code is executed inside a
81 // render context. All code running outside controllers has no render
82 // context by default, so URLs used there are not supposed to affect the
83 // response cacheability.
84 if ($this->renderer->hasRenderContext()) {
86 $generated_url->applyTo($build);
87 $this->renderer->render($build);
94 public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH) {
95 $options['absolute'] = is_bool($referenceType) ? $referenceType : $referenceType === self::ABSOLUTE_URL;
96 $generated_url = $this->generateFromRoute($name, $parameters, $options, TRUE);
97 $this->bubble($generated_url);
98 return $generated_url->getGeneratedUrl();
104 public function generateFromRoute($name, $parameters = [], $options = [], $collect_bubbleable_metadata = FALSE) {
105 $generated_url = $this->urlGenerator->generateFromRoute($name, $parameters, $options, TRUE);
106 if (!$collect_bubbleable_metadata) {
107 $this->bubble($generated_url, $options);
109 return $collect_bubbleable_metadata ? $generated_url : $generated_url->getGeneratedUrl();
115 public function supports($name) {
116 return $this->urlGenerator->supports($name);
122 public function getRouteDebugMessage($name, array $parameters = []) {
123 return $this->urlGenerator->getRouteDebugMessage($name, $parameters);