Show if a user is online, idle, or offline on their account page?












2















I want to display the status of the user on the account page. I added the following code in the theme I am using. It works, but users are never displayed offline.



Why? What is wrong in the code?



user.html.twig



<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>


bootstrap_subtheme_front_office.theme



<?php
/**
* @file
* Bootstrap sub-theme.
*
* Place your custom PHP code in this file.
*/

use DrupalCoreDatabaseDatabase;

/**
* 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;
}









share|improve this question

























  • I think that the biggest issue here is cache. If you need some realtime info a preprocess hook shouldn't be the way to go. Instead I'd recommend to expose an explicitly uncached custom route that takes a uid as argumemt, and then returns a JSON response built from a callback that holds your code. And finally add some JS to your site that requests that route and places the outcome somewhere in your markup.

    – leymannx
    Dec 13 '18 at 20:46











  • @leymannx Thank you. I am not looking for a specific status. If there is a shift of 3 minutes it is OK

    – user91071
    Dec 13 '18 at 20:55






  • 1





    What's been done in a preprocess hook normally is cached until you flush the Drupal cache for the next time if you don't implement some kind of a cache busting logic.

    – leymannx
    Dec 13 '18 at 20:59








  • 2





    If you don't do it the AJAX way you'll need to add something like $variables['#cache']['max-age'] = strtotime('+3 minutes'); in the preprocess hook, switch off the page cache module, and make sure any reverse proxy sitting in front of the site is configured to react. You might find the AJAX route to be less of a bother in the end

    – Clive
    Dec 13 '18 at 22:33
















2















I want to display the status of the user on the account page. I added the following code in the theme I am using. It works, but users are never displayed offline.



Why? What is wrong in the code?



user.html.twig



<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>


bootstrap_subtheme_front_office.theme



<?php
/**
* @file
* Bootstrap sub-theme.
*
* Place your custom PHP code in this file.
*/

use DrupalCoreDatabaseDatabase;

/**
* 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;
}









share|improve this question

























  • I think that the biggest issue here is cache. If you need some realtime info a preprocess hook shouldn't be the way to go. Instead I'd recommend to expose an explicitly uncached custom route that takes a uid as argumemt, and then returns a JSON response built from a callback that holds your code. And finally add some JS to your site that requests that route and places the outcome somewhere in your markup.

    – leymannx
    Dec 13 '18 at 20:46











  • @leymannx Thank you. I am not looking for a specific status. If there is a shift of 3 minutes it is OK

    – user91071
    Dec 13 '18 at 20:55






  • 1





    What's been done in a preprocess hook normally is cached until you flush the Drupal cache for the next time if you don't implement some kind of a cache busting logic.

    – leymannx
    Dec 13 '18 at 20:59








  • 2





    If you don't do it the AJAX way you'll need to add something like $variables['#cache']['max-age'] = strtotime('+3 minutes'); in the preprocess hook, switch off the page cache module, and make sure any reverse proxy sitting in front of the site is configured to react. You might find the AJAX route to be less of a bother in the end

    – Clive
    Dec 13 '18 at 22:33














2












2








2


3






I want to display the status of the user on the account page. I added the following code in the theme I am using. It works, but users are never displayed offline.



Why? What is wrong in the code?



user.html.twig



<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>


bootstrap_subtheme_front_office.theme



<?php
/**
* @file
* Bootstrap sub-theme.
*
* Place your custom PHP code in this file.
*/

use DrupalCoreDatabaseDatabase;

/**
* 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;
}









share|improve this question
















I want to display the status of the user on the account page. I added the following code in the theme I am using. It works, but users are never displayed offline.



Why? What is wrong in the code?



user.html.twig



<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>


bootstrap_subtheme_front_office.theme



<?php
/**
* @file
* Bootstrap sub-theme.
*
* Place your custom PHP code in this file.
*/

use DrupalCoreDatabaseDatabase;

/**
* 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;
}






8 theming users






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 7 hours ago









kiamlaluno

79.7k9130248




79.7k9130248










asked Dec 13 '18 at 19:27







user91071




















  • I think that the biggest issue here is cache. If you need some realtime info a preprocess hook shouldn't be the way to go. Instead I'd recommend to expose an explicitly uncached custom route that takes a uid as argumemt, and then returns a JSON response built from a callback that holds your code. And finally add some JS to your site that requests that route and places the outcome somewhere in your markup.

    – leymannx
    Dec 13 '18 at 20:46











  • @leymannx Thank you. I am not looking for a specific status. If there is a shift of 3 minutes it is OK

    – user91071
    Dec 13 '18 at 20:55






  • 1





    What's been done in a preprocess hook normally is cached until you flush the Drupal cache for the next time if you don't implement some kind of a cache busting logic.

    – leymannx
    Dec 13 '18 at 20:59








  • 2





    If you don't do it the AJAX way you'll need to add something like $variables['#cache']['max-age'] = strtotime('+3 minutes'); in the preprocess hook, switch off the page cache module, and make sure any reverse proxy sitting in front of the site is configured to react. You might find the AJAX route to be less of a bother in the end

    – Clive
    Dec 13 '18 at 22:33



















  • I think that the biggest issue here is cache. If you need some realtime info a preprocess hook shouldn't be the way to go. Instead I'd recommend to expose an explicitly uncached custom route that takes a uid as argumemt, and then returns a JSON response built from a callback that holds your code. And finally add some JS to your site that requests that route and places the outcome somewhere in your markup.

    – leymannx
    Dec 13 '18 at 20:46











  • @leymannx Thank you. I am not looking for a specific status. If there is a shift of 3 minutes it is OK

    – user91071
    Dec 13 '18 at 20:55






  • 1





    What's been done in a preprocess hook normally is cached until you flush the Drupal cache for the next time if you don't implement some kind of a cache busting logic.

    – leymannx
    Dec 13 '18 at 20:59








  • 2





    If you don't do it the AJAX way you'll need to add something like $variables['#cache']['max-age'] = strtotime('+3 minutes'); in the preprocess hook, switch off the page cache module, and make sure any reverse proxy sitting in front of the site is configured to react. You might find the AJAX route to be less of a bother in the end

    – Clive
    Dec 13 '18 at 22:33

















I think that the biggest issue here is cache. If you need some realtime info a preprocess hook shouldn't be the way to go. Instead I'd recommend to expose an explicitly uncached custom route that takes a uid as argumemt, and then returns a JSON response built from a callback that holds your code. And finally add some JS to your site that requests that route and places the outcome somewhere in your markup.

– leymannx
Dec 13 '18 at 20:46





I think that the biggest issue here is cache. If you need some realtime info a preprocess hook shouldn't be the way to go. Instead I'd recommend to expose an explicitly uncached custom route that takes a uid as argumemt, and then returns a JSON response built from a callback that holds your code. And finally add some JS to your site that requests that route and places the outcome somewhere in your markup.

– leymannx
Dec 13 '18 at 20:46













@leymannx Thank you. I am not looking for a specific status. If there is a shift of 3 minutes it is OK

– user91071
Dec 13 '18 at 20:55





@leymannx Thank you. I am not looking for a specific status. If there is a shift of 3 minutes it is OK

– user91071
Dec 13 '18 at 20:55




1




1





What's been done in a preprocess hook normally is cached until you flush the Drupal cache for the next time if you don't implement some kind of a cache busting logic.

– leymannx
Dec 13 '18 at 20:59







What's been done in a preprocess hook normally is cached until you flush the Drupal cache for the next time if you don't implement some kind of a cache busting logic.

– leymannx
Dec 13 '18 at 20:59






2




2





If you don't do it the AJAX way you'll need to add something like $variables['#cache']['max-age'] = strtotime('+3 minutes'); in the preprocess hook, switch off the page cache module, and make sure any reverse proxy sitting in front of the site is configured to react. You might find the AJAX route to be less of a bother in the end

– Clive
Dec 13 '18 at 22:33





If you don't do it the AJAX way you'll need to add something like $variables['#cache']['max-age'] = strtotime('+3 minutes'); in the preprocess hook, switch off the page cache module, and make sure any reverse proxy sitting in front of the site is configured to react. You might find the AJAX route to be less of a bother in the end

– Clive
Dec 13 '18 at 22:33










3 Answers
3






active

oldest

votes


















1














The ultimate problem with Drupal and user status is cache, but here is some code I am working with.



if ($variables['accessTime'] > (intval(time()) - 800)) {
$variables['sessionState'] = 'active';
}
else {
$variables['sessionState'] = 'inactive';
}


Then in Twig you can do stuff like:



{% if sessionState == active %}

{% endif %}


or



{%
set activeClass = [
sessionState == 'active' ? 'Active' : 'Not Active'
]
%}





share|improve this answer


























  • Why do you need to target the page title? I don't get that? This deals with showing the users status on their account page, basically users looking at other user profiles. They're using the proper preprocess function, the code itself is not accurate.

    – Kevin
    Dec 13 '18 at 20:10











  • Maybe I misread the question let me update my answer. Doesn't need to say so much anyway.

    – Prestosaurus
    Dec 13 '18 at 20:11











  • @Prestosaurus The status of the user will be displayed at several places on the site. Conversation, comment, product, store, node, group, ... wherever his name appears. I want the code to be user with the TWIG code of my question

    – user91071
    Dec 13 '18 at 20:12











  • I think you're going to have a harder time doing that sitewide, because your cache times will decrease dramatically just to ensure you're showing an accurate status. I thought you just wanted this on their profile.

    – Kevin
    Dec 13 '18 at 20:13








  • 1





    @mathmath Kind of where my mind was going. Following this question, and please see: drupal.stackexchange.com/questions/271119/… as well as drupal.stackexchange.com/questions/273350/…

    – Prestosaurus
    Dec 13 '18 at 20:15



















1














I guess the problem lies here, for starters:



//- 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';
}


The if ($user->getLastLoginTime()) { will be TRUE always, after the user has logged in once. This will prevent the else from ever being hit, thus, 'Offline' never gets set.



I don't know what the difference is for you in terms of time between "Absent" or "Offline", but it sounds like you'd want to figure another calculation here to know what to set status to.



This can be simplified to:



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;
}
}


Then break down smaller functions to evaulate the time against how many minutes ago they were active... use it in the switch above.



getLastAccessedTime() does:




The timestamp when the account last accessed the site.



A value of 0 means the user has never accessed the site.




So you don’t need a db_select.






share|improve this answer


























  • I am trying to put the user absent after 15 minutes of inactivity and offline after 30 minutes of inactivity (or when disconnected)

    – user91071
    Dec 13 '18 at 19:40













  • With the access value can we do 3 status? from 0 to 15 minutes "online", from 15 to 30 minustes "absent" (means unavailable), 30 minutes superior "offline".

    – user91071
    Dec 13 '18 at 19:52











  • The access value is the timestamp when the account last accessed the site according to the documentation. I don't know how frequently it is written to.

    – Kevin
    Dec 13 '18 at 19:53













  • So fill in the blanks, this is just boilerplate code.

    – Kevin
    Dec 13 '18 at 19:57











  • This answer here proves that its the method you want, not the last login time: drupal.stackexchange.com/a/21873/57

    – Kevin
    Dec 13 '18 at 19:59



















0














As Prestosaurus in their answer already said, the biggest issue here is cache. What's been done in preprocess hooks will be cached until you flush Drupal's theme cache the next time. You'll need to ensure the cache gets busted by reducing the max age of your piece of markup or by ajaxifying it completely.





I just created User Online Status. This module contains a new pseudo field for user entities, a route to return a given user's online status as a non-cached JSON response, and some JS that checks that response and prints the online status into the pseudo field.



It still needs proper description, screenshots and tests, though.




  1. Download and enable the module.

  2. Go to http://d8.localhost/user/1 to see the online status of user 1.


Optionally: Go to http://d8.localhost/admin/config/people/accounts/display to adjust the "Online Status" field's weight.





Credits for the switch snippet to Kevin (answer).






share|improve this answer


























  • I'll add a theme tomorrow, so everybody can create their own template to add a label or customize the markup.

    – leymannx
    Dec 13 '18 at 22:58











  • This is great news, it is late I will test it tomorrow. It is obvious that drupal 8 does not include this feature in the kernel. Yet drupal has always managed users. Does your module manage the idle status ? Thank you

    – user91071
    Dec 13 '18 at 23:06






  • 1





    Maybe you should replace case ($last > ($now - 900)): by case ($last >= ($now - 900)): otherwise there will be a white at 900 seconds

    – user91071
    Dec 13 '18 at 23:11











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "220"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdrupal.stackexchange.com%2fquestions%2f273973%2fshow-if-a-user-is-online-idle-or-offline-on-their-account-page%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown
























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














The ultimate problem with Drupal and user status is cache, but here is some code I am working with.



if ($variables['accessTime'] > (intval(time()) - 800)) {
$variables['sessionState'] = 'active';
}
else {
$variables['sessionState'] = 'inactive';
}


Then in Twig you can do stuff like:



{% if sessionState == active %}

{% endif %}


or



{%
set activeClass = [
sessionState == 'active' ? 'Active' : 'Not Active'
]
%}





share|improve this answer


























  • Why do you need to target the page title? I don't get that? This deals with showing the users status on their account page, basically users looking at other user profiles. They're using the proper preprocess function, the code itself is not accurate.

    – Kevin
    Dec 13 '18 at 20:10











  • Maybe I misread the question let me update my answer. Doesn't need to say so much anyway.

    – Prestosaurus
    Dec 13 '18 at 20:11











  • @Prestosaurus The status of the user will be displayed at several places on the site. Conversation, comment, product, store, node, group, ... wherever his name appears. I want the code to be user with the TWIG code of my question

    – user91071
    Dec 13 '18 at 20:12











  • I think you're going to have a harder time doing that sitewide, because your cache times will decrease dramatically just to ensure you're showing an accurate status. I thought you just wanted this on their profile.

    – Kevin
    Dec 13 '18 at 20:13








  • 1





    @mathmath Kind of where my mind was going. Following this question, and please see: drupal.stackexchange.com/questions/271119/… as well as drupal.stackexchange.com/questions/273350/…

    – Prestosaurus
    Dec 13 '18 at 20:15
















1














The ultimate problem with Drupal and user status is cache, but here is some code I am working with.



if ($variables['accessTime'] > (intval(time()) - 800)) {
$variables['sessionState'] = 'active';
}
else {
$variables['sessionState'] = 'inactive';
}


Then in Twig you can do stuff like:



{% if sessionState == active %}

{% endif %}


or



{%
set activeClass = [
sessionState == 'active' ? 'Active' : 'Not Active'
]
%}





share|improve this answer


























  • Why do you need to target the page title? I don't get that? This deals with showing the users status on their account page, basically users looking at other user profiles. They're using the proper preprocess function, the code itself is not accurate.

    – Kevin
    Dec 13 '18 at 20:10











  • Maybe I misread the question let me update my answer. Doesn't need to say so much anyway.

    – Prestosaurus
    Dec 13 '18 at 20:11











  • @Prestosaurus The status of the user will be displayed at several places on the site. Conversation, comment, product, store, node, group, ... wherever his name appears. I want the code to be user with the TWIG code of my question

    – user91071
    Dec 13 '18 at 20:12











  • I think you're going to have a harder time doing that sitewide, because your cache times will decrease dramatically just to ensure you're showing an accurate status. I thought you just wanted this on their profile.

    – Kevin
    Dec 13 '18 at 20:13








  • 1





    @mathmath Kind of where my mind was going. Following this question, and please see: drupal.stackexchange.com/questions/271119/… as well as drupal.stackexchange.com/questions/273350/…

    – Prestosaurus
    Dec 13 '18 at 20:15














1












1








1







The ultimate problem with Drupal and user status is cache, but here is some code I am working with.



if ($variables['accessTime'] > (intval(time()) - 800)) {
$variables['sessionState'] = 'active';
}
else {
$variables['sessionState'] = 'inactive';
}


Then in Twig you can do stuff like:



{% if sessionState == active %}

{% endif %}


or



{%
set activeClass = [
sessionState == 'active' ? 'Active' : 'Not Active'
]
%}





share|improve this answer















The ultimate problem with Drupal and user status is cache, but here is some code I am working with.



if ($variables['accessTime'] > (intval(time()) - 800)) {
$variables['sessionState'] = 'active';
}
else {
$variables['sessionState'] = 'inactive';
}


Then in Twig you can do stuff like:



{% if sessionState == active %}

{% endif %}


or



{%
set activeClass = [
sessionState == 'active' ? 'Active' : 'Not Active'
]
%}






share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 13 '18 at 20:12

























answered Dec 13 '18 at 20:08









PrestosaurusPrestosaurus

530212




530212













  • Why do you need to target the page title? I don't get that? This deals with showing the users status on their account page, basically users looking at other user profiles. They're using the proper preprocess function, the code itself is not accurate.

    – Kevin
    Dec 13 '18 at 20:10











  • Maybe I misread the question let me update my answer. Doesn't need to say so much anyway.

    – Prestosaurus
    Dec 13 '18 at 20:11











  • @Prestosaurus The status of the user will be displayed at several places on the site. Conversation, comment, product, store, node, group, ... wherever his name appears. I want the code to be user with the TWIG code of my question

    – user91071
    Dec 13 '18 at 20:12











  • I think you're going to have a harder time doing that sitewide, because your cache times will decrease dramatically just to ensure you're showing an accurate status. I thought you just wanted this on their profile.

    – Kevin
    Dec 13 '18 at 20:13








  • 1





    @mathmath Kind of where my mind was going. Following this question, and please see: drupal.stackexchange.com/questions/271119/… as well as drupal.stackexchange.com/questions/273350/…

    – Prestosaurus
    Dec 13 '18 at 20:15



















  • Why do you need to target the page title? I don't get that? This deals with showing the users status on their account page, basically users looking at other user profiles. They're using the proper preprocess function, the code itself is not accurate.

    – Kevin
    Dec 13 '18 at 20:10











  • Maybe I misread the question let me update my answer. Doesn't need to say so much anyway.

    – Prestosaurus
    Dec 13 '18 at 20:11











  • @Prestosaurus The status of the user will be displayed at several places on the site. Conversation, comment, product, store, node, group, ... wherever his name appears. I want the code to be user with the TWIG code of my question

    – user91071
    Dec 13 '18 at 20:12











  • I think you're going to have a harder time doing that sitewide, because your cache times will decrease dramatically just to ensure you're showing an accurate status. I thought you just wanted this on their profile.

    – Kevin
    Dec 13 '18 at 20:13








  • 1





    @mathmath Kind of where my mind was going. Following this question, and please see: drupal.stackexchange.com/questions/271119/… as well as drupal.stackexchange.com/questions/273350/…

    – Prestosaurus
    Dec 13 '18 at 20:15

















Why do you need to target the page title? I don't get that? This deals with showing the users status on their account page, basically users looking at other user profiles. They're using the proper preprocess function, the code itself is not accurate.

– Kevin
Dec 13 '18 at 20:10





Why do you need to target the page title? I don't get that? This deals with showing the users status on their account page, basically users looking at other user profiles. They're using the proper preprocess function, the code itself is not accurate.

– Kevin
Dec 13 '18 at 20:10













Maybe I misread the question let me update my answer. Doesn't need to say so much anyway.

– Prestosaurus
Dec 13 '18 at 20:11





Maybe I misread the question let me update my answer. Doesn't need to say so much anyway.

– Prestosaurus
Dec 13 '18 at 20:11













@Prestosaurus The status of the user will be displayed at several places on the site. Conversation, comment, product, store, node, group, ... wherever his name appears. I want the code to be user with the TWIG code of my question

– user91071
Dec 13 '18 at 20:12





@Prestosaurus The status of the user will be displayed at several places on the site. Conversation, comment, product, store, node, group, ... wherever his name appears. I want the code to be user with the TWIG code of my question

– user91071
Dec 13 '18 at 20:12













I think you're going to have a harder time doing that sitewide, because your cache times will decrease dramatically just to ensure you're showing an accurate status. I thought you just wanted this on their profile.

– Kevin
Dec 13 '18 at 20:13







I think you're going to have a harder time doing that sitewide, because your cache times will decrease dramatically just to ensure you're showing an accurate status. I thought you just wanted this on their profile.

– Kevin
Dec 13 '18 at 20:13






1




1





@mathmath Kind of where my mind was going. Following this question, and please see: drupal.stackexchange.com/questions/271119/… as well as drupal.stackexchange.com/questions/273350/…

– Prestosaurus
Dec 13 '18 at 20:15





@mathmath Kind of where my mind was going. Following this question, and please see: drupal.stackexchange.com/questions/271119/… as well as drupal.stackexchange.com/questions/273350/…

– Prestosaurus
Dec 13 '18 at 20:15













1














I guess the problem lies here, for starters:



//- 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';
}


The if ($user->getLastLoginTime()) { will be TRUE always, after the user has logged in once. This will prevent the else from ever being hit, thus, 'Offline' never gets set.



I don't know what the difference is for you in terms of time between "Absent" or "Offline", but it sounds like you'd want to figure another calculation here to know what to set status to.



This can be simplified to:



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;
}
}


Then break down smaller functions to evaulate the time against how many minutes ago they were active... use it in the switch above.



getLastAccessedTime() does:




The timestamp when the account last accessed the site.



A value of 0 means the user has never accessed the site.




So you don’t need a db_select.






share|improve this answer


























  • I am trying to put the user absent after 15 minutes of inactivity and offline after 30 minutes of inactivity (or when disconnected)

    – user91071
    Dec 13 '18 at 19:40













  • With the access value can we do 3 status? from 0 to 15 minutes "online", from 15 to 30 minustes "absent" (means unavailable), 30 minutes superior "offline".

    – user91071
    Dec 13 '18 at 19:52











  • The access value is the timestamp when the account last accessed the site according to the documentation. I don't know how frequently it is written to.

    – Kevin
    Dec 13 '18 at 19:53













  • So fill in the blanks, this is just boilerplate code.

    – Kevin
    Dec 13 '18 at 19:57











  • This answer here proves that its the method you want, not the last login time: drupal.stackexchange.com/a/21873/57

    – Kevin
    Dec 13 '18 at 19:59
















1














I guess the problem lies here, for starters:



//- 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';
}


The if ($user->getLastLoginTime()) { will be TRUE always, after the user has logged in once. This will prevent the else from ever being hit, thus, 'Offline' never gets set.



I don't know what the difference is for you in terms of time between "Absent" or "Offline", but it sounds like you'd want to figure another calculation here to know what to set status to.



This can be simplified to:



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;
}
}


Then break down smaller functions to evaulate the time against how many minutes ago they were active... use it in the switch above.



getLastAccessedTime() does:




The timestamp when the account last accessed the site.



A value of 0 means the user has never accessed the site.




So you don’t need a db_select.






share|improve this answer


























  • I am trying to put the user absent after 15 minutes of inactivity and offline after 30 minutes of inactivity (or when disconnected)

    – user91071
    Dec 13 '18 at 19:40













  • With the access value can we do 3 status? from 0 to 15 minutes "online", from 15 to 30 minustes "absent" (means unavailable), 30 minutes superior "offline".

    – user91071
    Dec 13 '18 at 19:52











  • The access value is the timestamp when the account last accessed the site according to the documentation. I don't know how frequently it is written to.

    – Kevin
    Dec 13 '18 at 19:53













  • So fill in the blanks, this is just boilerplate code.

    – Kevin
    Dec 13 '18 at 19:57











  • This answer here proves that its the method you want, not the last login time: drupal.stackexchange.com/a/21873/57

    – Kevin
    Dec 13 '18 at 19:59














1












1








1







I guess the problem lies here, for starters:



//- 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';
}


The if ($user->getLastLoginTime()) { will be TRUE always, after the user has logged in once. This will prevent the else from ever being hit, thus, 'Offline' never gets set.



I don't know what the difference is for you in terms of time between "Absent" or "Offline", but it sounds like you'd want to figure another calculation here to know what to set status to.



This can be simplified to:



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;
}
}


Then break down smaller functions to evaulate the time against how many minutes ago they were active... use it in the switch above.



getLastAccessedTime() does:




The timestamp when the account last accessed the site.



A value of 0 means the user has never accessed the site.




So you don’t need a db_select.






share|improve this answer















I guess the problem lies here, for starters:



//- 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';
}


The if ($user->getLastLoginTime()) { will be TRUE always, after the user has logged in once. This will prevent the else from ever being hit, thus, 'Offline' never gets set.



I don't know what the difference is for you in terms of time between "Absent" or "Offline", but it sounds like you'd want to figure another calculation here to know what to set status to.



This can be simplified to:



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;
}
}


Then break down smaller functions to evaulate the time against how many minutes ago they were active... use it in the switch above.



getLastAccessedTime() does:




The timestamp when the account last accessed the site.



A value of 0 means the user has never accessed the site.




So you don’t need a db_select.







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 13 '18 at 22:12

























answered Dec 13 '18 at 19:34









KevinKevin

17.7k848108




17.7k848108













  • I am trying to put the user absent after 15 minutes of inactivity and offline after 30 minutes of inactivity (or when disconnected)

    – user91071
    Dec 13 '18 at 19:40













  • With the access value can we do 3 status? from 0 to 15 minutes "online", from 15 to 30 minustes "absent" (means unavailable), 30 minutes superior "offline".

    – user91071
    Dec 13 '18 at 19:52











  • The access value is the timestamp when the account last accessed the site according to the documentation. I don't know how frequently it is written to.

    – Kevin
    Dec 13 '18 at 19:53













  • So fill in the blanks, this is just boilerplate code.

    – Kevin
    Dec 13 '18 at 19:57











  • This answer here proves that its the method you want, not the last login time: drupal.stackexchange.com/a/21873/57

    – Kevin
    Dec 13 '18 at 19:59



















  • I am trying to put the user absent after 15 minutes of inactivity and offline after 30 minutes of inactivity (or when disconnected)

    – user91071
    Dec 13 '18 at 19:40













  • With the access value can we do 3 status? from 0 to 15 minutes "online", from 15 to 30 minustes "absent" (means unavailable), 30 minutes superior "offline".

    – user91071
    Dec 13 '18 at 19:52











  • The access value is the timestamp when the account last accessed the site according to the documentation. I don't know how frequently it is written to.

    – Kevin
    Dec 13 '18 at 19:53













  • So fill in the blanks, this is just boilerplate code.

    – Kevin
    Dec 13 '18 at 19:57











  • This answer here proves that its the method you want, not the last login time: drupal.stackexchange.com/a/21873/57

    – Kevin
    Dec 13 '18 at 19:59

















I am trying to put the user absent after 15 minutes of inactivity and offline after 30 minutes of inactivity (or when disconnected)

– user91071
Dec 13 '18 at 19:40







I am trying to put the user absent after 15 minutes of inactivity and offline after 30 minutes of inactivity (or when disconnected)

– user91071
Dec 13 '18 at 19:40















With the access value can we do 3 status? from 0 to 15 minutes "online", from 15 to 30 minustes "absent" (means unavailable), 30 minutes superior "offline".

– user91071
Dec 13 '18 at 19:52





With the access value can we do 3 status? from 0 to 15 minutes "online", from 15 to 30 minustes "absent" (means unavailable), 30 minutes superior "offline".

– user91071
Dec 13 '18 at 19:52













The access value is the timestamp when the account last accessed the site according to the documentation. I don't know how frequently it is written to.

– Kevin
Dec 13 '18 at 19:53







The access value is the timestamp when the account last accessed the site according to the documentation. I don't know how frequently it is written to.

– Kevin
Dec 13 '18 at 19:53















So fill in the blanks, this is just boilerplate code.

– Kevin
Dec 13 '18 at 19:57





So fill in the blanks, this is just boilerplate code.

– Kevin
Dec 13 '18 at 19:57













This answer here proves that its the method you want, not the last login time: drupal.stackexchange.com/a/21873/57

– Kevin
Dec 13 '18 at 19:59





This answer here proves that its the method you want, not the last login time: drupal.stackexchange.com/a/21873/57

– Kevin
Dec 13 '18 at 19:59











0














As Prestosaurus in their answer already said, the biggest issue here is cache. What's been done in preprocess hooks will be cached until you flush Drupal's theme cache the next time. You'll need to ensure the cache gets busted by reducing the max age of your piece of markup or by ajaxifying it completely.





I just created User Online Status. This module contains a new pseudo field for user entities, a route to return a given user's online status as a non-cached JSON response, and some JS that checks that response and prints the online status into the pseudo field.



It still needs proper description, screenshots and tests, though.




  1. Download and enable the module.

  2. Go to http://d8.localhost/user/1 to see the online status of user 1.


Optionally: Go to http://d8.localhost/admin/config/people/accounts/display to adjust the "Online Status" field's weight.





Credits for the switch snippet to Kevin (answer).






share|improve this answer


























  • I'll add a theme tomorrow, so everybody can create their own template to add a label or customize the markup.

    – leymannx
    Dec 13 '18 at 22:58











  • This is great news, it is late I will test it tomorrow. It is obvious that drupal 8 does not include this feature in the kernel. Yet drupal has always managed users. Does your module manage the idle status ? Thank you

    – user91071
    Dec 13 '18 at 23:06






  • 1





    Maybe you should replace case ($last > ($now - 900)): by case ($last >= ($now - 900)): otherwise there will be a white at 900 seconds

    – user91071
    Dec 13 '18 at 23:11
















0














As Prestosaurus in their answer already said, the biggest issue here is cache. What's been done in preprocess hooks will be cached until you flush Drupal's theme cache the next time. You'll need to ensure the cache gets busted by reducing the max age of your piece of markup or by ajaxifying it completely.





I just created User Online Status. This module contains a new pseudo field for user entities, a route to return a given user's online status as a non-cached JSON response, and some JS that checks that response and prints the online status into the pseudo field.



It still needs proper description, screenshots and tests, though.




  1. Download and enable the module.

  2. Go to http://d8.localhost/user/1 to see the online status of user 1.


Optionally: Go to http://d8.localhost/admin/config/people/accounts/display to adjust the "Online Status" field's weight.





Credits for the switch snippet to Kevin (answer).






share|improve this answer


























  • I'll add a theme tomorrow, so everybody can create their own template to add a label or customize the markup.

    – leymannx
    Dec 13 '18 at 22:58











  • This is great news, it is late I will test it tomorrow. It is obvious that drupal 8 does not include this feature in the kernel. Yet drupal has always managed users. Does your module manage the idle status ? Thank you

    – user91071
    Dec 13 '18 at 23:06






  • 1





    Maybe you should replace case ($last > ($now - 900)): by case ($last >= ($now - 900)): otherwise there will be a white at 900 seconds

    – user91071
    Dec 13 '18 at 23:11














0












0








0







As Prestosaurus in their answer already said, the biggest issue here is cache. What's been done in preprocess hooks will be cached until you flush Drupal's theme cache the next time. You'll need to ensure the cache gets busted by reducing the max age of your piece of markup or by ajaxifying it completely.





I just created User Online Status. This module contains a new pseudo field for user entities, a route to return a given user's online status as a non-cached JSON response, and some JS that checks that response and prints the online status into the pseudo field.



It still needs proper description, screenshots and tests, though.




  1. Download and enable the module.

  2. Go to http://d8.localhost/user/1 to see the online status of user 1.


Optionally: Go to http://d8.localhost/admin/config/people/accounts/display to adjust the "Online Status" field's weight.





Credits for the switch snippet to Kevin (answer).






share|improve this answer















As Prestosaurus in their answer already said, the biggest issue here is cache. What's been done in preprocess hooks will be cached until you flush Drupal's theme cache the next time. You'll need to ensure the cache gets busted by reducing the max age of your piece of markup or by ajaxifying it completely.





I just created User Online Status. This module contains a new pseudo field for user entities, a route to return a given user's online status as a non-cached JSON response, and some JS that checks that response and prints the online status into the pseudo field.



It still needs proper description, screenshots and tests, though.




  1. Download and enable the module.

  2. Go to http://d8.localhost/user/1 to see the online status of user 1.


Optionally: Go to http://d8.localhost/admin/config/people/accounts/display to adjust the "Online Status" field's weight.





Credits for the switch snippet to Kevin (answer).







share|improve this answer














share|improve this answer



share|improve this answer








edited 5 hours ago

























answered Dec 13 '18 at 22:54









leymannxleymannx

6,92952659




6,92952659













  • I'll add a theme tomorrow, so everybody can create their own template to add a label or customize the markup.

    – leymannx
    Dec 13 '18 at 22:58











  • This is great news, it is late I will test it tomorrow. It is obvious that drupal 8 does not include this feature in the kernel. Yet drupal has always managed users. Does your module manage the idle status ? Thank you

    – user91071
    Dec 13 '18 at 23:06






  • 1





    Maybe you should replace case ($last > ($now - 900)): by case ($last >= ($now - 900)): otherwise there will be a white at 900 seconds

    – user91071
    Dec 13 '18 at 23:11



















  • I'll add a theme tomorrow, so everybody can create their own template to add a label or customize the markup.

    – leymannx
    Dec 13 '18 at 22:58











  • This is great news, it is late I will test it tomorrow. It is obvious that drupal 8 does not include this feature in the kernel. Yet drupal has always managed users. Does your module manage the idle status ? Thank you

    – user91071
    Dec 13 '18 at 23:06






  • 1





    Maybe you should replace case ($last > ($now - 900)): by case ($last >= ($now - 900)): otherwise there will be a white at 900 seconds

    – user91071
    Dec 13 '18 at 23:11

















I'll add a theme tomorrow, so everybody can create their own template to add a label or customize the markup.

– leymannx
Dec 13 '18 at 22:58





I'll add a theme tomorrow, so everybody can create their own template to add a label or customize the markup.

– leymannx
Dec 13 '18 at 22:58













This is great news, it is late I will test it tomorrow. It is obvious that drupal 8 does not include this feature in the kernel. Yet drupal has always managed users. Does your module manage the idle status ? Thank you

– user91071
Dec 13 '18 at 23:06





This is great news, it is late I will test it tomorrow. It is obvious that drupal 8 does not include this feature in the kernel. Yet drupal has always managed users. Does your module manage the idle status ? Thank you

– user91071
Dec 13 '18 at 23:06




1




1





Maybe you should replace case ($last > ($now - 900)): by case ($last >= ($now - 900)): otherwise there will be a white at 900 seconds

– user91071
Dec 13 '18 at 23:11





Maybe you should replace case ($last > ($now - 900)): by case ($last >= ($now - 900)): otherwise there will be a white at 900 seconds

– user91071
Dec 13 '18 at 23:11


















draft saved

draft discarded




















































Thanks for contributing an answer to Drupal Answers!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdrupal.stackexchange.com%2fquestions%2f273973%2fshow-if-a-user-is-online-idle-or-offline-on-their-account-page%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Bressuire

Cabo Verde

Gyllenstierna