mirror of
https://github.com/Mibew/tray.git
synced 2025-01-22 18:10:34 +03:00
Create Thread class and tests for it
This commit is contained in:
parent
1a963cff00
commit
03ffd84e76
1226
src/messenger/tests/server_side/webim/classes/ThreadTest.php
Normal file
1226
src/messenger/tests/server_side/webim/classes/ThreadTest.php
Normal file
File diff suppressed because it is too large
Load Diff
727
src/messenger/webim/libs/classes/thread.php
Normal file
727
src/messenger/webim/libs/classes/thread.php
Normal file
@ -0,0 +1,727 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2005-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a chat thread
|
||||
*
|
||||
* @todo Think about STATE_* and KIND_* constant systems and may be simplifies them.
|
||||
*/
|
||||
Class Thread {
|
||||
|
||||
/**
|
||||
* User in the users queue
|
||||
*/
|
||||
const STATE_QUEUE = 0;
|
||||
/**
|
||||
* User waiting for operator
|
||||
*/
|
||||
const STATE_WAITING = 1;
|
||||
/**
|
||||
* Conversation in progress
|
||||
*/
|
||||
const STATE_CHATTING = 2;
|
||||
/**
|
||||
* Thread closed
|
||||
*/
|
||||
const STATE_CLOSED = 3;
|
||||
/**
|
||||
* Thread just created
|
||||
*/
|
||||
const STATE_LOADING = 4;
|
||||
/**
|
||||
* User left message without starting a conversation
|
||||
*/
|
||||
const STATE_LEFT = 5;
|
||||
|
||||
/**
|
||||
* Message sent by user
|
||||
*/
|
||||
const KIND_USER = 1;
|
||||
/**
|
||||
* Message sent by operator
|
||||
*/
|
||||
const KIND_AGENT = 2;
|
||||
/**
|
||||
* Hidden system message to operator
|
||||
*/
|
||||
const KIND_FOR_AGENT = 3;
|
||||
/**
|
||||
* System messages for user and operator
|
||||
*/
|
||||
const KIND_INFO = 4;
|
||||
/**
|
||||
* Message for user if operator have connection problems
|
||||
*/
|
||||
const KIND_CONN = 5;
|
||||
/**
|
||||
* System message about some events (like rename).
|
||||
*/
|
||||
const KIND_EVENTS = 6;
|
||||
/**
|
||||
* Message with operators avatar
|
||||
*/
|
||||
const KIND_AVATAR = 7;
|
||||
|
||||
/**
|
||||
* Messaging window connection timeout.
|
||||
*/
|
||||
const CONNECTION_TIMEOUT = 30;
|
||||
|
||||
/**
|
||||
* Contain mapping of thread object properties to fields in database.
|
||||
*
|
||||
* Keys are object properties and vlues are {chatthread} table fields. Properties are available via magic __get
|
||||
* and __set methods. Real values are stored in the Thread::$threadInfo array.
|
||||
*
|
||||
* Thread object have following properties:
|
||||
* - 'id': id of the thread
|
||||
* - 'lastRevision': last revision number
|
||||
* - 'state': state of the thread. See Thread::STATE_*
|
||||
* - 'lastToken': last chat token
|
||||
* - 'nextAgent': id of the next agent(agent that change current agent in the chat)
|
||||
* - 'groupId': id of the group related to the thread
|
||||
* - 'shownMessageId': last id of shown message
|
||||
* - 'messageCount': count of user's messages related to the thread
|
||||
* - 'created': unix timestamp of the thread creation
|
||||
* - 'modified': unix timestamp of the thread's last modification
|
||||
* - 'chatStarted': unix timestamp of related to thread chat started
|
||||
* - 'agentId': id of an operator who take part in the chat
|
||||
* - 'agentName': name of an operator who take part in the chat
|
||||
* - 'agentTyping': "1" if operator typing at last ping time and "0" otherwise
|
||||
* - 'lastPingAgent': unix timestamp of last operator ping
|
||||
* - 'locale': locale code of the chat related to thread
|
||||
* - 'userId': id of an user who take part in the chat
|
||||
* - 'userName': name of an user who take part in the chat
|
||||
* - 'userTyping': "1" if user typing at last ping time and "0" otherwise
|
||||
* - 'lastPingUser': unix timestamp of last user ping
|
||||
* - 'remote': user's IP
|
||||
* - 'referer': content of HTTP Referer header for user
|
||||
* - 'userAgent': content of HTTP User-agent header for user
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @see Thread::__get()
|
||||
* @see Thread::__set()
|
||||
* @see Thread::$threadInfo
|
||||
*/
|
||||
protected $propertyMap = array(
|
||||
'id' => 'threadid',
|
||||
|
||||
'lastRevision' => 'lrevision',
|
||||
'state' => 'istate',
|
||||
'lastToken' => 'ltoken',
|
||||
|
||||
'nextAgent' => 'nextagent',
|
||||
'groupId' => 'groupid',
|
||||
|
||||
'shownMessageId' => 'shownmessageid',
|
||||
'messageCount' => 'messageCount',
|
||||
|
||||
'created' => 'dtmcreated',
|
||||
'modified' => 'dtmmodified',
|
||||
'chatStarted' => 'dtmchatstarted',
|
||||
|
||||
'agentId' => 'agentId',
|
||||
'agentName' => 'agentName',
|
||||
'agentTyping' => 'agentTyping',
|
||||
'lastPingAgent' => 'lastpingagent',
|
||||
|
||||
'locale' => 'locale',
|
||||
|
||||
'userId' => 'userid',
|
||||
'userName' => 'userName',
|
||||
'userTyping' => 'userTyping',
|
||||
'lastPingUser' => 'lastpinguser',
|
||||
|
||||
'remote' => 'remote',
|
||||
'referer' => 'referer',
|
||||
'userAgent' => 'userAgent'
|
||||
);
|
||||
|
||||
/**
|
||||
* Contain loaded from database information about thread
|
||||
*
|
||||
* Do not use this property manually!
|
||||
* @var array
|
||||
*/
|
||||
protected $threadInfo;
|
||||
|
||||
/**
|
||||
* List of modified fields.
|
||||
*
|
||||
* Do not use this property manually!
|
||||
* @var array
|
||||
*/
|
||||
protected $updatedFields = array();
|
||||
|
||||
/**
|
||||
* Load thread from database or create a new one in the database if $id is empty.
|
||||
*
|
||||
* @param int $id ID of the thread to load
|
||||
*/
|
||||
protected function __construct($id = null) {
|
||||
// Get database object
|
||||
$db = Database::getInstance();
|
||||
|
||||
if (! empty($id)) {
|
||||
// Load thread
|
||||
$thread_info = $db->query(
|
||||
"select * from {chatthread} where threadid = :threadid",
|
||||
array(
|
||||
':threadid' => $id
|
||||
),
|
||||
array('return_rows' => Database::RETURN_ONE_ROW)
|
||||
);
|
||||
|
||||
if (! $thread_info) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->threadInfo = $thread_info;
|
||||
} else {
|
||||
// Create thread
|
||||
$db->query("insert into {chatthread} (threadid) values (NULL)");
|
||||
// Set initial values
|
||||
// In this case Thread::$threadInfo array use because id of a thread should not be update
|
||||
$this->threadInfo['threadid'] = $db->insertedId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new empty thread in database
|
||||
*
|
||||
* @return boolean|Thread Returns an object of the Thread class or boolean false on failure
|
||||
*/
|
||||
public static function create() {
|
||||
// Create new empty thread
|
||||
$thread = new self();
|
||||
// Check if something went wrong
|
||||
if (empty($thread->id)) {
|
||||
return false;
|
||||
}
|
||||
return $thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load thread from database
|
||||
*
|
||||
* @param int $id ID of the thread to load
|
||||
* @return boolean|Thread Returns an object of the Thread class or boolean false on failure
|
||||
*/
|
||||
public static function load($id) {
|
||||
// Check $id
|
||||
if (empty($id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load thread
|
||||
$thread = new self($id);
|
||||
|
||||
// Check if something went wrong
|
||||
if ($thread->id != $id) {
|
||||
return false;
|
||||
}
|
||||
return $thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reopen thread and send message about it
|
||||
*
|
||||
* @return boolean|Thread Boolean FALSE on failure or thread object on success
|
||||
*/
|
||||
public static function reopen($id) {
|
||||
// Load thread
|
||||
$thread = self::load($id);
|
||||
// Check if user and agent gone
|
||||
if (Settings::get('thread_lifetime') != 0 &&
|
||||
abs($thread->lastPingUser - time()) > Settings::get('thread_lifetime') &&
|
||||
abs($thread->lastPingAgent - time()) > Settings::get('thread_lifetime')) {
|
||||
unset($thread);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if thread closed
|
||||
if ($thread->state == self::STATE_CLOSED || $thread->state == self::STATE_LEFT) {
|
||||
unset($thread);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reopen thread
|
||||
if ($thread->state == self::STATE_WAITING) {
|
||||
$thread->nextAgent = 0;
|
||||
$thread->save();
|
||||
}
|
||||
|
||||
// Send message
|
||||
$thread->postMessage(self::KIND_EVENTS, getstring_("chat.status.user.reopenedthread", $thread->locale));
|
||||
return $thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close all old threads that were not closed by some reasons
|
||||
*/
|
||||
public static function closeOldThreads() {
|
||||
if (Settings::get('thread_lifetime') == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$db = Database::getInstance();
|
||||
|
||||
$query = "update {chatthread} set lrevision = :next_revision, " .
|
||||
"dtmmodified = :now, istate = :state_closed " .
|
||||
"where istate <> :state_closed and istate <> :state_left " .
|
||||
"and ((lastpingagent <> 0 and lastpinguser <> 0 and " .
|
||||
"(ABS(:now - lastpinguser) > :thread_lifetime and " .
|
||||
"ABS(:now - lastpingagent) > :thread_lifetime)) or " .
|
||||
"(lastpingagent = 0 and lastpinguser <> 0 and " .
|
||||
"ABS(:now - lastpinguser) > :thread_lifetime))";
|
||||
|
||||
$db->query(
|
||||
$query,
|
||||
array(
|
||||
':next_revision' => self::nextRevision(),
|
||||
':now' => time(),
|
||||
':state_closed' => self::STATE_CLOSED,
|
||||
':state_left' => self::STATE_LEFT,
|
||||
':thread_lifetime' => Settings::get('thread_lifetime')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return next revision number (last revision number plus one)
|
||||
*
|
||||
* @return int revision number
|
||||
*/
|
||||
protected static function nextRevision() {
|
||||
$db = Database::getInstance();
|
||||
$db->query("update {chatrevision} set id=LAST_INSERT_ID(id+1)");
|
||||
$val = $db->insertedId();
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of the magic __get method
|
||||
*
|
||||
* Check if variable with name $name exists in the Thread::$propertyMap array.
|
||||
* If it does not exist triggers an error with E_USER_NOTICE level and returns false.
|
||||
*
|
||||
* @param string $name property name
|
||||
* @return mixed
|
||||
* @see Thread::$propertyMap
|
||||
*/
|
||||
public function __get($name) {
|
||||
// Check property existance
|
||||
if (! array_key_exists($name, $this->propertyMap)) {
|
||||
trigger_error("Undefined property '{$name}'", E_USER_NOTICE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$field_name = $this->propertyMap[$name];
|
||||
return $this->threadInfo[$field_name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of the magic __set method
|
||||
*
|
||||
* Check if variable with name $name exists in the Thread::$propertyMap array before setting.
|
||||
* If it does not exist triggers an error with E_USER_NOTICE level and value will NOT set.
|
||||
*
|
||||
* @param string $name Property name
|
||||
* @param mixed $value Property value
|
||||
* @return mixed
|
||||
* @see Thread::$propertyMap
|
||||
*/
|
||||
public function __set($name, $value) {
|
||||
if (empty($this->propertyMap[$name])) {
|
||||
trigger_error("Undefined property '{$name}'", E_USER_NOTICE);
|
||||
return;
|
||||
}
|
||||
|
||||
$field_name = $this->propertyMap[$name];
|
||||
$this->threadInfo[$field_name] = $value;
|
||||
|
||||
if (! in_array($field_name, $this->updatedFields)) {
|
||||
$this->updatedFields[] = $field_name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of the magic __isset method
|
||||
*
|
||||
* Check if variable with $name exists.
|
||||
*
|
||||
* param string $name Variable name
|
||||
* return boolean True if variable exists and false otherwise
|
||||
*/
|
||||
public function __isset($name) {
|
||||
if (!array_key_exists($name, $this->propertyMap)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$property_name = $this->propertyMap[$name];
|
||||
return isset($this->threadInfo[$property_name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove thread from database
|
||||
*/
|
||||
public function delete() {
|
||||
$db = Database::getInstance();
|
||||
$db->query(
|
||||
"DELETE FROM {chatthread} WHERE threadid = :id LIMIT 1",
|
||||
array(':id' => $this->id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping the thread.
|
||||
*
|
||||
* Updates ping time for conversation members and sends messages about connection problems.
|
||||
*
|
||||
* @param boolean $is_user Indicates user or operator pings thread. Boolean true for user and boolean false
|
||||
* otherwise.
|
||||
* @param boolean $is_typing Indicates if user or operator is typing a message.
|
||||
*/
|
||||
public function ping($is_user, $is_typing) {
|
||||
// Last ping time of other side
|
||||
$last_ping_other_side = 0;
|
||||
// Update last ping time
|
||||
if ($is_user) {
|
||||
$last_ping_other_side = $this->lastPingAgent;
|
||||
$this->lastPingUser = time();
|
||||
$this->userTyping = $is_typing ? "1" : "0";
|
||||
} else {
|
||||
$last_ping_other_side = $this->lastPingUser;
|
||||
$this->lastPingAgent = time();
|
||||
$this->agentTyping = $is_typing ? "1" : "0";
|
||||
}
|
||||
|
||||
// Update thread state for the first user ping
|
||||
if ($this->state == self::STATE_LOADING && $is_user) {
|
||||
$this->state = self::STATE_QUEUE;
|
||||
$this->save();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if other side of the conversation have connection problems
|
||||
if ($last_ping_other_side > 0 && abs(time() - $last_ping_other_side) > self::CONNECTION_TIMEOUT) {
|
||||
// Connection problems detected
|
||||
if ($is_user) {
|
||||
// _Other_ side is operator
|
||||
// Update operator's last ping time
|
||||
$this->lastPingAgent = 0;
|
||||
|
||||
// Check if user chatting at the moment
|
||||
if ($this->state == self::STATE_CHATTING) {
|
||||
// Send message to user
|
||||
$message_to_post = getstring_("chat.status.operator.dead", $this->locale);
|
||||
$this->postMessage(
|
||||
self::KIND_CONN,
|
||||
$message_to_post,
|
||||
null,
|
||||
null,
|
||||
$last_ping_other_side + self::CONNECTION_TIMEOUT
|
||||
);
|
||||
|
||||
// And update thread
|
||||
$this->state = self::STATE_WAITING;
|
||||
$this->nextAgent = 0;
|
||||
}
|
||||
} else {
|
||||
// _Other_ side is user
|
||||
// Update user's last ping time
|
||||
$this->lastPingUser = 0;
|
||||
|
||||
// And send a message to operator
|
||||
$message_to_post = getstring_("chat.status.user.dead", $this->locale);
|
||||
$this->postMessage(
|
||||
self::KIND_FOR_AGENT,
|
||||
$message_to_post,
|
||||
null,
|
||||
null,
|
||||
$last_ping_other_side + self::CONNECTION_TIMEOUT
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the thread to the database
|
||||
*/
|
||||
public function save(){
|
||||
$db = Database::getInstance();
|
||||
|
||||
$query = "update {chatthread} t " .
|
||||
"set lrevision = ?, dtmmodified = ?";
|
||||
|
||||
$values = array();
|
||||
$values[] = $this->nextRevision();
|
||||
$values[] = time();
|
||||
|
||||
foreach ($this->updatedFields as $field_name) {
|
||||
$query .= ", {$field_name} = ?" ;
|
||||
$values[] = $this->threadInfo[$field_name];
|
||||
}
|
||||
|
||||
$query .= " where threadid = ?";
|
||||
$values[] = $this->id;
|
||||
$db->query($query, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if thread is reassigned for another operator
|
||||
*
|
||||
* Updates thread info, send events messages and avatar message to user
|
||||
* @global string $home_locale
|
||||
* @param array $operator Operator for test
|
||||
*/
|
||||
public function checkForReassign($operator) {
|
||||
global $home_locale;
|
||||
|
||||
$operator_name = ($this->locale == $home_locale) ? $operator['vclocalename'] : $operator['vccommonname'];
|
||||
|
||||
if ($this->state == self::STATE_WAITING &&
|
||||
($this->nextAgent == $operator['operatorid'] || $this->agentId == $operator['operatorid'])) {
|
||||
|
||||
// Prepare message
|
||||
if ($this->nextAgent == $operator['operatorid']) {
|
||||
$message_to_post = getstring2_(
|
||||
"chat.status.operator.changed",
|
||||
array($operator_name, $this->agentName),
|
||||
$this->locale
|
||||
);
|
||||
} else {
|
||||
$message_to_post = getstring2_("chat.status.operator.returned", array($operator_name), $this->locale);
|
||||
}
|
||||
|
||||
// Update thread info
|
||||
$this->state = self::STATE_CHATTING;
|
||||
$this->nextAgent = 0;
|
||||
$this->agentId = $operator['operatorid'];
|
||||
$this->agentName = $operator_name;
|
||||
$this->save();
|
||||
|
||||
// Send messages
|
||||
$this->postMessage(self::KIND_EVENTS, $message_to_post);
|
||||
$this->postMessage(self::KIND_AVATAR, $operator['vcavatar'] ? $operator['vcavatar'] : "");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load messages from database corresponding to the thread those ID's more than $lastid
|
||||
*
|
||||
* @param boolean $is_user Boolean TRUE if messages loads for user and boolean FALSE if they loads for operator.
|
||||
* @param int $lastid ID of the last loaded message.
|
||||
* @return array Array of messages
|
||||
* @see Thread::postMessage()
|
||||
*/
|
||||
public function getMessages($is_user, &$last_id) {
|
||||
|
||||
$db = Database::getInstance();
|
||||
|
||||
// Load messages
|
||||
$messages = $db->query(
|
||||
"select messageid,ikind,dtmcreated as created,tname,tmessage from {chatmessage} " .
|
||||
"where threadid = :threadid and messageid > :lastid " .
|
||||
($is_user ? "and ikind <> " . self::KIND_FOR_AGENT : "") .
|
||||
" order by messageid",
|
||||
array(
|
||||
':threadid' => $this->id,
|
||||
':lastid' => $last_id
|
||||
),
|
||||
array('return_rows' => Database::RETURN_ALL_ROWS)
|
||||
);
|
||||
|
||||
foreach ($messages as $msg) {
|
||||
// Get last message ID
|
||||
if ($msg['messageid'] > $last_id) {
|
||||
$last_id = $msg['messageid'];
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the messsage
|
||||
*
|
||||
* @param int $kind Message kind. One of the Thread::KIND_*
|
||||
* @param string $message Message body
|
||||
* @param string|null $from Sender name
|
||||
* @param int|null $opid operator id. Use NULL for system messages
|
||||
* @param int|null $time unix timestamp of the send time. Use NULL for current time.
|
||||
* @return int Message ID
|
||||
*
|
||||
* @see Thread::KIND_USER
|
||||
* @see Thread::KIND_AGENT
|
||||
* @see Thread::KIND_FOR_AGENT
|
||||
* @see Thread::KIND_INFO
|
||||
* @see Thread::KIND_CONN
|
||||
* @see Thread::KIND_EVENTS
|
||||
* @see Thread::KIND_AVATAR
|
||||
* @see Thread::getMessages()
|
||||
*/
|
||||
public function postMessage($kind, $message, $from = null, $opid = null, $time = null) {
|
||||
$db = Database::getInstance();
|
||||
|
||||
$query = "INSERT INTO {chatmessage} " .
|
||||
"(threadid,ikind,tmessage,tname,agentId,dtmcreated) " .
|
||||
"VALUES (:threadid,:kind,:message,:name,:agentid,:created)";
|
||||
|
||||
$values = array(
|
||||
':threadid' => $this->id,
|
||||
':kind' => $kind,
|
||||
':message' => $message,
|
||||
':name' => ($from ? $from : "null"),
|
||||
':agentid' => ($opid ? $opid : 0),
|
||||
':created' => ($time ? $time : time())
|
||||
);
|
||||
|
||||
$db->query($query, $values);
|
||||
return $db->insertedId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close thread and send closing messages to the conversation members
|
||||
*
|
||||
* @param boolean $is_user Boolean TRUE if user initiate thread closing or boolean FALSE otherwise
|
||||
*/
|
||||
public function close($is_user) {
|
||||
$db = Database::getInstance();
|
||||
|
||||
// Get messages count
|
||||
list($message_count) = $db->query(
|
||||
"SELECT COUNT(*) FROM {chatmessage} WHERE {chatmessage}.threadid = :threadid AND ikind = :kind_user",
|
||||
array(
|
||||
':threadid' => $this->id,
|
||||
':kind_user' => Thread::KIND_USER
|
||||
),
|
||||
array(
|
||||
'return_rows' => Database::RETURN_ONE_ROW,
|
||||
'fetch_type' => Database::FETCH_NUM
|
||||
)
|
||||
);
|
||||
|
||||
// Close thread if it's not already closed
|
||||
if ($this->state != self::STATE_CLOSED) {
|
||||
$this->state = self::STATE_CLOSED;
|
||||
$this->messageCount = $message_count;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
// Send message about closing
|
||||
$message = '';
|
||||
if ($is_user) {
|
||||
$message = getstring2_("chat.status.user.left", array($this->userName), $this->locale);
|
||||
} else {
|
||||
$message = getstring2_("chat.status.operator.left", array($this->agentName), $this->locale);
|
||||
}
|
||||
$this->postMessage(self::KIND_EVENTS, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign operator to thread
|
||||
*
|
||||
* @global string $home_locale
|
||||
* @param array $operator Operator who try to take thread
|
||||
* @return boolean Boolean TRUE on success or FALSE on failure
|
||||
*/
|
||||
public function take($operator) {
|
||||
global $home_locale;
|
||||
|
||||
$take_thread = false;
|
||||
$message = '';
|
||||
$operator_name = ($this->locale == $home_locale) ? $operator['vclocalename'] : $operator['vccommonname'];
|
||||
|
||||
if ($this->state == self::STATE_QUEUE || $this->state == self::STATE_WAITING || $this->state == self::STATE_LOADING) {
|
||||
// User waiting
|
||||
$take_thread = true;
|
||||
if ($this->state == self::STATE_WAITING) {
|
||||
if ($operator['operatorid'] != $this->agentId) {
|
||||
$message = getstring2_(
|
||||
"chat.status.operator.changed",
|
||||
array($operator_name, $this->agentName),
|
||||
$this->locale
|
||||
);
|
||||
} else {
|
||||
$message = getstring2_("chat.status.operator.returned", array($operator_name), $this->locale);
|
||||
}
|
||||
} else {
|
||||
$message = getstring2_("chat.status.operator.joined", array($operator_name), $this->locale);
|
||||
}
|
||||
} elseif ($this->state == self::STATE_CHATTING) {
|
||||
// User chatting
|
||||
if ($operator['operatorid'] != $this->agentId) {
|
||||
$take_thread = true;
|
||||
$message = getstring2_(
|
||||
"chat.status.operator.changed",
|
||||
array($operator_name, $this->agentName),
|
||||
$this->locale
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Thread closed
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change operator and update chat info
|
||||
if ($take_thread) {
|
||||
$this->state = self::STATE_CHATTING;
|
||||
$this->nextAgent = 0;
|
||||
$this->agentId = $operator['operatorid'];
|
||||
$this->agentName = $operator_name;
|
||||
if (empty($this->chatStarted)) {
|
||||
$this->chatStarted = time();
|
||||
}
|
||||
$this->save();
|
||||
}
|
||||
|
||||
// Send message
|
||||
if ($message) {
|
||||
$this->postMessage(self::KIND_EVENTS, $message);
|
||||
$this->postMessage(self::KIND_AVATAR, $operator['vcavatar'] ? $operator['vcavatar'] : "");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change user name in the conversation
|
||||
*
|
||||
* @param string $new_name New user name
|
||||
*/
|
||||
public function renameUser($new_name) {
|
||||
// Rename only if a new name is realy new
|
||||
if ($this->userName != $new_name) {
|
||||
// Rename user
|
||||
$this->userName = $new_name;
|
||||
$this->save();
|
||||
|
||||
// Send message about renaming
|
||||
$message = getstring2_(
|
||||
"chat.status.user.changedname",
|
||||
array($this->userName, $new_name),
|
||||
$this->locale
|
||||
);
|
||||
$this->postMessage(self::KIND_EVENTS, $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Loading…
Reference in New Issue
Block a user