MetadataBubblingUrlGenerator.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <?php
  2. namespace Drupal\Core\Render;
  3. use Drupal\Core\GeneratedUrl;
  4. use Drupal\Core\Routing\UrlGeneratorInterface;
  5. use Symfony\Component\Routing\RequestContext as SymfonyRequestContext;
  6. /**
  7. * Decorator for the URL generator, which bubbles bubbleable URL metadata.
  8. *
  9. * Implements a decorator for the URL generator that allows to automatically
  10. * collect and bubble up bubbleable metadata associated with URLs due to
  11. * outbound path and route processing. This approach helps keeping the render
  12. * and the routing subsystems decoupled.
  13. *
  14. * @see \Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface
  15. * @see \Drupal\Core\PathProcessor\OutboundPathProcessorInterface
  16. * @see \Drupal\Core\Render\BubbleableMetadata
  17. */
  18. class MetadataBubblingUrlGenerator implements UrlGeneratorInterface {
  19. /**
  20. * The non-bubbling URL generator.
  21. *
  22. * @var \Drupal\Core\Routing\UrlGeneratorInterface
  23. */
  24. protected $urlGenerator;
  25. /**
  26. * The renderer.
  27. *
  28. * @var \Drupal\Core\Render\RendererInterface
  29. */
  30. protected $renderer;
  31. /**
  32. * Constructs a new bubbling URL generator service.
  33. *
  34. * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
  35. * The non-bubbling URL generator.
  36. * @param \Drupal\Core\Render\RendererInterface $renderer
  37. * The renderer.
  38. */
  39. public function __construct(UrlGeneratorInterface $url_generator, RendererInterface $renderer) {
  40. $this->urlGenerator = $url_generator;
  41. $this->renderer = $renderer;
  42. }
  43. /**
  44. * {@inheritdoc}
  45. */
  46. public function setContext(SymfonyRequestContext $context) {
  47. $this->urlGenerator->setContext($context);
  48. }
  49. /**
  50. * {@inheritdoc}
  51. */
  52. public function getContext() {
  53. return $this->urlGenerator->getContext();
  54. }
  55. /**
  56. * {@inheritdoc}
  57. */
  58. public function getPathFromRoute($name, $parameters = []) {
  59. return $this->urlGenerator->getPathFromRoute($name, $parameters);
  60. }
  61. /**
  62. * Bubbles the bubbleable metadata to the current render context.
  63. *
  64. * @param \Drupal\Core\GeneratedUrl $generated_url
  65. * The generated URL whose bubbleable metadata to bubble.
  66. * @param array $options
  67. * (optional) The URL options. Defaults to none.
  68. */
  69. protected function bubble(GeneratedUrl $generated_url, array $options = []) {
  70. // Bubbling metadata makes sense only if the code is executed inside a
  71. // render context. All code running outside controllers has no render
  72. // context by default, so URLs used there are not supposed to affect the
  73. // response cacheability.
  74. if ($this->renderer->hasRenderContext()) {
  75. $build = [];
  76. $generated_url->applyTo($build);
  77. $this->renderer->render($build);
  78. }
  79. }
  80. /**
  81. * {@inheritdoc}
  82. */
  83. public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH) {
  84. $options['absolute'] = is_bool($referenceType) ? $referenceType : $referenceType === self::ABSOLUTE_URL;
  85. $generated_url = $this->generateFromRoute($name, $parameters, $options, TRUE);
  86. $this->bubble($generated_url);
  87. return $generated_url->getGeneratedUrl();
  88. }
  89. /**
  90. * {@inheritdoc}
  91. */
  92. public function generateFromRoute($name, $parameters = [], $options = [], $collect_bubbleable_metadata = FALSE) {
  93. $generated_url = $this->urlGenerator->generateFromRoute($name, $parameters, $options, TRUE);
  94. if (!$collect_bubbleable_metadata) {
  95. $this->bubble($generated_url, $options);
  96. }
  97. return $collect_bubbleable_metadata ? $generated_url : $generated_url->getGeneratedUrl();
  98. }
  99. /**
  100. * {@inheritdoc}
  101. */
  102. public function supports($name) {
  103. return $this->urlGenerator->supports($name);
  104. }
  105. /**
  106. * {@inheritdoc}
  107. */
  108. public function getRouteDebugMessage($name, array $parameters = []) {
  109. return $this->urlGenerator->getRouteDebugMessage($name, $parameters);
  110. }
  111. }