You are here

class Token in Token 8

Service to retrieve token information.

This service replaces the core's token service and provides the same functionality by extending it. It also provides additional functionality commonly required by the additional support provided by token module and other modules.

Hierarchy

Expanded class hierarchy of Token

2 string references to 'Token'
token.info.yml in ./token.info.yml
token.info.yml
TokenTreeTable::preRenderTokenTree in src/Element/TokenTreeTable.php
Pre-render the token tree to transform rows in the token tree.

File

src/Token.php, line 17

Namespace

Drupal\token
View source
class Token extends TokenBase implements TokenInterface {

  /**
   * Token definitions.
   *
   * @var array[]|null
   *   An array of token definitions, or NULL when the definitions are not set.
   *
   * @see self::resetInfo()
   */
  protected $globalTokenTypes;

  /**
   * {@inheritdoc}
   */
  public function getInfo() {
    if (empty($this->tokenInfo)) {
      $cache_id = 'token_info_sorted:' . $this->languageManager
        ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
        ->getId();
      $cache = $this->cache
        ->get($cache_id);
      if ($cache) {
        $this->tokenInfo = $cache->data;
      }
      else {
        $token_info = $this->moduleHandler
          ->invokeAll('token_info');
        $this->moduleHandler
          ->alter('token_info', $token_info);
        foreach (array_keys($token_info['types']) as $type_key) {
          if (isset($token_info['types'][$type_key]['type'])) {
            $base_type = $token_info['types'][$type_key]['type'];

            // If this token type extends another token type, then merge in
            // the base token type's tokens.
            if (isset($token_info['tokens'][$base_type])) {
              $token_info['tokens'] += [
                $type_key => [],
              ];
              $token_info['tokens'][$type_key] += $token_info['tokens'][$base_type];
            }
          }
          else {

            // Add a 'type' value to each token type information.
            $token_info['types'][$type_key]['type'] = $type_key;
          }
        }

        // Pre-sort tokens.
        $by_name = $this
          ->prepareMultisort($token_info['types']);
        array_multisort($by_name, SORT_ASC, SORT_NATURAL | SORT_FLAG_CASE, $token_info['types']);
        foreach (array_keys($token_info['tokens']) as $type) {
          $by_name = $this
            ->prepareMultisort($token_info['tokens'][$type]);
          array_multisort($by_name, SORT_ASC, SORT_NATURAL | SORT_FLAG_CASE, $token_info['tokens'][$type]);
        }
        $this->tokenInfo = $token_info;
        $this->cache
          ->set($cache_id, $this->tokenInfo, CacheBackendInterface::CACHE_PERMANENT, [
          static::TOKEN_INFO_CACHE_TAG,
        ]);
      }
    }
    return $this->tokenInfo;
  }

  /**
   * Extracts data from the token data for use in array_multisort().
   *
   * @param array $token_info
   *   List of tokens or token types, each element must have a name key.
   *
   * @return string[]
   *   List of the names keyed by the token key.
   */
  protected function prepareMultisort($token_info) {
    $by_name = [];
    foreach ($token_info as $key => $token_info_element) {
      $by_name[$key] = $token_info_element['name'];
    }
    return $by_name;
  }

  /**
   * {@inheritdoc}
   */
  public function getTokenInfo($token_type, $token) {
    if (empty($this->tokenInfo)) {
      $this
        ->getInfo();
    }
    return isset($this->tokenInfo['tokens'][$token_type][$token]) ? $this->tokenInfo['tokens'][$token_type][$token] : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function getTypeInfo($token_type) {
    if (empty($this->tokenInfo)) {
      $this
        ->getInfo();
    }
    return isset($this->tokenInfo['types'][$token_type]) ? $this->tokenInfo['types'][$token_type] : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function getGlobalTokenTypes() {
    if (empty($this->globalTokenTypes)) {
      $token_info = $this
        ->getInfo();
      foreach ($token_info['types'] as $type => $type_info) {

        // If the token types has not specified that 'needs-data' => TRUE, then
        // it is a global token type that will always be replaced in any context.
        if (empty($type_info['needs-data'])) {
          $this->globalTokenTypes[] = $type;
        }
      }
    }
    return $this->globalTokenTypes;
  }

  /**
   * {@inheritdoc}
   */
  function getInvalidTokens($type, $tokens) {
    $token_info = $this
      ->getInfo();
    $invalid_tokens = [];
    foreach ($tokens as $token => $full_token) {
      if (isset($token_info['tokens'][$type][$token])) {
        continue;
      }

      // Split token up if it has chains.
      $parts = explode(':', $token, 2);
      if (!isset($token_info['tokens'][$type][$parts[0]])) {

        // This is an invalid token (not defined).
        $invalid_tokens[] = $full_token;
      }
      elseif (count($parts) == 2) {
        $sub_token_info = $token_info['tokens'][$type][$parts[0]];
        if (!empty($sub_token_info['dynamic'])) {

          // If this token has been flagged as a dynamic token, skip it.
          continue;
        }
        elseif (empty($sub_token_info['type'])) {

          // If the token has chains, but does not support it, it is invalid.
          $invalid_tokens[] = $full_token;
        }
        else {

          // Recursively check the chained tokens.
          $sub_tokens = $this
            ->findWithPrefix([
            $token => $full_token,
          ], $parts[0]);
          $invalid_tokens = array_merge($invalid_tokens, $this
            ->getInvalidTokens($sub_token_info['type'], $sub_tokens));
        }
      }
    }
    return $invalid_tokens;
  }

  /**
   * {@inheritdoc}
   */
  public function getInvalidTokensByContext($value, array $valid_types = []) {
    if (in_array('all', $valid_types)) {
      $info = $this
        ->getInfo();
      $valid_types = array_keys($info['types']);
    }
    else {

      // Add the token types that are always valid in global context.
      $valid_types = array_merge($valid_types, $this
        ->getGlobalTokenTypes());
    }
    $invalid_tokens = [];
    $value_tokens = is_string($value) ? $this
      ->scan($value) : $value;
    foreach ($value_tokens as $type => $tokens) {
      if (!in_array($type, $valid_types)) {

        // If the token type is not a valid context, its tokens are invalid.
        $invalid_tokens = array_merge($invalid_tokens, array_values($tokens));
      }
      else {

        // Check each individual token for validity.
        $invalid_tokens = array_merge($invalid_tokens, $this
          ->getInvalidTokens($type, $tokens));
      }
    }
    array_unique($invalid_tokens);
    return $invalid_tokens;
  }

  /**
   * {@inheritdoc}
   */
  public function resetInfo() {
    parent::resetInfo();
    $this->globalTokenTypes = NULL;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
Token::$cache protected property The token cache.
Token::$cacheTagsInvalidator protected property The cache tags invalidator.
Token::$globalTokenTypes protected property Token definitions.
Token::$languageManager protected property The language manager.
Token::$moduleHandler protected property The module handler service.
Token::$renderer protected property The renderer.
Token::$tokenInfo protected property Token definitions.
Token::findWithPrefix public function Returns a list of tokens that begin with a specific prefix.
Token::generate public function Generates replacement values for a list of tokens.
Token::getGlobalTokenTypes public function Get a list of token types that can be used without any context (global). Overrides TokenInterface::getGlobalTokenTypes
Token::getInfo public function Returns metadata describing supported tokens. Overrides Token::getInfo
Token::getInvalidTokens function Validate an array of tokens based on their token type. Overrides TokenInterface::getInvalidTokens
Token::getInvalidTokensByContext public function Validate tokens in raw text based on possible contexts. Overrides TokenInterface::getInvalidTokensByContext
Token::getTokenInfo public function Returns metadata describing supported a token. Overrides TokenInterface::getTokenInfo
Token::getTypeInfo public function Returns metadata describing supported token types. Overrides TokenInterface::getTypeInfo
Token::prepareMultisort protected function Extracts data from the token data for use in array_multisort().
Token::replace public function Replaces all tokens in a given string with appropriate values.
Token::resetInfo public function Resets metadata describing supported tokens. Overrides Token::resetInfo
Token::scan public function Builds a list of all token-like patterns that appear in the text.
Token::setInfo public function Sets metadata describing supported tokens.
Token::TOKEN_INFO_CACHE_TAG constant The tag to cache token info with.
Token::__construct public function Constructs a new class instance.