You are here

protected function PluginBase::viewsTokenReplace in Drupal 10

Same name and namespace in other branches
  1. 8 core/modules/views/src/Plugin/views/PluginBase.php \Drupal\views\Plugin\views\PluginBase::viewsTokenReplace()
  2. 9 core/modules/views/src/Plugin/views/PluginBase.php \Drupal\views\Plugin\views\PluginBase::viewsTokenReplace()

Replaces Views' tokens in a given string. The resulting string will be sanitized with Xss::filterAdmin.

Parameters

$text: Unsanitized string with possible tokens.

$tokens: Array of token => replacement_value items.

Return value

string

1 call to PluginBase::viewsTokenReplace()
StylePluginBase::tokenizeValue in core/modules/views/src/Plugin/views/style/StylePluginBase.php
Take a value and apply token replacement logic to it.

File

core/modules/views/src/Plugin/views/PluginBase.php, line 352

Class

PluginBase

Namespace

Drupal\views\Plugin\views

Code

protected function viewsTokenReplace($text, $tokens) {
  if (!strlen($text)) {

    // No need to run filterAdmin on an empty string.
    return '';
  }
  if (empty($tokens)) {
    return Xss::filterAdmin($text);
  }
  $twig_tokens = [];
  foreach ($tokens as $token => $replacement) {

    // Twig wants a token replacement array stripped of curly-brackets.
    // Some Views tokens come with curly-braces, others do not.
    // @todo: https://www.drupal.org/node/2544392
    if (strpos($token, '{{') !== FALSE) {

      // Twig wants a token replacement array stripped of curly-brackets.
      $token = trim(str_replace([
        '{{',
        '}}',
      ], '', $token));
    }

    // Check for arrays in Twig tokens. Internally these are passed as
    // dot-delimited strings, but need to be turned into associative arrays
    // for parsing.
    if (strpos($token, '.') === FALSE) {

      // We need to validate tokens are valid Twig variables. Twig uses the
      // same variable naming rules as PHP.
      // @see http://php.net/manual/language.variables.basics.php
      assert(preg_match('/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$/', $token) === 1, 'Tokens need to be valid Twig variables.');
      $twig_tokens[$token] = $replacement;
    }
    else {
      $parts = explode('.', $token);
      $top = array_shift($parts);
      assert(preg_match('/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$/', $top) === 1, 'Tokens need to be valid Twig variables.');
      $token_array = [
        array_pop($parts) => $replacement,
      ];
      foreach (array_reverse($parts) as $key) {

        // The key could also be numeric (array index) so allow that.
        assert(is_numeric($key) || preg_match('/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$/', $key) === 1, 'Tokens need to be valid Twig variables.');
        $token_array = [
          $key => $token_array,
        ];
      }
      if (!isset($twig_tokens[$top])) {
        $twig_tokens[$top] = [];
      }
      $twig_tokens[$top] += $token_array;
    }
  }
  if ($twig_tokens) {

    // Use the unfiltered text for the Twig template, then filter the output.
    // Otherwise, Xss::filterAdmin could remove valid Twig syntax before the
    // template is parsed.
    $build = [
      '#type' => 'inline_template',
      '#template' => $text,
      '#context' => $twig_tokens,
      '#post_render' => [
        function ($children, $elements) {
          return Xss::filterAdmin($children);
        },
      ],
    ];

    // Currently you cannot attach assets to tokens with
    // Renderer::renderPlain(). This may be unnecessarily limiting. Consider
    // using Renderer::executeInRenderContext() instead.
    // @todo: https://www.drupal.org/node/2566621
    return (string) $this
      ->getRenderer()
      ->renderPlain($build);
  }
  else {
    return Xss::filterAdmin($text);
  }
}