299 lines
8.8 KiB
Perl
299 lines
8.8 KiB
Perl
package WebGUI::Macro::UsersOnline;
|
|
|
|
=head1 LEGAL
|
|
|
|
-------------------------------------------------------------------
|
|
WebGUI is Copyright 2001-2009 Plain Black LLC.
|
|
-------------------------------------------------------------------
|
|
Please read the legal notices (docs/legal.txt) and the license
|
|
(docs/license.txt) that came with this distribution before using
|
|
this software.
|
|
-------------------------------------------------------------------
|
|
http://www.plainblack.com info@plainblack.com
|
|
-------------------------------------------------------------------
|
|
Authors of Macro:
|
|
Carlos Rivero (http://www.carlosrivero.com),
|
|
Bernd Kalbfuss-Zimmermann
|
|
-------------------------------------------------------------------
|
|
|
|
=cut
|
|
|
|
use strict;
|
|
use Apache2::ServerRec;
|
|
use Net::DNS;
|
|
use WebGUI::Asset::Template;
|
|
use WebGUI::International;
|
|
use WebGUI::Session::DateTime;
|
|
use WebGUI::SQL;
|
|
use WebGUI::User;
|
|
|
|
=head1 NAME
|
|
|
|
Package WebGUI::Macro::UsersOnline;
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
Macro for displaying users that are online.
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 process ( [templateId], [minutes], [maxMembers], [maxVisitors] )
|
|
|
|
Returns a fragment of HTML code showing the number of users online. Appearance
|
|
can be altered by specifying an alternative template.
|
|
|
|
=head3 templateId
|
|
|
|
The ID of the template to be processed. The default is 'h_T2xtOxGRQ9QJOR6ebLpQ'.
|
|
|
|
=head3 minutes
|
|
|
|
The number of minutes the last activity may date back for a user to count as
|
|
online.cThe default is 5 minutes.
|
|
|
|
=head3 maxMembers
|
|
|
|
The maximum number of members to be returned in the members template loop. The
|
|
default is 10.
|
|
|
|
=head3 maxVisitors
|
|
|
|
The maximum number of visitors to be returned in the visitors template loop. The
|
|
default is 10.
|
|
|
|
=cut
|
|
|
|
sub process {
|
|
|
|
# Assign parameters
|
|
my $session = shift;
|
|
my $templateId = shift;
|
|
my $minutes = shift;
|
|
my $maxMembers = shift;
|
|
my $maxVisitors = shift;
|
|
|
|
# Assign default values
|
|
$templateId ||= "h_T2xtOxGRQ9QJOR6ebLpQ";
|
|
$minutes = 5 unless defined $minutes;
|
|
$maxMembers = 10 unless defined $maxMembers;
|
|
$maxVisitors = 10 unless defined $maxVisitors;
|
|
|
|
|
|
# Create hash of template variables
|
|
my %var;
|
|
# Obtain internationalization instance
|
|
my $i18n = WebGUI::International->new($session, "Macro_UsersOnline");
|
|
# Get preferred time format of current user
|
|
my $time_format = $session->user->profileField("timeFormat");
|
|
|
|
# Calculate epoch time for comparison to last activity
|
|
my $dt = $session->datetime;
|
|
my $epoch = $dt->time();
|
|
$epoch = $session->datetime->addToTime($epoch, 0, -$minutes, 0);
|
|
|
|
# Let private subroutines do the work
|
|
_visitors($session, \%var, $epoch, $maxVisitors);
|
|
_members($session, \%var, $epoch, $maxMembers);
|
|
|
|
# Calculate the total number of active users
|
|
$var{'total'} = $var{'members'} + $var{'visitors'};
|
|
# Set some flags
|
|
$var{'isVisitor'} = 1 if ($session->user->userId == 1);
|
|
$var{'hasMembers'} = 1 if $var{'member_loop'};
|
|
|
|
# Assign labels
|
|
$var{'usersOnline_label'} = $i18n->get("Users Online");
|
|
$var{'members_label'} = $i18n->get("Members");
|
|
$var{'visitors_label'} = $i18n->get("Visitors");
|
|
$var{'total_label'} = $i18n->get("Total");
|
|
$var{'membersOnline_label'} = $i18n->get("Members Online");
|
|
$var{'visitorsOnline_label'} = $i18n->get("Visitors Online");
|
|
$var{'avatar_label'} = $i18n->get("Avatar");
|
|
$var{'name_label'} = $i18n->get("Name");
|
|
$var{'alias_label'} = $i18n->get("Alias");
|
|
$var{'session_label'} = $i18n->get("Session");
|
|
$var{'ip_label'} = $i18n->get("IP");
|
|
$var{'lastActivity_label'} = $i18n->get("Last Activity");
|
|
|
|
# Process Template
|
|
return WebGUI::Asset::Template->new($session,$templateId)->process(\%var);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 _visitors ( session, varRef, epoch, maxVisitors )
|
|
|
|
Fills template variables concerning visitors, i.e. the number of visitors and
|
|
all variables in the visitors loop. Private subroutine used by process().
|
|
|
|
=head3 session
|
|
|
|
A reference to the current session.
|
|
|
|
=head3 varRef
|
|
|
|
A reference to the hash of template variables.
|
|
|
|
=head3 epoch
|
|
|
|
Epoch time for comparison to last activity.
|
|
|
|
=head3 maxVisitors
|
|
|
|
The maximum number of visitors to be returned in the visitors template loop.
|
|
|
|
=cut
|
|
|
|
sub _visitors {
|
|
|
|
# Assign parameters
|
|
my $session = shift;
|
|
my $var = shift;
|
|
my $epoch = shift;
|
|
my $maxVisitors = shift;
|
|
|
|
# Obtain some session-associated objects
|
|
my $db = $session->db();
|
|
my $dt = $session->datetime;
|
|
# Get preferred time format of current user
|
|
my $time_format = $session->user->profileField("timeFormat");
|
|
|
|
# SQL conditional clause for filtering server IP
|
|
my $ip_clause;
|
|
|
|
# Check whether instance of Apache2::ServerRec is available
|
|
if($session->server) {
|
|
# Query hostname of server
|
|
my $hostname = $session->server->server_hostname();
|
|
|
|
# Look up server IP addresses
|
|
my $res = Net::DNS::Resolver->new();
|
|
my $query = $res->search($hostname);
|
|
if ($query) {
|
|
foreach my $rr ($query->answer) {
|
|
next unless $rr->type eq "A";
|
|
# Generate SQL clause which excludes server IPs
|
|
$ip_clause = $ip_clause . "AND STRCMP(lastIp, '" . $rr->address . "') ";
|
|
}
|
|
}
|
|
}
|
|
|
|
# Determine the number of visitors. Server IP adresses and the loopback
|
|
# network are excluded. We only count IPs - not sessions. The reason is
|
|
# that crawlers tend to open multiple sessions(e.g. googlebot) and thereby
|
|
# increase the count artificially. Note, that the number determined here
|
|
# may deviate from the number of items returned in the visitor loop.
|
|
$$var{'visitors'} = $db->quickScalar("SELECT COUNT(DISTINCT lastIp) FROM " .
|
|
"userSession WHERE (lastPageView > $epoch) AND (userId = 1) AND " .
|
|
"lastIp NOT LIKE '127.%.%.%'" . $ip_clause);
|
|
|
|
# Query session IDs and IPs of visitors
|
|
my $query = $db->prepare("SELECT sessionId, lastIp, lastPageView FROM " .
|
|
"userSession WHERE (lastPageView > $epoch) AND (userId = 1) AND " .
|
|
"lastIp NOT LIKE '127.%.%.%' " . $ip_clause . "LIMIT $maxVisitors");
|
|
$query->execute;
|
|
|
|
# Iterate through rows
|
|
while (my %row = $query->hash) {
|
|
# Add item to visitor template loop
|
|
push(@{$$var{'visitor_loop'}}, {
|
|
sessionId => $row{'sessionId'},
|
|
ip => $row{'lastIp'},
|
|
lastActivity => $dt->epochToHuman($row{'lastPageView'}, $time_format)
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 _members ( session, varRef, epoch, maxMembers )
|
|
|
|
Fills template variables concerning members, i.e. the number of members and
|
|
all variables in the members loop. Private subroutine used by process().
|
|
|
|
=head3 session
|
|
|
|
A reference to the current session.
|
|
|
|
=head3 varRef
|
|
|
|
A reference to the hash of template variables.
|
|
|
|
=head3 epoch
|
|
|
|
Epoch time for comparison to last activity.
|
|
|
|
=head3 maxMembers
|
|
|
|
The maximum number of members to be returned in the members template loop.
|
|
|
|
=cut
|
|
|
|
sub _members {
|
|
|
|
# Assign parameters
|
|
my $session = shift;
|
|
my $var = shift;
|
|
my $epoch = shift;
|
|
my $maxMembers = shift;
|
|
|
|
# Obtain some session-associated objects
|
|
my $db = $session->db();
|
|
my $dt = $session->datetime;
|
|
# Get preferred time format of current user
|
|
my $time_format = $session->user->profileField("timeFormat");
|
|
|
|
# Determine the number of registered users that are online. The Admin
|
|
# account is excluded from the list.
|
|
$$var{'members'} = $db->quickScalar("SELECT COUNT(DISTINCT userId) FROM " .
|
|
"userSession where (lastPageView > $epoch) and (userId != 1) and " .
|
|
"(userId != 3)");
|
|
|
|
# Query the names of registered users that are online. The showOnline flag
|
|
# in the user profile is respected.
|
|
my $query = $db->prepare("SELECT userId, sessionId, lastIp, lastPageView " .
|
|
"FROM userSession WHERE (lastPageView > $epoch) AND (userId != 1) " .
|
|
"AND (userId != 3) LIMIT $maxMembers");
|
|
$query->execute;
|
|
|
|
# Iterate through rows
|
|
while (my %row = $query->hash) {
|
|
# Create instance of WebGUI::User for the user id from the current row
|
|
my $user = WebGUI::User->new($session, $row{'userId'});
|
|
|
|
# Only show users with the "showOnline" flag set to true
|
|
if ($user->profileField("showOnline")) {
|
|
# Find URL of avatar if available
|
|
my $avatar_url;
|
|
my $avatar = $user->profileField("avatar");
|
|
if ($avatar) {
|
|
my $storage = WebGUI::Storage->get($session, $avatar);
|
|
my @files = @{ $storage->getFiles() };
|
|
# We assume it is the first file in the storage. But maybe
|
|
# that is incorrect?
|
|
$avatar_url = $storage->getUrl($files[0]);
|
|
}
|
|
|
|
# Add item to member template loop
|
|
push(@{$$var{'member_loop'}}, {
|
|
username => $user->username(),
|
|
firstName => $user->profileField("firstName"),
|
|
middleName => $user->profileField("middleName"),
|
|
lastName => $user->profileField("lastName"),
|
|
alias => $user->profileField("alias"),
|
|
avatar => $avatar_url,
|
|
uid => $row{'userId'},
|
|
sessionId => $row{'sessionId'},
|
|
ip => $row{'lastIp'},
|
|
lastActivity => $dt->epochToHuman($row{'lastPageView'}, $time_format)
|
|
});
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
1;
|