Note from the moderator: Thank you for sharing the snippet with the Drupal community. In its current state the snippet might present security risks. See Writing secure code for a background on the most common problems.

Specifically, the second snippet

  • allows SQL injection because it uses user supplied data directly inside an SQL query without further checks. Proper use of Drupals database abstraction layer can prevent these attacks.

Example of db_query usage:

  db_query("SELECT * FROM {users} WHERE uid = $uid"); // INSECURE
  db_query("SELECT * FROM {users} WHERE uid = %d", $uid);

--

PLEASE NOTE! These snippets are user submitted. It is impossible to check them all, so please use at your own risk! For users who have setup drupal using an alternate database to the default (MYSQL), please note that the snippets may contain some database queries specific to MYSQL.

Description

This php snippet adds a This user is [online/Offline] status message in the user profile page.

Dependencies: profile.module must be installed and enabled.

Usage

  • For use in your user profile page override
  • Using a text editor like NOTEPAD.EXE or an equivalent, copy and paste the code into your user_profile.tpl.php file
  • Select appropriate snippet for the versionof Drupal you are using
  • Change the div class name or the message text to suit.

Snippet for Drupal 4.5 and 4.6

<?php
print "<div class=\"fields\">";
print "Online/Offline Status";
$time_period = variable_get('user_block_seconds_online', 2700);
$uid = arg(1); // get the current userid that is being viewed.
$users = db_query('SELECT DISTINCT(uid), MAX(timestamp) AS max_timestamp FROM {sessions} WHERE timestamp >= %d AND uid = %u GROUP BY uid ORDER BY max_timestamp DESC', time() - $time_period, $uid);
		  $total_users = db_num_rows($users);

		  if ($total_users == 1) {
		    $output = t('This user is currently online'); 
		  }
		  else {
		    $output = t('This user is currently offline'); 		
		  }

	          print $output;
                       print "</div>";
?>

Snippet for Drupal 4.7

Thanks to rocketman528 for this snippet.

<?php
print "<div class=\"fields\">";
print "Online/Offline Status";
$time_period = variable_get('user_block_seconds_online', 2700);
$uid = arg(1); // get the current userid that is being viewed.
$users = db_query("SELECT uid, name, access FROM {users} WHERE access >= %d AND uid = $uid", time() - $time_period);
          $total_users = db_num_rows($users);

          if ($total_users == 1) {
            $output = t('This user is currently online');
          }
          else {
            $output = t('This user is currently offline');      
          }

              print $output;
                      print "</div>";
?>

Comments

WhatTheFawk’s picture

I'm using this in Drupal 5.1 with the usernode.module. I had to change a few things in this snippet because the way it's getting the uid by using arg(1) conflicted with the new usernode.module. The usernode.module, (if used with the template.php code that comes with it), overwrites user/[uid] from all links and takes you to usernode/[usernodeid], BUT usernodeid which is what arg(1) will grab is not the uid so $uid = arg(1); wasn't working.

Change:

$uid = arg(1); // get the current userid that is being viewed.
$users = db_query("SELECT uid, name, access FROM {users} WHERE access >= %d AND uid = $uid", time() - $time_period);

To:

$users = db_query("SELECT DISTINCT(uid), access FROM {users} WHERE access >= %d AND uid = %s", time() - $time_period, $user->uid);

It all works smoothly so far so I hope this is correct, I read above if you're using $user->uid or similar you shouldn't directly have uid = $user->uid in the SQL query, but instead should use db_query("SELECT foo FROM {bar} WHERE uid = %s",$user->uid); syntax, can anyone tell me if I'm doing this right?

Full Code [Drupal 5.1][ Makes User Online/Offline snippet compatible with usernode.module ]:

<?php
	print "<div class=\"fields\">";
	
        $time_period = variable_get('user_block_seconds_online', 600);
	$users = db_query("SELECT DISTINCT(uid), access FROM {users} WHERE access >= %d AND uid = %s", time() - $time_period, $user->uid);
	$total_users = db_num_rows($users);
		if ($total_users == 1) 
		{
			$output = t($user->name.' is currently online');
		}
		else 
		{
			$output = t($user->name.' is currently offline');      
		}
		
	print $output;
	print "</div>";
?>

I also in $time_period I shortened 2700 which I think is 45 mins to 600 (10 mins), 45 mins seemed a bit long to me. I thought it was broken when I was checking the status of another user, but really I just hadn't waited 45 mins after logging off to check.

stevenjo’s picture

Add

global $user;

right below <? tag to make it work.

Steven Jodistiro
http://www.groklight.com

Drupal_’s picture

It worked for me without the global $user .. I am using 5.1

-----------------------------
PopularSikh - for the sikh inside you
http://www.popularsikh.com

ebeyrent’s picture

Does this really indicate that the user is currently logged in? Perhaps I don't understand the code, but it looks like you are making the assumption that after 45 (or 10) minutes, the user is not logged in anymore. Does the user record contain a flag that can be queried regarding whether a user is logged in or not?

Michelle’s picture

This snippit has nothing to do with whether they are looged in. It is making a best guess as to whether they are online based on the time since last activity. Since people can stay logged in when they aren't using the site, being logged is irrelevent.

Michelle

--------------------------------------
See my Drupal articles and tutorials or come check out life in the Coulee Region.

Chippe’s picture

I agree, even if you log out it will say you're online. While you're online, it seems like surfing the site is not enough to keep you active. You will have to make a post or something.

I made a small change so it'll work in D6.

BTW, Im still looking for a better way to show the online/offline status.
I think it should be based on if you are logged in or out but also on activness since you might leave the site without logging out and visiting a node = active.

Here is the code for Drupal 6 in case somebody wants it:

print "<div class=\"fields\">";
print "Online/Offline Status";
$time_period = variable_get('user_block_seconds_online', 2700);
$uid = arg(1); // get the current userid that is being viewed.
$users = db_query("SELECT uid, name, access FROM {users} WHERE access >= %d AND uid = $uid", time() - $time_period);
          $total_users = db_result($users);

          if ($total_users == 1) {
            $output = t('This user is currently online');
          }
          else {
            $output = t('This user is currently offline');     
          }

              print $output;
                      print "</div>";

Altaisoft’s picture

I'm using Drupal 6.6. In the user-profile.tpl.php file the $account variable is allowed. It contains all the data required.

  $time_period = variable_get('user_block_seconds_online', 2700);
  $uid = $account->uid; // get the current userid that is being viewed.
  if ($account->access > time() - $time_period) {
    echo 'Online';
  }
  else {
    echo 'Offline';
  }

This works for me pretty well.

konordo’s picture

Two handy lines of code from http://drupal.org/project/user_stats module:

      $user_access = db_result(db_query("SELECT access FROM {users} WHERE uid = %d", $uid));
      $data = (round((time() - $user_access) / 60) < 15 ? TRUE : FALSE);

This could be used when e.g. creating a view with a list of users.

--------------------------------------------
Konordo Ltd
http://www.konordo.com

miaoulafrite’s picture

Dear konordo,

thanks for your post, this is exactly what i am looking for: views listing users + indicating status (online/offline).
could you please be more detailed when presenting the information?

where are these lines supposed to be inserted? in views? how?

thanks

miaoulafrite’s picture

actually, there is also another variable in page.tpl.php, $logged_in, it would be better to user it instead of checking if the user has done something in the last 15min, no?

konordo’s picture

Hi! Sorry for the late response...

Indeed, you can use the $logged_in variable (or the http://api.drupal.org/api/function/user_is_logged_in/6 function) to check if the user is logged in.
But the question in this case is, rather, if the user is active - if they are using the site, and therefore it is irrelevant if they are logged in or not.
Check Michelle's comment above http://drupal.org/node/36822#comment-285228.

There are many cases where this snippet could come in handy. For example, create a PHP block that will appear in user pages (user/user-id).
You can take the user-id with args and use it in there to show if this user is "active" or not.

I used this in a project to create a list of users with views, also displaying their activity status. I added a PHP field with http://drupal.org/project/views_customfield - the uid can be found in the $data.

In other cases i checked the $logged_in var in my tpl, to show different pieces of code to anonymous and to logged in users - activity is irrelevant in this case. If users are logged in, they will see different things.

It depends on what you need to accomplish.

Hope that helps!

--------------------------------------------
Konordo Ltd
http://www.konordo.com

superdorx’s picture

Is anyone planning to post a Drupal 7 version of this snippet?

Thanks!

Québec’s picture

Interested in this snippet for D7. Having the code for display a «light» (online/offline) in a block would be nice.

Thanks

fugazi’s picture

I would also interest for a d7 snippet

vadivel123’s picture

There is no straight forward to do this afaik. There is no proper way to detect whether a user has closed his browser. One method I have seen commonly used to solve this specific problem [within your context] is by using a last_activity_timestamp field in the posts table. Each time a user does any activity, the last_activity_timestamp is updated with the new time.
$res = mysql_query("UPDATE `posts` SET last_update_timestamp = NOW() WHERE user_id = {$currentUserId};");

Then in your code for checking whether a user is currently online, you can also check whether a certain time period (say 20 minutes) has elapsed since the last activity of a user like so:

$res = mysql_query("SELECT * FROM `posts` WHERE status=1 AND TIMESTAMPDIFF(MINUTE, last_activity_timestamp, NOW()) > 20;");

If the last activity of a user was more than 20 minutes old, then he is effectively logged out.

view source from allinonescript.com