Your tokens/types aren't structured quite right. You want big
and small
to be tokens in the state
type (not the user
), and you want the token you're adding to the user
type to be of type state
.
The code explains it better:
$types['state'] = array(
'name' => t('State'),
'description' => t('Tokens related to user state.'),
'needs-data' => 'user',
);
$tokens['state']['big'] = array(
'name' => t('User State (Big)'),
'description' => t('The big state of the user.'),
);
$tokens['state']['small'] = array(
'name' => t('User State (Small)'),
'description' => t('The small state of the user.'),
);
$tokens['user']['state'] = array(
'name' => t('User State'),
'description' => t('The user state.'),
'type' => 'state',
);
return array(
'types' => $types,
'tokens' => $tokens,
);
That will enable, e.g., [user:state:big]
for use, and show the expected hierarchy in the token browser.
As an aside, you'll also need to populate the data for the state
type in hook_tokens()
.
For example:
function module_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
$token_service = \Drupal::token();
$replacements = [];
if ($type == 'user' && !empty($data['user'])) {
if ($state_tokens = $token_service->findWithPrefix($tokens, 'state')) {
$replacements += $token_service->generate(
'state',
$state_tokens,
['user' => $data['user']],
$options,
$bubbleable_metadata
);
}
}
return $replacements;
}
Also bear in mind that varying cache by individual user, which is happening here, can result in a lot of cache entries (depending on the number of users and how/where this token is used).
If you can find a solution which varies the content based on role, or even change the implementation so that it incorporates a render array with a lazy builder, you might see better cache performance.