543 lines
No EOL
13 KiB
Perl
543 lines
No EOL
13 KiB
Perl
package WebGUI::Inbox;
|
|
|
|
=head1 LEGAL
|
|
|
|
-------------------------------------------------------------------
|
|
WebGUI is Copyright 2001-2008 Plain Black Corporation.
|
|
-------------------------------------------------------------------
|
|
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
|
|
-------------------------------------------------------------------
|
|
|
|
=cut
|
|
|
|
use strict;
|
|
use WebGUI::Inbox::Message;
|
|
|
|
=head1 NAME
|
|
|
|
Package WebGUI::Inbox;
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This class provides a message routing system, which is primarily used by WebGUI's workflow engine.
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
use WebGUI::Inbox;
|
|
|
|
=head1 METHODS
|
|
|
|
These methods are available from this class:
|
|
|
|
=cut
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 addMessage ( properties )
|
|
|
|
Adds a new message to the inbox.
|
|
|
|
=head3 properties
|
|
|
|
See WebGUI::Inbox::Message::create() for details.
|
|
|
|
=cut
|
|
|
|
sub addMessage {
|
|
my $self = shift;
|
|
return WebGUI::Inbox::Message->create($self->session, @_);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 addPrivateMessage ( properties[, userToSend] )
|
|
|
|
Adds a new private message to the inbox if the user accepts private messages.
|
|
|
|
=head3 properties
|
|
|
|
See WebGUI::Inbox::Message::addMessage() for details.
|
|
|
|
=cut
|
|
|
|
sub addPrivateMessage {
|
|
my $self = shift;
|
|
my $messageData = shift;
|
|
my $isReply = shift;
|
|
|
|
my $userId = $messageData->{userId};
|
|
my $sentBy = $messageData->{sentBy} || $self->session->user->userId;
|
|
return undef unless $userId;
|
|
|
|
my $u = WebGUI::User->new($self->session,$userId);
|
|
return undef unless ($isReply || $u->acceptsPrivateMessages($sentBy));
|
|
|
|
return $self->addMessage($messageData);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 canRead ( messageId [, user] )
|
|
|
|
Returns whether or not a user can view the message passed in.
|
|
|
|
=head3 message
|
|
|
|
A WebGUI::Inbox::Message object
|
|
|
|
=head3 user
|
|
|
|
WebGUI::User object to test against. Defaults to the current user.
|
|
|
|
=cut
|
|
|
|
sub canRead {
|
|
my $self = shift;
|
|
my $message = shift;
|
|
my $user = shift || $self->session->user;
|
|
|
|
unless (ref $message eq "WebGUI::Inbox::Message") {
|
|
$self->session->log->warn("Message passed in was either empty or not a valid WebGUI::Inbox::Message. Got: ".(ref $message));
|
|
return 0
|
|
}
|
|
|
|
my $userId = $message->get("userId");
|
|
my $groupId = $message->get("groupId");
|
|
|
|
return ($user->userId eq $userId || (defined $groupId && $user->isInGroup($groupId)));
|
|
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 DESTROY ( )
|
|
|
|
Deconstructor.
|
|
|
|
=cut
|
|
|
|
sub DESTROY {
|
|
my $self = shift;
|
|
undef $self;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getMessage ( messageId [, userId] )
|
|
|
|
Returns a WebGUI::Inbox::Message object.
|
|
|
|
=head3 messageId
|
|
|
|
The id of the message to retrieve.
|
|
|
|
=head3 userId
|
|
|
|
The id of the user to retrieve the message for. Defaults to the current user.
|
|
|
|
=cut
|
|
|
|
sub getMessage {
|
|
my $self = shift;
|
|
my $messageId = shift;
|
|
my $userId = shift;
|
|
|
|
return WebGUI::Inbox::Message->new($self->session, $messageId, $userId);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getNextMessage ( message [, userId] )
|
|
|
|
Returns the message that was send after the message passed in for the user
|
|
|
|
=head3 message
|
|
|
|
The message to find the next message for
|
|
|
|
=head3 user
|
|
|
|
The WebGUI::User object of the user to retrieve the message for. Defaults to the current user.
|
|
|
|
=cut
|
|
|
|
sub getNextMessage {
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
my $message = shift;
|
|
my $user = shift || $session->user;
|
|
|
|
my $sql = $self->getMessageSql($user,{
|
|
whereClause => "ibox.dateStamp > ".$message->get("dateStamp"),
|
|
sortBy => "ibox.dateStamp",
|
|
sortDir => "asc",
|
|
limit => 1
|
|
});
|
|
|
|
my $message = $self->session->db->quickHashRef($sql);
|
|
|
|
return $self->getMessage($message->{messageId});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getPreviousMessage ( message [, userId] )
|
|
|
|
Returns the message that was sent before the message passed in for the user
|
|
|
|
=head3 message
|
|
|
|
The message to find the previous message for
|
|
|
|
=head3 user
|
|
|
|
The WebGUI::User object of the user to retrieve the message for. Defaults to the current user.
|
|
|
|
=cut
|
|
|
|
sub getPreviousMessage {
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
my $message = shift;
|
|
my $user = shift || $session->user;
|
|
|
|
my $sql = $self->getMessageSql($user,{
|
|
whereClause => "ibox.dateStamp < ".$message->get("dateStamp"),
|
|
sortBy => "ibox.dateStamp",
|
|
sortDir => "desc",
|
|
limit => 1
|
|
});
|
|
|
|
my $message = $self->session->db->quickHashRef($sql);
|
|
|
|
return $self->getMessage($message->{messageId});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getMessagesForUser ( user [ , limit, page, sortBy ] )
|
|
|
|
Returns an array reference containing the most recent message objects for a given user.
|
|
|
|
=head3 user
|
|
|
|
A user object.
|
|
|
|
=head3 limit
|
|
|
|
An integer indicating the number of messages to fetch. Defaults to 50.
|
|
|
|
=head3 page
|
|
|
|
An integer indication the page to return. Defaults to 1
|
|
|
|
=head3 sortby
|
|
|
|
The column to sort by
|
|
|
|
=cut
|
|
|
|
sub getMessagesForUser {
|
|
my $self = shift;
|
|
my $user = shift;
|
|
my $perpage = shift || 50;
|
|
my $page = shift || 1;
|
|
my $sortBy = shift;
|
|
|
|
my $p = $self->getMessagesPaginator( $user , {
|
|
sortBy => $sortBy,
|
|
sortDir => "desc",
|
|
paginateAfter => $perpage,
|
|
pageNumber => $page
|
|
|
|
});
|
|
|
|
return $self->getMessagesOnPage($p);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getMessagesOnPage ( paginator )
|
|
|
|
Returns an array ref of WebGUI::Inbox::Message objects created from the current
|
|
page of data.
|
|
|
|
=head3 paginator
|
|
|
|
The id of the message to retrieve.
|
|
|
|
=cut
|
|
|
|
sub getMessagesOnPage {
|
|
my $self = shift;
|
|
my $p = shift;
|
|
my @messages = ();
|
|
|
|
unless (defined $p and ref $p eq "WebGUI::Paginator") {
|
|
$self->session->log->warn("Paginator was not defined");
|
|
return [];
|
|
}
|
|
|
|
foreach my $row (@{$p->getPageData}) {
|
|
push @messages, $self->getMessage( $row->{messageId} );
|
|
}
|
|
|
|
return \@messages;
|
|
}
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getMessagesPaginator ( user [, properties ] )
|
|
|
|
Returns an reference to a WebGUI::Paginator object filled with all the messages in a user's inbox
|
|
|
|
=head3 user
|
|
|
|
A user object.
|
|
|
|
=head3 properties
|
|
|
|
Properties which can be set to determine how many rows are returned, etc
|
|
|
|
=head4 sortBy
|
|
|
|
Column to sort the inbox by. Valid values are subject, sentBy, and dateStamp. Defaults to
|
|
dateStamp if value is invalid. Defaults to status="pending" DESC, dateStamp DESC if value not set.
|
|
|
|
=head4 sortDir
|
|
|
|
Direction to sort the results by. Defaults to desc. This only works if a sortBy value is set.
|
|
|
|
=head4 baseUrl
|
|
|
|
The URL of the current page including attributes. The page number will be appended to this in all links generated by the paginator.
|
|
Defaults to $session->url->pge
|
|
|
|
=head4 paginateAfter
|
|
|
|
The number of rows to display per page. If left blank it defaults to 25.
|
|
|
|
=head4 formVar
|
|
|
|
Specify the form variable the paginator should use in its links. Defaults to "pn".
|
|
|
|
=head pageNumber
|
|
|
|
By default the page number will be determined by looking at $self->session->form->process("pn"). If that is empty the page number will be defaulted to "1". If you'd like to override the page number specify it here.
|
|
|
|
=cut
|
|
|
|
sub getMessagesPaginator {
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
my $user = shift || $session->user;
|
|
my $properties = shift;
|
|
|
|
my $userId = $user->userId;
|
|
my $sortBy = $properties->{sortBy};
|
|
my $sortDir = $properties->{sortDir} || "desc";
|
|
my $baseUrl = $properties->{baseUrl} || $session->url->page;
|
|
my $paginateAfter = $properties->{paginateAfter};
|
|
my $formVar = $properties->{formVar};
|
|
my $pageNumber = $properties->{pageNumber};
|
|
|
|
#Make sure a valid sortBy is passed in
|
|
if($sortBy && !WebGUI::Utility::isIn($sortBy,qw( subject sentBy dateStamp status ))) {
|
|
$sortBy = q{dateStamp}
|
|
}
|
|
#Sort by fullname if user wants to sort by who sent the message
|
|
if ($sortBy eq "sentBy") {
|
|
$sortBy = q{fullName};
|
|
}
|
|
elsif ($sortBy eq "status") {
|
|
$sortBy = q{messageStatus};
|
|
}
|
|
elsif($sortBy) {
|
|
$sortBy = qq{ibox.$sortBy};
|
|
}
|
|
else {
|
|
$sortBy = q{messageStatus='pending' DESC, dateStamp DESC};
|
|
$sortDir = q{};
|
|
}
|
|
|
|
my $sql = $self->getMessageSql($user, {
|
|
user => $user,
|
|
sortBy => $sortBy,
|
|
sortDir => $sortDir
|
|
});
|
|
|
|
#$session->log->warn($sql);
|
|
|
|
my $p = WebGUI::Paginator->new(
|
|
$session,
|
|
$baseUrl,
|
|
$paginateAfter,
|
|
$formVar,
|
|
$pageNumber
|
|
);
|
|
|
|
$p->setDataByQuery($sql,undef,undef);
|
|
|
|
return $p;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getMessageSql ( user, properties )
|
|
|
|
Returns the SQL used to return the messages in a user's inbox.
|
|
|
|
=head3 user
|
|
|
|
WebGUI::User object of user to get messages for. Defaults to current user.
|
|
|
|
=head3 properties
|
|
|
|
Hash reference of properties
|
|
|
|
=head4 sortBy
|
|
|
|
Column to sort by. Valid columns are:
|
|
|
|
ibox.messageId,
|
|
ibox.subject,
|
|
ibox.sentBy,
|
|
ibox.dateStamp,
|
|
ibox.status,
|
|
messageStatus,
|
|
fullName
|
|
|
|
=head4 sortDir
|
|
|
|
Direction to sort by
|
|
|
|
=head4 whereClause
|
|
|
|
A where clause to use
|
|
|
|
=head4 limit
|
|
|
|
Column
|
|
|
|
=cut
|
|
|
|
sub getMessageSql {
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
my $user = shift || $session->user;
|
|
my $props = shift || {};
|
|
|
|
my $userId = $user->userId;
|
|
my $sortBy = $props->{sortBy};
|
|
my $sortDir = $props->{sortDir};
|
|
my $whereClause = $props->{whereClause};
|
|
my $limit = $props->{limit};
|
|
|
|
if($sortBy) {
|
|
$sortBy = qq{ORDER BY $sortBy $sortDir};
|
|
}
|
|
|
|
if($whereClause) {
|
|
$whereClause = qq{WHERE $whereClause};
|
|
}
|
|
|
|
if($limit) {
|
|
$limit = qq{LIMIT $limit};
|
|
}
|
|
|
|
my $messageLimit = 20_000;
|
|
my $limitHalf = $messageLimit / 2;
|
|
my $limitQuarter = $messageLimit / 4;
|
|
my $userGroups = $session->db->quoteAndJoin( $user->getGroupIdsRecursive );
|
|
$userGroups = "''" if $userGroups eq "";
|
|
|
|
# for performance purposes don't use datasets larger than 20000 no matter how man messages are in the inbox
|
|
my $sql = qq{
|
|
SELECT
|
|
ibox.messageId, ibox.subject, ibox.sentBy, ibox.dateStamp,
|
|
(IF(ibox.status = 'completed' or ibox.status = 'pending',ibox.status,IF(inbox_messageState.repliedTo,'replied',IF(inbox_messageState.isRead,'read','unread')))) as messageStatus,
|
|
(IF(userProfileData.firstName != '' and userProfileData.firstName is not null and userProfileData.lastName !='' and userProfileData.lastName is not null, concat(userProfileData.firstName,' ',userProfileData.lastName),users.username)) as fullName
|
|
FROM (
|
|
( SELECT messageId, subject, sentBy, dateStamp, status FROM inbox WHERE userId = '$userId' order by dateStamp desc limit $limitHalf)
|
|
UNION
|
|
( SELECT messageId, subject, sentBy, dateStamp, status FROM inbox WHERE groupId IN ( $userGroups ) order by dateStamp desc limit $limitHalf )
|
|
) AS ibox
|
|
JOIN inbox_messageState on inbox_messageState.messageId=ibox.messageId and inbox_messageState.userId='$userId' and inbox_messageState.deleted=0
|
|
LEFT JOIN users on users.userId=ibox.sentBy
|
|
LEFT JOIN userProfileData on userProfileData.userId=ibox.sentBy
|
|
$whereClause
|
|
$sortBy
|
|
$limit
|
|
};
|
|
|
|
#$session->log->warn($sql);
|
|
|
|
return $sql;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getUnreadMessageCount ( [userId] )
|
|
|
|
Returns the number of unread messages for the user passed in
|
|
|
|
=head3 userId
|
|
|
|
user to get unread message count for. Defaults to current user.
|
|
|
|
=cut
|
|
|
|
sub getUnreadMessageCount {
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
my $userId = shift || $session->user->userId;
|
|
|
|
return $session->db->quickScalar(
|
|
qq{select count(*) from inbox_messageState where userId=? and deleted=0 and isRead=0 },
|
|
[$userId]
|
|
);
|
|
}
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 new ( session )
|
|
|
|
Constructor.
|
|
|
|
=head3 session
|
|
|
|
A reference to the current session.
|
|
|
|
=cut
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
my $session = shift;
|
|
bless {_session=>$session}, $class;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 session ( )
|
|
|
|
Returns a reference to the current session.
|
|
|
|
=cut
|
|
|
|
sub session {
|
|
my $self = shift;
|
|
return $self->{_session};
|
|
}
|
|
|
|
|
|
1; |