アカウントページにユーザーのステータスを表示したい。使用しているテーマに次のコードを追加しました。機能しますが、ユーザーがオフラインで表示されることはありません。
どうして?コードの何が問題になっていますか?
<div class="bs-field-status">
{% if status == 'Online' %}
<i class="user-online fa fa-circle fa-lg"></i> Online
{% elseif status == 'Absent' %}
<i class="user-absent fa fa-circle fa-lg"></i> Absent
{% else %}
<i class="user-offline fa fa-circle fa-lg"></i> Offline
{% endif %}
</div>
<?php
/**
* @file
* Bootstrap sub-theme.
*
* Place your custom PHP code in this file.
*/
use Drupal\Core\Database\Database;
/**
* Implements hook_entity_presave().
*/
function bootstrap_subtheme_front_office_preprocess_user(&$variables) {
// get user object
$user = $variables['elements']['#user'];
//- The user has logged in at least once
if ($user->getLastLoginTime()) {
if (account_is_logged_in_less_then_thirty_minutes($user->id())) {
$status = 'Online';
}
else {
$status = 'Absent';
}
}
else {
$status = 'Offline';
}
$variables['status'] = $status;
}
/**
* @param $uid
*
* @return bool
*/
function account_is_logged_in_less_then_thirty_minutes($uid) {
$connection = Database::getConnection();
$query = $connection->select('sessions', 'sessions')
->fields('sessions', ['sid', 'uid', 'timestamp'])
->condition('sessions.uid', $uid, '=')
//- chef if the user was online in 30 minutes (60 * 30)
->condition('sessions.timestamp', \Drupal::time()
->getRequestTime() - (60 * 30), '>')
->execute();
//- Get result.
$results = $query->fetchAll(\PDO::FETCH_OBJ);
return (count($results) > 0) ? TRUE : FALSE;
}
まず、問題はここにあると思います。
_//- The user has logged in at least once
if ($user->getLastLoginTime()) {
if (account_is_logged_in_less_then_thirty_minutes($user->id())) {
$status = 'Online';
}
else {
$status = 'Absent';
}
}
else {
$status = 'Offline';
}
_
if ($user->getLastLoginTime()) {
は、ユーザーが一度ログインした後は常にTRUEになります。これにより、else
がヒットすることが防止されるため、「オフライン」が設定されることはありません。
「不在」と「オフライン」の時間の違いはわかりませんが、ステータスを何に設定するかを知るために、ここで別の計算を考えたいと思います。
これは次のように簡略化できます。
_function bootstrap_subtheme_front_office_preprocess_user(&$variables) {
// get user object
$user = $variables['elements']['#user'];
$last = $user->getLastAccessedTime();
$now = \Drupal::time()->getRequestTime();
switch ($last) {
case ($last > ($now - 900)) :
$variables['status'] = 'Online';
break;
case (($last < ($now - 900)) && $last > ($now - 1800)) :
$variables['status'] = 'Absent';
break;
default:
$variables['status'] = 'Offline';
break;
}
}
_
次に、小さい関数を分解して、何分前にアクティブであったかを評価します。上のスイッチでそれを使用します。
getLastAccessedTime()
は:
アカウントが最後にサイトにアクセスしたときのタイムスタンプ。
値0は、ユーザーがサイトにアクセスしたことがないことを意味します。
したがって、_db_select
_は必要ありません。
Drupalおよびユーザーのステータスに関する最終的な問題はキャッシュですが、ここで私が作業しているコードがあります。
if ($variables['accessTime'] > (intval(time()) - 800)) {
$variables['sessionState'] = 'active';
}
else {
$variables['sessionState'] = 'inactive';
}
次にTwigで次のようなことができます:
{% if sessionState == active %}
{% endif %}
または
{%
set activeClass = [
sessionState == 'active' ? 'Active' : 'Not Active'
]
%}
彼らの答えのプレストサウルスがすでに言ったように、ここで最大の問題はキャッシュです。プリプロセスフックで行われた内容は、次回Drupalのテーマキャッシュをフラッシュするまでキャッシュされます。マークアップの最大有効期間を減らすか、完全にajax化することにより、キャッシュが確実に破壊されるようにする必要があります。
作成した ユーザーオンラインステータス 。このモジュールには、ユーザーエンティティの新しい疑似フィールド、特定のユーザーのオンラインステータスをキャッシュされていないJSON応答として返すルート、その応答をチェックしてオンラインステータスを疑似フィールドに出力するJSが含まれています。
ただし、適切な説明、スクリーンショット、テストが必要です。
オプション: http://d8.localhost/admin/config/people/accounts/display に移動して、「オンラインステータス」フィールドの重みを調整します。
switch
スニペットのクレジットをKevin( answer )に。