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

Using tokens

If you remember, the custom MailLogger we wrote had a $context array as an argument to its log() method. This contains some relevant information to the thing being logged--channel, uri, timestamp, user, and others. We could use this data in conjunction with the token API to include information about the user who was signed in at the moment the error happened and was logged-in in the email. This can be useful information.

We will need to do two simple things to achieve this. First, we will need to alter our MailLogger::log() method to get the user account that was signed in and pass it to the mailer in the $param array:

  /**
* {@inheritdoc}
*/
public function log($level, $message, array $context = array()) {
if ($level !== RfcLogLevel::ERROR) {
return;
}

/** @var AccountProxyInterface $account */
$account = $context['user'];
$to = $this->configFactory->get('system.site')->get('mail');
$langode = $this->configFactory->get('system.site')->get('langcode');
$variables = $this->parser->parseMessagePlaceholders($message, $context);
$markup = new FormattableMarkup($message, $variables);
\Drupal::service('plugin.manager.mail')->mail('hello_world', 'hello_world_log', $to, $langode, ['message' => $markup, 'user' => $account]);
}

An important thing to note here is that we are talking about the currently logged-in user, which means that it is not a fully loaded user, but a simple AccountProxyInterface, which is a more shallow object rather than the full entity--the user session basically. If you are ever dealing with this object and need the entire User entity, you'll need to load it by its ID. However, in our case, the user module's hook_tokens() implementation does that for us, as we will see in a moment.

Finally, we will need to alter our hook_mail() implementation to handle this user and add another string to our mail body and, of course, replace a token:

/**
* Implements hook_mail().
*/
function hello_world_mail($key, &$message, $params) {
switch ($key) {
case 'hello_world_log':
$message['from'] = \Drupal::config('system.site')->get('mail');
$message['subject'] = t('There is an error on your website');
$message['body'][] = $params['message'];
if (isset($params['user'])) {
$user_message = 'The user that was logged in: [current-user:name]';
$message['body'][] = \Drupal::token()->replace($user_message, ['current-user' => $params['user']]);
}

break;
}
}

As you can see, if we receive the user parameter, we will add a new paragraph to our email. This is a simple string that informs us about the user who was logged in. However, in doing so, we use the token service (statically) to replace that string with the token value. The replace() method of the service takes a string and optionally an array of data objects keyed by the type (group) of the tokens they should be used for.

The choice of a token and type in this case is important. The User module defines the user and current-user types. The difference between the two types, if you check inside user_tokens(), is that the latter simply delegates to the former after it loads a full user entity. We could, alternatively, have done that ourselves and then passed the user type, but why should we? If somebody has done that for us already, we should not have to do it again.

So, that's it. Now, the email message will get an extra line that contains the dynamically generated username of the currently logged-in user at the time the error happened. Under the hood, the token service scans the string, extracts the token, and calls all hook_tokens() implementations. The User module is the one that can return the replacement for this token based on the User object it receives.

主站蜘蛛池模板: 茶陵县| 沁阳市| 哈密市| 白朗县| 安新县| 荆门市| 从化市| 巴中市| 凤庆县| 基隆市| 新营市| 甘泉县| 汉阴县| 甘德县| 乌鲁木齐县| 泰州市| 黑水县| 安丘市| 长春市| 马公市| 乡城县| 龙江县| 台南县| 桐柏县| 曲沃县| 嘉鱼县| 读书| 米易县| 西吉县| 苍南县| 定陶县| 梅河口市| 西乡县| 阜城县| 平顶山市| 台南县| 广灵县| 平遥县| 菏泽市| 随州市| 乐陵市|