123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- <?php
- namespace Drupal\token;
- use Drupal\Core\Cache\CacheBackendInterface;
- use Drupal\Core\Language\LanguageInterface;
- use Drupal\Core\Utility\Token as TokenBase;
- /**
- * 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.
- */
- 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, array(
- 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 = array();
- 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(array($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 = array();
- $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;
- }
- }
|