class LinkGenerator
Same name in other branches
- 8.9.x core/lib/Drupal/Core/Utility/LinkGenerator.php \Drupal\Core\Utility\LinkGenerator
- 10 core/lib/Drupal/Core/Utility/LinkGenerator.php \Drupal\Core\Utility\LinkGenerator
- 11.x core/lib/Drupal/Core/Utility/LinkGenerator.php \Drupal\Core\Utility\LinkGenerator
Provides a class which generates a link with route names and parameters.
Hierarchy
- class \Drupal\Core\Utility\LinkGenerator implements \Drupal\Core\Utility\LinkGeneratorInterface
Expanded class hierarchy of LinkGenerator
2 files declare their use of LinkGenerator
- FieldPluginBaseTest.php in core/
modules/ views/ tests/ src/ Unit/ Plugin/ field/ FieldPluginBaseTest.php - Contains \Drupal\Tests\views\Unit\Plugin\field\FieldPluginBaseTest.
- LinkGeneratorTest.php in core/
tests/ Drupal/ Tests/ Core/ Utility/ LinkGeneratorTest.php
1 string reference to 'LinkGenerator'
- core.services.yml in core/
core.services.yml - core/core.services.yml
1 service uses LinkGenerator
File
-
core/
lib/ Drupal/ Core/ Utility/ LinkGenerator.php, line 21
Namespace
Drupal\Core\UtilityView source
class LinkGenerator implements LinkGeneratorInterface {
/**
* The URL generator.
*
* @var \Drupal\Core\Routing\UrlGeneratorInterface
*/
protected $urlGenerator;
/**
* The module handler firing the route_link alter hook.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The renderer service.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* Constructs a LinkGenerator instance.
*
* @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
* The url generator.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
*/
public function __construct(UrlGeneratorInterface $url_generator, ModuleHandlerInterface $module_handler, RendererInterface $renderer) {
$this->urlGenerator = $url_generator;
$this->moduleHandler = $module_handler;
$this->renderer = $renderer;
}
/**
* {@inheritdoc}
*/
public function generateFromLink(Link $link) {
return $this->generate($link->getText(), $link->getUrl());
}
/**
* {@inheritdoc}
*
* For anonymous users, the "active" class will be calculated on the server,
* because most sites serve each anonymous user the same cached page anyway.
* For authenticated users, the "active" class will be calculated on the
* client (through JavaScript), only data- attributes are added to links to
* prevent breaking the render cache. The JavaScript is added in
* system_page_attachments().
*
* @see system_page_attachments()
*/
public function generate($text, Url $url) {
// The link generator should not modify the original URL object, this
// ensures consistent rendering.
// @see https://www.drupal.org/node/2842399
$url = clone $url;
// Performance: avoid Url::toString() needing to retrieve the URL generator
// service from the container.
$url->setUrlGenerator($this->urlGenerator);
if (is_array($text)) {
$text = $this->renderer
->render($text);
}
// Start building a structured representation of our link to be altered later.
$variables = [
'text' => $text,
'url' => $url,
'options' => $url->getOptions(),
];
// Merge in default options.
$variables['options'] += [
'attributes' => [],
'query' => [],
'language' => NULL,
'set_active_class' => FALSE,
'absolute' => FALSE,
];
// Add a hreflang attribute if we know the language of this link's URL and
// hreflang has not already been set.
if (!empty($variables['options']['language']) && !isset($variables['options']['attributes']['hreflang'])) {
$variables['options']['attributes']['hreflang'] = $variables['options']['language']->getId();
}
// Ensure that query values are strings.
array_walk($variables['options']['query'], function (&$value) {
if ($value instanceof MarkupInterface) {
$value = (string) $value;
}
});
// Set the "active" class if the 'set_active_class' option is not empty.
if (!empty($variables['options']['set_active_class']) && !$url->isExternal()) {
// Add a "data-drupal-link-query" attribute to let the
// drupal.active-link library know the query in a standardized manner.
if (!empty($variables['options']['query'])) {
$query = $variables['options']['query'];
ksort($query);
$variables['options']['attributes']['data-drupal-link-query'] = Json::encode($query);
}
// Add a "data-drupal-link-system-path" attribute to let the
// drupal.active-link library know the path in a standardized manner.
if ($url->isRouted() && !isset($variables['options']['attributes']['data-drupal-link-system-path'])) {
// @todo System path is deprecated - use the route name and parameters.
$system_path = $url->getInternalPath();
// Special case for the front page.
if ($url->getRouteName() === '<front>') {
$system_path = '<front>';
}
if (!empty($system_path)) {
$variables['options']['attributes']['data-drupal-link-system-path'] = $system_path;
}
}
}
// Remove all HTML and PHP tags from a tooltip, calling expensive strip_tags()
// only when a quick strpos() gives suspicion tags are present.
if (isset($variables['options']['attributes']['title']) && strpos($variables['options']['attributes']['title'], '<') !== FALSE) {
$variables['options']['attributes']['title'] = strip_tags($variables['options']['attributes']['title']);
}
// Allow other modules to modify the structure of the link.
$this->moduleHandler
->alter('link', $variables);
$url = $variables['url'];
// Move attributes out of options since generateFromRoute() doesn't need
// them. Make sure the "href" comes first for testing purposes.
$attributes = [
'href' => '',
] + $variables['options']['attributes'];
unset($variables['options']['attributes']);
$url->setOptions($variables['options']);
// External URLs can not have cacheable metadata.
if ($url->isExternal()) {
$generated_link = new GeneratedLink();
$attributes['href'] = $url->toString(FALSE);
return $this->doGenerate($generated_link, $attributes, $variables);
}
if ($url->isRouted() && $url->getRouteName() === '<nolink>') {
$generated_link = new GeneratedNoLink();
unset($attributes['href'], $attributes['hreflang']);
return $this->doGenerate($generated_link, $attributes, $variables);
}
if ($url->isRouted() && $url->getRouteName() === '<button>') {
$generated_link = new GeneratedButton();
$attributes['type'] = 'button';
unset($attributes['href'], $attributes['hreflang']);
return $this->doGenerate($generated_link, $attributes, $variables);
}
$generated_url = $url->toString(TRUE);
$generated_link = GeneratedLink::createFromObject($generated_url);
// The result of the URL generator is a plain-text URL to use as the href
// attribute, and it is escaped by \Drupal\Core\Template\Attribute.
$attributes['href'] = $generated_url->getGeneratedUrl();
return $this->doGenerate($generated_link, $attributes, $variables);
}
/**
* Generates the link.
*
* @param Drupal\Core\GeneratedLink $generated_link
* The generated link, along with its associated cacheability metadata.
* @param array $attributes
* The attributes of the generated link.
* @param array $variables
* The link text, url, and other options.
*
* @return Drupal\Core\GeneratedLink
* The generated link, along with its associated cacheability metadata.
*/
protected function doGenerate($generated_link, $attributes, $variables) {
if (!$variables['text'] instanceof MarkupInterface) {
$variables['text'] = Html::escape($variables['text']);
}
$attributes = new Attribute($attributes);
// This is safe because Attribute does escaping and $variables['text'] is
// either rendered or escaped.
return $generated_link->setGeneratedLink('<' . $generated_link::TAG . $attributes . '>' . $variables['text'] . '</' . $generated_link::TAG . '>');
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title |
---|---|---|---|---|
LinkGenerator::$moduleHandler | protected | property | The module handler firing the route_link alter hook. | |
LinkGenerator::$renderer | protected | property | The renderer service. | |
LinkGenerator::$urlGenerator | protected | property | The URL generator. | |
LinkGenerator::doGenerate | protected | function | Generates the link. | |
LinkGenerator::generate | public | function | For anonymous users, the "active" class will be calculated on the server, because most sites serve each anonymous user the same cached page anyway. For authenticated users, the "active" class will be calculated on the client… |
Overrides LinkGeneratorInterface::generate |
LinkGenerator::generateFromLink | public | function | Renders a link from a link object. | Overrides LinkGeneratorInterface::generateFromLink |
LinkGenerator::__construct | public | function | Constructs a LinkGenerator instance. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.