官术网_书友最值得收藏!

Defining new tokens

We just saw how we can programmatically use existing tokens inside our strings and get them replaced with minimal effort. All we need is the token service and the data object that can be used to replace the token. Keep in mind that there are tokens which don't even require any data objects due to their global nature. The hook_tokens() implementation will take care of that--let's see how.

In the preceding chapter, we created functionalities for a dynamic "Hello World" message, which are either calculated or loaded from a configuration object. How about we expose the message to a token? This would make its usage more flexible because our string becomes exposed to the entire token system.

As mentioned, we will start with the hook_token_info() implementation:

/**
* Implements hook_token_info().
*/
function hello_world_token_info() {
$type = [
'name' => t('Hello World'),
'description' => t('Tokens related to the Hello World module.'),
];

$tokens['salutation'] = [
'name' => t('Salutation'),
'description' => t('The Hello World salutation value.'),
];

return [
'types' => ['hello_world' => $type],
'tokens' => ['hello_world' => $tokens],
];
}

In here, we will need to define two things--the types and the tokens. In our case, we are defining one of each. The type is hello_world and comes with a human-readable name and description in case it needs to be rendered somewhere in the UI. The token is salutation and belongs to the hello_world type. It also gets a name and description. At the end, we return an array that contains both.

What follows is the hook_tokens() implementation in which we handle the replacement of our token:

/**
* Implements hook_tokens().
*/
function hello_world_tokens($type, $tokens, array $data, array $options, \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata) {
$replacements = [];
if ($type == 'hello_world') {
foreach ($tokens as $name => $original) {
switch ($name) {
case 'salutation':
$replacements[$original] = \Drupal::service('hello_world.salutation')->getSalutation();
$config = \Drupal::config('hello_world.custom_salutation');
$bubbleable_metadata->addCacheableDependency($config);
break;

}
}
}

return $replacements;
}

There is a bit more going on here, but I'll explain everything. This hook gets fired for each type located inside a string (after all have been scanned and grouped accordingly), and the $type is the first parameter. Inside $tokens, we get an array of tokens located in that string, which belong to the $type. The $data array contains the objects needed to replace the tokens, keyed by the type. This array can be empty (as it will be in our case).

Inside the function, we loop through each token of this group and try to replace it. We only know of one, and we use our HelloWorldSalutation service to determine the replacement string.

Finally, the function needs to return an array of all replacements found (which can be multiple if multiple tokens of the same type are found inside a string).

The bubbleable_metadata parameter is a special cache metadata object that describes this token in the cache system. It is needed because tokens get cached, so if any dependent object changes, the cache needs to be invalidated for this token as well. By default, all objects inside the $data array are read and included in this object. However, in our case, it is empty, yet we still depend on a configuration object that can change--the one that stores the overridden salutation message. So, we will need to add a dependency on that configuration object even if the actual value for the salutation we compute uses the same HelloWorldSalutation service we used before. So, we have a simple example here, but with a complex twist.

That's all there is to defining our token. It can now also be used inside strings and replaced using the Token service. Something like this:

$final_string = \Drupal::token()->replace('The salutation text is: [hello_world:salutation]');

As you can see, we pass no other parameters. If our token were dependent on an entity object, for example, we would have passed it in the second parameter array and would have made use of it inside hook_tokens() to compute the replacement.

主站蜘蛛池模板: 双柏县| 平罗县| 册亨县| 芦溪县| 襄樊市| 广丰县| 洞口县| 永城市| 许昌市| 邢台市| 壶关县| 太原市| 张家川| 韩城市| 勐海县| 施秉县| 宜昌市| 宜城市| 和龙市| 新竹县| 江北区| 朝阳县| 县级市| 廊坊市| 法库县| 兴仁县| 辽阳市| 阳谷县| 英超| 枣阳市| 普定县| 维西| 突泉县| 含山县| 德阳市| 秦安县| 临汾市| 安阳县| 永兴县| 洪洞县| 任丘市|