summaryrefslogtreecommitdiffstats
path: root/core/lib/Drupal/Core/Utility/Token.php
diff options
context:
space:
mode:
Diffstat (limited to 'core/lib/Drupal/Core/Utility/Token.php')
-rw-r--r--core/lib/Drupal/Core/Utility/Token.php76
1 files changed, 64 insertions, 12 deletions
diff --git a/core/lib/Drupal/Core/Utility/Token.php b/core/lib/Drupal/Core/Utility/Token.php
index 075abb5..9966726 100644
--- a/core/lib/Drupal/Core/Utility/Token.php
+++ b/core/lib/Drupal/Core/Utility/Token.php
@@ -8,11 +8,15 @@
namespace Drupal\Core\Utility;
use Drupal\Core\Cache\Cache;
+use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\Core\Render\AttachmentsInterface;
+use Drupal\Core\Render\BubbleableMetadata;
+use Drupal\Core\Render\RendererInterface;
/**
* Drupal placeholder/token replacement system.
@@ -105,6 +109,13 @@ class Token {
protected $cacheTagsInvalidator;
/**
+ * The renderer.
+ *
+ * @var \Drupal\Core\Render\RendererInterface
+ */
+ protected $renderer;
+
+ /**
* Constructs a new class instance.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
@@ -115,12 +126,15 @@ class Token {
* The language manager.
* @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_invalidator
* The cache tags invalidator.
+ * @param \Drupal\Core\Render\RendererInterface $renderer
+ * The renderer.
*/
- public function __construct(ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, CacheTagsInvalidatorInterface $cache_tags_invalidator) {
+ public function __construct(ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, CacheTagsInvalidatorInterface $cache_tags_invalidator, RendererInterface $renderer) {
$this->cache = $cache;
$this->languageManager = $language_manager;
$this->moduleHandler = $module_handler;
$this->cacheTagsInvalidator = $cache_tags_invalidator;
+ $this->renderer = $renderer;
}
/**
@@ -152,19 +166,39 @@ class Token {
* \Drupal\Component\Utility\Xss::filter(),
* \Drupal\Component\Utility\SafeMarkup::checkPlain() or other appropriate
* scrubbing functions before displaying data to users.
+ * @param \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata|null
+ * (optional) An object to which static::generate() and the hooks and
+ * functions that it invokes will add their required bubbleable metadata.
+ *
+ * To ensure that the metadata associated with the token replacements gets
+ * attached to the same render array that contains the token-replaced text,
+ * callers of this method are encouraged to pass in a BubbleableMetadata
+ * object and apply it to the corresponding render array. For example:
+ * @code
+ * $bubbleable_metadata = new BubbleableMetadata();
+ * $build['#markup'] = $token_service->replace('Tokens: [node:nid] [current-user:uid]', ['node' => $node], [], $bubbleable_metadata);
+ * $bubbleable_metadata->applyTo($build);
+ * @endcode
+ *
+ * When the caller does not pass in a BubbleableMetadata object, this
+ * method creates a local one, and applies the collected metadata to the
+ * Renderer's currently active render context.
*
* @return string
* Text with tokens replaced.
*/
- public function replace($text, array $data = array(), array $options = array()) {
+ public function replace($text, array $data = array(), array $options = array(), BubbleableMetadata $bubbleable_metadata = NULL) {
$text_tokens = $this->scan($text);
if (empty($text_tokens)) {
return $text;
}
+ $bubbleable_metadata_is_passed_in = (bool) $bubbleable_metadata;
+ $bubbleable_metadata = $bubbleable_metadata ?: new BubbleableMetadata();
+
$replacements = array();
foreach ($text_tokens as $type => $tokens) {
- $replacements += $this->generate($type, $tokens, $data, $options);
+ $replacements += $this->generate($type, $tokens, $data, $options, $bubbleable_metadata);
if (!empty($options['clear'])) {
$replacements += array_fill_keys($tokens, '');
}
@@ -173,12 +207,20 @@ class Token {
// Optionally alter the list of replacement values.
if (!empty($options['callback'])) {
$function = $options['callback'];
- $function($replacements, $data, $options);
+ $function($replacements, $data, $options, $bubbleable_metadata);
}
$tokens = array_keys($replacements);
$values = array_values($replacements);
+ // If a local $bubbleable_metadata object was created, apply the metadata
+ // it collected to the renderer's currently active render context.
+ if (!$bubbleable_metadata_is_passed_in && $this->renderer->hasRenderContext()) {
+ $build = [];
+ $bubbleable_metadata->applyTo($build);
+ $this->renderer->render($build);
+ }
+
return str_replace($tokens, $values, $text);
}
@@ -226,14 +268,14 @@ class Token {
* An array of tokens to be replaced, keyed by the literal text of the token
* as it appeared in the source text.
* @param array $data
- * (optional) An array of keyed objects. For simple replacement scenarios
- * 'node', 'user', and others are common keys, with an accompanying node or
- * user object being the value. Some token types, like 'site', do not require
+ * An array of keyed objects. For simple replacement scenarios: 'node',
+ * 'user', and others are common keys, with an accompanying node or user
+ * object being the value. Some token types, like 'site', do not require
* any explicit information from $data and can be replaced even if it is
* empty.
* @param array $options
- * (optional) A keyed array of settings and flags to control the token
- * replacement process. Supported options are:
+ * A keyed array of settings and flags to control the token replacement
+ * process. Supported options are:
* - langcode: A language code to be used when generating locale-sensitive
* tokens.
* - callback: A callback function that will be used to post-process the
@@ -245,6 +287,9 @@ class Token {
* responsibility for running \Drupal\Component\Utility\Xss::filter(),
* \Drupal\Component\Utility\SafeMarkup::checkPlain() or other appropriate
* scrubbing functions before displaying data to users.
+ * @param \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata
+ * The bubbleable metadata. This is passed to the token replacement
+ * implementations so that they can attach their metadata.
*
* @return array
* An associative array of replacement values, keyed by the original 'raw'
@@ -254,9 +299,16 @@ class Token {
* @see hook_tokens()
* @see hook_tokens_alter()
*/
- public function generate($type, array $tokens, array $data = array(), array $options = array()) {
+ public function generate($type, array $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
$options += array('sanitize' => TRUE);
- $replacements = $this->moduleHandler->invokeAll('tokens', array($type, $tokens, $data, $options));
+
+ foreach ($data as $object) {
+ if ($object instanceof CacheableDependencyInterface || $object instanceof AttachmentsInterface) {
+ $bubbleable_metadata->addCacheableDependency($object);
+ }
+ }
+
+ $replacements = $this->moduleHandler->invokeAll('tokens', [$type, $tokens, $data, $options, $bubbleable_metadata]);
// Allow other modules to alter the replacements.
$context = array(
@@ -265,7 +317,7 @@ class Token {
'data' => $data,
'options' => $options,
);
- $this->moduleHandler->alter('tokens', $replacements, $context);
+ $this->moduleHandler->alter('tokens', $replacements, $context, $bubbleable_metadata);
return $replacements;
}