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

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.

主站蜘蛛池模板: 孟津县| 关岭| 游戏| 沧源| 新营市| 陈巴尔虎旗| 时尚| 会东县| 财经| 从江县| 洪湖市| 长武县| 溆浦县| 同江市| 临夏市| 临高县| 时尚| 全州县| 华宁县| 康平县| 荣成市| 景泰县| 普兰县| 宝山区| 青海省| 汾西县| 莲花县| 延吉市| 岳西县| 西华县| 久治县| 洱源县| 沙洋县| 诏安县| 永昌县| 余姚市| 东城区| 庆阳市| 监利县| 大关县| 通道|