���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home/alphpwcp/public_html/us/alphachat/lib/core/lhchat/lhchatworkflow.php
���ѧ٧ѧ�
<?php class erLhcoreClassChatWorkflow { /** * Message for timeout */ public static function timeoutWorkflow(erLhcoreClassModelChat & $chat) { $operator = $chat->auto_responder->auto_responder->operator; $name_support = $operator != '' ? $operator : erTranslationClassLhTranslation::getInstance()->getTranslation('chat/startchat','Live Support'); if (trim($chat->auto_responder->auto_responder->timeout_message) != '') { $msg = new erLhcoreClassModelmsg(); $msg->msg = erLhcoreClassGenericBotWorkflow::translateMessage(trim($chat->auto_responder->auto_responder->timeout_message), array('chat' => $chat, 'args' => ['chat' => $chat])); $msg->chat_id = $chat->id; $msg->name_support = $name_support; $msg->user_id = -2; $msg->time = time(); $msg->meta_msg = json_encode(['content' => ['auto_responder' => true]]); \LiveHelperChat\Models\Departments\UserDepAlias::getAlias(array('scope' => 'msg', 'msg' => & $msg, 'chat' => & $chat)); $msg->saveThis(); $chat->last_msg_id = $msg->id; $chat->updateThis(array('update' => array('last_msg_id'))); $originalValues = $msg->name_support . '_' .$msg->meta_msg . '_' . $msg->del_st; erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.before_auto_responder_msg_saved', array('no_auto_events' => true, 'ignore_times' => true,'msg' => & $msg, 'chat' => & $chat)); if ($originalValues != $msg->name_support . '_' . $msg->meta_msg . '_' . $msg->del_st) { $msg->saveThis(); } } $chat->auto_responder->auto_responder->getMeta($chat, 'pending_op', 1, array('override_nick' => $name_support, 'store_messages' => true)); } /** * Transfer workflow between departments * */ public static function transferWorkflow(erLhcoreClassModelChat & $chat, $params = array()) { $chat->transfer_if_na = 0; $chat->transfer_timeout_ts = time(); if ($chat->department !== false && ($departmentTransfer = $chat->department->department_transfer) !== false) { $botConfiguration = $chat->department->bot_configuration_array; $chat->dep_id = $departmentTransfer->id; $msg = new erLhcoreClassModelmsg(); if (isset($params['offline_operators']) && $params['offline_operators'] == true) { $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Transferred to').' "'.$departmentTransfer.'" '.erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','as no operators online in').' "'.$chat->department.'"'; } else { $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Chat was automatically transferred to').' "'.$departmentTransfer.'" '.erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','from').' "'.$chat->department.'"'; } $msg->chat_id = $chat->id; $msg->user_id = -1; $chat->last_user_msg_time = $msg->time = time(); erLhcoreClassChat::getSession()->save($msg); if ($chat->last_msg_id < $msg->id) { $chat->last_msg_id = $msg->id; } if ($departmentTransfer->inform_unread == 1) { $chat->reinform_timeout = $departmentTransfer->inform_unread_delay; $chat->unread_messages_informed = 0; } // Our new department also has a transfer rule // Check if further transfer is possible because of priority condition if ($departmentTransfer->department_transfer !== false && !(isset($departmentTransfer->bot_configuration_array['transfer_min_priority']) && is_numeric($departmentTransfer->bot_configuration_array['transfer_min_priority']) && (int)$departmentTransfer->bot_configuration_array['transfer_min_priority'] > $chat->priority)) { $chat->transfer_if_na = 1; $chat->transfer_timeout_ac = $departmentTransfer->transfer_timeout; } // Reset user on chat transfer to other department if required if (isset($botConfiguration['ru_on_transfer']) && $botConfiguration['ru_on_transfer'] == 1 && $chat->user_id > 0) { if ($chat->user_id > 0) { erLhcoreClassChat::updateActiveChats($chat->user_id); } $chat->user_id = 0; } if ($chat->department->nc_cb_execute == 1) { $chat->nc_cb_executed = 0; } erLhAbstractModelAutoResponder::updateAutoResponder($chat); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.data_changed_assigned_department',array('chat' => & $chat, 'from_dep' => $chat->department, 'to_dep' => $departmentTransfer)); $chat->updateThis(array('update' => array('dep_id','last_user_msg_time','last_msg_id','reinform_timeout','unread_messages_informed','user_id','na_cb_executed','transfer_if_na','transfer_timeout_ts','transfer_timeout_ac'))); } else { $chat->updateThis(array('update' => array('transfer_if_na','transfer_timeout_ts'))); } } public static function mainUnansweredChatWorkflow() { $output = ''; if ( erLhcoreClassModelChatConfig::fetch('run_unaswered_chat_workflow')->current_value > 0) { $output .= "Starting unaswered chats workflow\n"; $delay = time()-(erLhcoreClassModelChatConfig::fetch('run_unaswered_chat_workflow')->current_valu*60); foreach (erLhcoreClassChat::getList(array('limit' => 500, 'filterlt' => array('time' => $delay), 'filter' => array('status' => erLhcoreClassModelChat::STATUS_PENDING_CHAT, 'na_cb_executed' => 0))) as $chat) { erLhcoreClassChatWorkflow::unansweredChatWorkflow($chat); $output .= "executing unanswered callback for chat - ".$chat->id."\n"; } $output .= "Ended unaswered chats workflow\n"; } return $output; } /* * Chat was unanswered for n minits, execute callback. * */ public static function unansweredChatWorkflow(erLhcoreClassModelChat & $chat){ $chat->na_cb_executed = 1; $chat->updateThis(array('update' => array('na_cb_executed'))); // Execute callback if it exists $extensions = erConfigClassLhConfig::getInstance()->getOverrideValue( 'site', 'extensions' ); $instance = erLhcoreClassSystem::instance(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.unread_chat_workflow',array('chat' => & $chat)); foreach ($extensions as $ext) { $callbackFile = $instance->SiteDir . '/extension/' . $ext . '/callbacks/unanswered_chat.php'; if (file_exists($callbackFile)) { include $callbackFile; } } } public static function unreadInformWorkflow($options, & $chat) { $chat->unread_messages_informed = 1; $chat->updateThis(array('update' => array('unread_messages_informed'))); if (in_array('mail', $options['options'])) { erLhcoreClassChatMail::sendMailUnacceptedChat($chat,7); } if (in_array('xmp', $options['options'])) { $errors = array(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('xml.before_send_xmp_message', array('chat' => & $chat, 'errors' => & $errors)); if (empty($errors)) { erLhcoreClassXMP::sendXMPMessage($chat); } } erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.chat_unread_message',array('chat' => & $chat)); // Execute callback if it exists $extensions = erConfigClassLhConfig::getInstance()->getOverrideValue( 'site', 'extensions' ); $instance = erLhcoreClassSystem::instance(); foreach ($extensions as $ext) { $callbackFile = $instance->SiteDir . '/extension/' . $ext . '/callbacks/unread_message_chat.php'; if (file_exists($callbackFile)) { include $callbackFile; } } } public static function chatAcceptedWorkflow($options, & $chat) { if (in_array('mail_accepted', $options['options'])) { erLhcoreClassChatMail::sendMailUnacceptedChat($chat,9); } if (in_array('xmp_accepted', $options['options'])) { $errors = array(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('xml.before_send_xmp_message', array('chat' => & $chat, 'errors' => & $errors)); if (empty($errors)) { erLhcoreClassXMP::sendXMPMessage($chat, array('template' => 'xmp_accepted_message', 'recipients_setting' => 'xmp_users_accepted')); } } erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.chat_accepted',array('chat' => & $chat)); } public static function newChatInformWorkflow($options, & $chat) { $chat->nc_cb_executed = 1; $chat->updateThis(array('update' => array('nc_cb_executed'))); if (in_array('mail', $options['options'])) { erLhcoreClassChatMail::sendMailUnacceptedChat($chat); } if (in_array('xmp', $options['options'])) { $errors = array(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('xml.before_send_xmp_message', array('chat' => & $chat, 'errors' => & $errors)); if (empty($errors)) { erLhcoreClassXMP::sendXMPMessage($chat); } } erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.new_chat',array('chat' => & $chat)); // Execute callback if it exists $extensions = erConfigClassLhConfig::getInstance()->getOverrideValue( 'site', 'extensions' ); $instance = erLhcoreClassSystem::instance(); foreach ($extensions as $ext) { $callbackFile = $instance->SiteDir . '/extension/' . $ext . '/callbacks/new_chat.php'; if (file_exists($callbackFile)) { include $callbackFile; } } } public static function automaticChatClosing() { $closedChatsNumber = 0; $timeout = (int)erLhcoreClassModelChatConfig::fetch('autoclose_timeout')->current_value; if ($timeout > 0) { // Close normal chats $delay = time()-($timeout*60); foreach (erLhcoreClassChat::getList(array('limit' => 500,'filtergt' => array('last_user_msg_time' => 0), 'filterlt' => array('last_user_msg_time' => $delay), 'filter' => array('status' => erLhcoreClassModelChat::STATUS_ACTIVE_CHAT))) as $chat) { if ($chat->cls_us == 0) { $chat->cls_us = $chat->user_status_front + 1; } if (in_array($chat->status,[erLhcoreClassModelChat::STATUS_ACTIVE_CHAT,erLhcoreClassModelChat::STATUS_BOT_CHAT]) && $chat->auto_responder !== false) { $chat->auto_responder->chat = $chat; $chat->auto_responder->processClose(); } $chat->status = erLhcoreClassModelChat::STATUS_CLOSED_CHAT; $msg = new erLhcoreClassModelmsg(); $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Chat was closed by cron!'); $msg->meta_msg = json_encode(['content' => ['close_reason' => [ 'reason' => 'autoclose_timeout', 'last_user_msg_time' => $chat->last_user_msg_time, 'delay' => $delay ]]]); $msg->chat_id = $chat->id; $msg->user_id = -1; $chat->last_user_msg_time = $msg->time = time(); erLhcoreClassChat::getSession()->save($msg); if ($chat->last_msg_id < $msg->id) { $chat->last_msg_id = $msg->id; } if ($chat->wait_time == 0) { $chat->wait_time = time() - ($chat->pnd_time > 0 ? $chat->pnd_time : $chat->time); } \LiveHelperChat\Helpers\ChatDuration::setChatTimes($chat); $chat->cls_time = time(); $chat->has_unread_messages = 0; $chat->updateThis(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.auto_close',array('msg' => & $msg,'chat' => & $chat)); erLhcoreClassChat::closeChatCallback($chat, $chat->user); erLhcoreClassChat::updateActiveChats($chat->user_id); $closedChatsNumber++; } // Close pending chats where the only message is user initial message foreach (erLhcoreClassChat::getList(array('limit' => 500,'filterlt' => array('time' => $delay), 'filterin' => array('status' => array(erLhcoreClassModelChat::STATUS_PENDING_CHAT, erLhcoreClassModelChat::STATUS_ACTIVE_CHAT)),'filter' => array('last_user_msg_time' => 0))) as $chat) { if ($chat->cls_us == 0) { $chat->cls_us = $chat->user_status_front + 1; } if (in_array($chat->status,[erLhcoreClassModelChat::STATUS_ACTIVE_CHAT,erLhcoreClassModelChat::STATUS_BOT_CHAT]) && $chat->auto_responder !== false) { $chat->auto_responder->chat = $chat; $chat->auto_responder->processClose(); } $chat->status = erLhcoreClassModelChat::STATUS_CLOSED_CHAT; $msg = new erLhcoreClassModelmsg(); $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Chat was closed by cron!'); $msg->chat_id = $chat->id; $msg->user_id = -1; $msg->meta_msg = json_encode(['content' => ['close_reason' => [ 'reason' => 'autoclose_timeout_initial', 'delay' => $delay ]]]); $chat->last_user_msg_time = $msg->time = time(); erLhcoreClassChat::getSession()->save($msg); if ($chat->last_msg_id < $msg->id) { $chat->last_msg_id = $msg->id; } if ($chat->wait_time == 0) { $chat->wait_time = time() - ($chat->pnd_time > 0 ? $chat->pnd_time : $chat->time); } \LiveHelperChat\Helpers\ChatDuration::setChatTimes($chat); $chat->cls_time = time(); $chat->has_unread_messages = 0; $chat->updateThis(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.auto_close',array('msg' => & $msg,'chat' => & $chat)); erLhcoreClassChat::closeChatCallback($chat, $chat->user); erLhcoreClassChat::updateActiveChats($chat->user_id); $closedChatsNumber++; } } $timeout = (int)erLhcoreClassModelChatConfig::fetch('autoclose_timeout_pending')->current_value; if ($timeout > 0) { $delay = time()-($timeout*60); foreach (erLhcoreClassChat::getList(array('limit' => 500,'filterlt' => array('time' => $delay), 'filterin' => array('status' => array(erLhcoreClassModelChat::STATUS_PENDING_CHAT)))) as $chat) { if ($chat->cls_us == 0) { $chat->cls_us = $chat->user_status_front + 1; } $chat->status = erLhcoreClassModelChat::STATUS_CLOSED_CHAT; $msg = new erLhcoreClassModelmsg(); $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Chat was closed by cron!'); $msg->chat_id = $chat->id; $msg->user_id = -1; $msg->meta_msg = json_encode(['content' => ['close_reason' => [ 'reason' => 'autoclose_timeout_pending', 'delay' => $delay ]]]); $chat->last_user_msg_time = $msg->time = time(); erLhcoreClassChat::getSession()->save($msg); if ($chat->last_msg_id < $msg->id) { $chat->last_msg_id = $msg->id; } if ($chat->wait_time == 0) { $chat->wait_time = time() - ($chat->pnd_time > 0 ? $chat->pnd_time : $chat->time); } \LiveHelperChat\Helpers\ChatDuration::setChatTimes($chat); $chat->cls_time = time(); $chat->has_unread_messages = 0; $chat->updateThis(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.auto_close',array('msg' => & $msg,'chat' => & $chat)); erLhcoreClassChat::closeChatCallback($chat, $chat->user); erLhcoreClassChat::updateActiveChats($chat->user_id); $closedChatsNumber++; } } $timeout = (int)erLhcoreClassModelChatConfig::fetch('autoclose_timeout_active')->current_value; if ($timeout > 0) { $delay = time()-($timeout*60); foreach (erLhcoreClassChat::getList(array('limit' => 500,'filterlt' => array('time' => $delay), 'filterin' => array('status' => array(erLhcoreClassModelChat::STATUS_ACTIVE_CHAT)))) as $chat) { if ($chat->cls_us == 0) { $chat->cls_us = $chat->user_status_front + 1; } if (in_array($chat->status,[erLhcoreClassModelChat::STATUS_ACTIVE_CHAT,erLhcoreClassModelChat::STATUS_BOT_CHAT]) && $chat->auto_responder !== false) { $chat->auto_responder->chat = $chat; $chat->auto_responder->processClose(); } $chat->status = erLhcoreClassModelChat::STATUS_CLOSED_CHAT; $msg = new erLhcoreClassModelmsg(); $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Chat was closed by cron!'); $msg->chat_id = $chat->id; $msg->user_id = -1; $msg->meta_msg = json_encode(['content' => ['close_reason' => [ 'reason' => 'autoclose_timeout_active', 'delay' => $delay ]]]); $chat->last_user_msg_time = $msg->time = time(); erLhcoreClassChat::getSession()->save($msg); if ($chat->last_msg_id < $msg->id) { $chat->last_msg_id = $msg->id; } if ($chat->wait_time == 0) { $chat->wait_time = time() - ($chat->pnd_time > 0 ? $chat->pnd_time : $chat->time); } \LiveHelperChat\Helpers\ChatDuration::setChatTimes($chat); $chat->cls_time = time(); $chat->has_unread_messages = 0; $chat->updateThis(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.auto_close',array('msg' => & $msg,'chat' => & $chat)); erLhcoreClassChat::closeChatCallback($chat, $chat->user); erLhcoreClassChat::updateActiveChats($chat->user_id); $closedChatsNumber++; } } $timeout = (int)erLhcoreClassModelChatConfig::fetch('autoclose_timeout_bot')->current_value; if ($timeout > 0) { $delay = time()-($timeout*60); foreach (erLhcoreClassChat::getList(array('limit' => 500,'customfilter' => array('((last_user_msg_time = 0 AND time < ' . $delay . ') OR (last_user_msg_time > 0 AND last_user_msg_time < ' . $delay . '))'), 'filterin' => array('status' => array(erLhcoreClassModelChat::STATUS_BOT_CHAT)))) as $chat) { if ($chat->cls_us == 0) { $chat->cls_us = $chat->user_status_front + 1; } if (in_array($chat->status,[erLhcoreClassModelChat::STATUS_ACTIVE_CHAT,erLhcoreClassModelChat::STATUS_BOT_CHAT]) && $chat->auto_responder !== false) { $chat->auto_responder->chat = $chat; $chat->auto_responder->processClose(); } $chat->status = erLhcoreClassModelChat::STATUS_CLOSED_CHAT; $msg = new erLhcoreClassModelmsg(); $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Chat was closed by cron!'); $msg->chat_id = $chat->id; $msg->user_id = -1; $msg->meta_msg = json_encode(['content' => ['close_reason' => [ 'reason' => 'autoclose_timeout_bot', 'delay' => $delay, 'last_user_msg_time' => $chat->last_user_msg_time ]]]); $chat->last_user_msg_time = $msg->time = time(); erLhcoreClassChat::getSession()->save($msg); if ($chat->last_msg_id < $msg->id) { $chat->last_msg_id = $msg->id; } if ($chat->wait_time == 0) { $chat->pnd_time = time(); $chat->wait_time = 1; } \LiveHelperChat\Helpers\ChatDuration::setChatTimes($chat); $chat->cls_time = time(); $chat->has_unread_messages = 0; $chat->updateThis(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.auto_close',array('msg' => & $msg,'chat' => & $chat)); erLhcoreClassChat::closeChatCallback($chat, $chat->user); erLhcoreClassChat::updateActiveChats($chat->user_id); $closedChatsNumber++; } } $timeout = (int)erLhcoreClassModelChatConfig::fetch('autoclose_activity_timeout')->current_value; if ($timeout > 0) { $delay = time()-($timeout*60); foreach (erLhcoreClassChat::getList(array('limit' => 500, 'customfilter' => array('(( (last_user_msg_time = 0 AND last_op_msg_time = 0 AND time < ' . $delay . ') OR (last_user_msg_time > 0 AND last_user_msg_time >= last_op_msg_time AND last_user_msg_time < ' . $delay . ') OR (last_op_msg_time > 0 AND last_op_msg_time >= last_user_msg_time AND last_op_msg_time < ' . $delay . ') ) AND (GREATEST(`pnd_time`,`time`) + `wait_time`) < '.$delay.')'), 'filterin' => array('status' => array(erLhcoreClassModelChat::STATUS_ACTIVE_CHAT)))) as $chat) { if ($chat->cls_us == 0) { $chat->cls_us = $chat->user_status_front + 1; } if (in_array($chat->status,[erLhcoreClassModelChat::STATUS_ACTIVE_CHAT,erLhcoreClassModelChat::STATUS_BOT_CHAT]) && $chat->auto_responder !== false) { $chat->auto_responder->chat = $chat; $chat->auto_responder->processClose(); } $chat->status = erLhcoreClassModelChat::STATUS_CLOSED_CHAT; $msg = new erLhcoreClassModelmsg(); $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Chat was closed by cron because of inactivity!'); $msg->chat_id = $chat->id; $msg->user_id = -1; $msg->meta_msg = json_encode(['content' => ['close_reason' => [ 'reason' => 'autoclose_activity_timeout', 'delay' => $delay, 'last_user_msg_time' => $chat->last_user_msg_time, 'last_op_msg_time' => $chat->last_op_msg_time ]]]); $chat->last_user_msg_time = $msg->time = time(); erLhcoreClassChat::getSession()->save($msg); if ($chat->last_msg_id < $msg->id) { $chat->last_msg_id = $msg->id; } if ($chat->wait_time == 0) { $chat->wait_time = time() - ($chat->pnd_time > 0 ? $chat->pnd_time : $chat->time); } \LiveHelperChat\Helpers\ChatDuration::setChatTimes($chat); $chat->cls_time = time(); $chat->has_unread_messages = 0; $chat->updateThis(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.auto_close',array('msg' => & $msg,'chat' => & $chat)); erLhcoreClassChat::closeChatCallback($chat, $chat->user); erLhcoreClassChat::updateActiveChats($chat->user_id); $closedChatsNumber++; } } $timeoutParts = explode(',',str_replace(' ','',erLhcoreClassModelChatConfig::fetch('autoclose_abandon_pending')->current_value)); if ((int)$timeoutParts[0] > 0) { $delay = time()-((int)$timeoutParts[0]*60); $delayMobile = time()-((isset($timeoutParts[1]) && is_numeric($timeoutParts[1]) ? (int)$timeoutParts[1] : (int)$timeoutParts[0]) * 60); $closeActive = isset($timeoutParts[2]) && is_numeric($timeoutParts[2]) ? (int)$timeoutParts[2] : 0; if ($closeActive == 1) { $closeTypes = array( erLhcoreClassModelChat::STATUS_ACTIVE_CHAT ); } elseif ($closeActive == 2) { $closeTypes = array( erLhcoreClassModelChat::STATUS_PENDING_CHAT, erLhcoreClassModelChat::STATUS_ACTIVE_CHAT, ); } elseif ($closeActive == 3) { $closeTypes = array( erLhcoreClassModelChat::STATUS_PENDING_CHAT, erLhcoreClassModelChat::STATUS_BOT_CHAT, ); } elseif ($closeActive == 4) { $closeTypes = array( erLhcoreClassModelChat::STATUS_BOT_CHAT, ); } else { $closeTypes = array( erLhcoreClassModelChat::STATUS_PENDING_CHAT ); } $chatsToClose = erLhcoreClassChat::getList(array('limit' => 500, 'customfilter' => array('(`status_sub` IN ('. erLhcoreClassModelChat::STATUS_SUB_SURVEY_SHOW . ',' . erLhcoreClassModelChat::STATUS_SUB_USER_CLOSED_CHAT . ',' . erLhcoreClassModelChat::STATUS_SUB_SURVEY_COMPLETED . ',' . erLhcoreClassModelChat::STATUS_SUB_CONTACT_FORM . ') OR (`lsync` > 0 AND ((`lsync` < '. $delay .' AND `device_type` = 0) OR (`lsync` < '. $delayMobile .' AND `device_type` IN (1,2)))))'), 'filterin' => array('status' => $closeTypes))); $avoidCloseCallback = count($chatsToClose) == 500; foreach ($chatsToClose as $chat) { if ($chat->cls_us == 0) { $chat->cls_us = $chat->user_status_front + 1; } if (in_array($chat->status,[erLhcoreClassModelChat::STATUS_ACTIVE_CHAT,erLhcoreClassModelChat::STATUS_BOT_CHAT]) && $chat->auto_responder !== false) { $chat->auto_responder->chat = $chat; $chat->auto_responder->processClose(); } $statusOriginal = $chat->status; $chat->status = erLhcoreClassModelChat::STATUS_CLOSED_CHAT; $msg = new erLhcoreClassModelmsg(); if ($statusOriginal == erLhcoreClassModelChat::STATUS_BOT_CHAT) { $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Chat was closed by cron because visitor left the bot chat!'); } elseif ($statusOriginal == erLhcoreClassModelChat::STATUS_ACTIVE_CHAT){ $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Chat was closed by cron because visitor left the active chat!'); } else { $msg->msg = erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncuser','Chat was closed by cron because visitor left the pending chat!'); } $msg->chat_id = $chat->id; $msg->user_id = -1; $msg->meta_msg = json_encode(['content' => ['close_reason' => [ 'reason' => 'autoclose_activity_timeout', 'delay' => implode(',',$timeoutParts), 'lsync' => $chat->lsync ]]]); $chat->last_user_msg_time = $msg->time = time(); erLhcoreClassChat::getSession()->save($msg); if ($chat->last_msg_id < $msg->id) { $chat->last_msg_id = $msg->id; } if ($chat->wait_time == 0) { if ($statusOriginal == erLhcoreClassModelChat::STATUS_BOT_CHAT) { $chat->pnd_time = time(); $chat->wait_time = 1; } else { $chat->wait_time = time() - ($chat->pnd_time > 0 ? $chat->pnd_time : $chat->time); } } \LiveHelperChat\Helpers\ChatDuration::setChatTimes($chat); $chat->cls_time = time(); $chat->has_unread_messages = 0; $chat->updateThis(); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.auto_close',array('msg' => & $msg,'chat' => & $chat)); if (!$avoidCloseCallback) { erLhcoreClassChat::closeChatCallback($chat, $chat->user); } erLhcoreClassChat::updateActiveChats($chat->user_id); $closedChatsNumber++; } } return $closedChatsNumber; } public static function automaticChatPurge() { $purgedChatsNumber = 0; $timeout = (int)erLhcoreClassModelChatConfig::fetch('autopurge_timeout')->current_value; if ($timeout > 0) { $delay = time()-($timeout*60); foreach (erLhcoreClassChat::getList(array('limit' => 500,'filtergt' => array('last_user_msg_time' => 0), 'filterlt' => array('last_user_msg_time' => $delay), 'filter' => array('status' => erLhcoreClassModelChat::STATUS_CLOSED_CHAT))) as $chat) { $chat->removeThis(); erLhcoreClassChat::updateActiveChats($chat->user_id); if ($chat->department !== false) { erLhcoreClassChat::updateDepartmentStats($chat->department); } erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.delete', array( 'chat' => & $chat )); $purgedChatsNumber++; } } return $purgedChatsNumber; } public static function autoAssignMail(& $chat, $department, $params = array()) { $timestamp = time(); if (is_object($department) && $department->active_mail_balancing == 1 && ($department->max_ac_dep_mails == 0 || $department->active_mails_counter < $department->max_ac_dep_mails) && ($chat->user_id == 0 || ($department->max_timeout_seconds_mail > 0 && $chat->tslasign < $timestamp-$department->max_timeout_seconds_mail)) ){ $isOnlineUser = (int)erLhcoreClassModelChatConfig::fetch('sync_sound_settings')->data['online_timeout']; $db = ezcDbInstance::get(); try { $db->beginTransaction(); // Lock chat record for update untill we finish this procedure erLhcoreClassChat::lockDepartment($department->id, $db); if ($chat->status == erLhcoreClassModelMailconvConversation::STATUS_PENDING && ($chat->user_id == 0 || ($department->max_timeout_seconds_mail > 0 && $chat->tslasign < $timestamp-$department->max_timeout_seconds_mail))) { $condition = '(active_mails + pending_mails)'; if ($department->max_active_mails > 0) { $appendSQL = " AND ((max_mails = 0 AND {$condition} < :max_active_chats) OR (max_mails > 0 AND {$condition} < max_mails))"; } else { $appendSQL = " AND ((max_mails > 0 AND {$condition} < max_mails) OR (max_mails = 0))"; } if (!isset($params['include_ignored_users']) || $params['include_ignored_users'] == false) { $appendSQL .= " AND exclude_autoasign_mails = 0"; } // Allow limit by provided user_ids // Usefull for extension which has custom auto assign workflow if (isset($params['user_ids'])) { if (empty($params['user_ids'])) { $db->rollback(); return array('status' => erLhcoreClassChatEventDispatcher::STOP_WORKFLOW, 'user_id' => 0); } $appendSQL .= ' AND `lh_userdep`.`user_id` IN (' . implode(', ',$params['user_ids']) . ')'; } $sql = "SELECT user_id FROM lh_userdep WHERE last_accepted_mail < :last_accepted_mail AND ro = 0 AND hide_online = 0 AND dep_id = :dep_id AND (`lh_userdep`.`last_activity` > :last_activity OR `lh_userdep`.`always_on` = 1) AND user_id != :user_id {$appendSQL} ORDER BY last_accepted_mail ASC LIMIT 1"; $db = ezcDbInstance::get(); $stmt = $db->prepare($sql); $stmt->bindValue(':dep_id',$department->id,PDO::PARAM_INT); $stmt->bindValue(':last_activity',($timestamp-$isOnlineUser),PDO::PARAM_INT); $stmt->bindValue(':user_id',$chat->user_id,PDO::PARAM_INT); $stmt->bindValue(':last_accepted_mail',($timestamp - $department->delay_before_assign_mail),PDO::PARAM_INT); // if ($department->max_active_mails > 0) { $stmt->bindValue(':max_active_chats',$department->max_active_mails,PDO::PARAM_INT); } $stmt->execute(); $user_id = $stmt->fetchColumn(); if ($user_id > 0) { $previousMessage = ''; // Update previously assigned operator statistic if ($chat->user_id > 0) { erLhcoreClassChat::updateActiveChats($chat->user_id); $userOld = erLhcoreClassModelUser::fetch($chat->user_id); $previousMessage = '[' . $chat->user_id . '] ' . $userOld->name_support . ' '. erTranslationClassLhTranslation::getInstance()->getTranslation('chat/adminchat','did not accepted mail in time.') . ' '; } $chat->tslasign = $timestamp; $chat->user_id = $user_id; $chat->updateThis(array('update' => array('tslasign','user_id'))); erLhcoreClassUserDep::updateLastAcceptedByUser($user_id, $timestamp, '_mail'); // Update fresh user statistic erLhcoreClassChat::updateActiveChats($chat->user_id); $userData = erLhcoreClassModelUser::fetch($chat->user_id); erLhcoreClassMailconvWorkflow::logInteraction($previousMessage . $userData->name_support . ' [' . $userData->id.'] '.erTranslationClassLhTranslation::getInstance()->getTranslation('module/mailconv','was assigned as a mail owner from auto assignment workflow'), $userData->name_support, $chat->id); } } $db->commit(); } catch (Exception $e) { $db->rollback(); throw $e; } } } public static $lastError = ''; public static $lastSuccess = ''; public static function autoAssign(& $chat, $department, $params = array()) { $timestamp = time(); self::$lastError = ''; if (is_object($department) && $department->active_balancing == 1 && ($department->max_ac_dep_chats == 0 || $department->active_chats_counter < $department->max_ac_dep_chats) && ($chat->user_id == 0 || ($department->max_timeout_seconds > 0 && $chat->tslasign < $timestamp-$department->max_timeout_seconds))){ $isOnlineUser = (int)erLhcoreClassModelChatConfig::fetch('sync_sound_settings')->data['online_timeout']; $db = ezcDbInstance::get(); try { $botConfiguration = $department->bot_configuration_array; if ( isset($botConfiguration['auto_delay_var']) && $botConfiguration['auto_delay_var'] != '' && isset($botConfiguration['auto_delay_timeout']) && $botConfiguration['auto_delay_timeout'] > 0 && ($timestamp - $chat->time) < $botConfiguration['auto_delay_timeout'] ) { $valueToCompare = null; if (strpos($botConfiguration['auto_delay_var'],'additional_data') !== false) { $additionalDataArray = $chat->additional_data_array; if (is_array($additionalDataArray)) { foreach ($additionalDataArray as $additionalItem) { $valueCompare = false; if (isset($additionalItem['identifier'])){ $valueCompare = $additionalItem['identifier']; } elseif (isset($additionalItem['key'])){ $valueCompare = $additionalItem['key']; } if ($valueCompare !== false && $valueCompare == str_replace('additional_data.','',$botConfiguration['auto_delay_var'])) { $valueToCompare = $additionalItem['value']; break; } } } } elseif (strpos($botConfiguration['auto_delay_var'],'chat_variable') !== false) { $additionalDataArray = $chat->chat_variables_array; if (is_array($additionalDataArray)) { $variableName = str_replace('chat_variable.','', $botConfiguration['auto_delay_var']); if (isset($chat->chat_variables_array[$variableName]) && $chat->chat_variables_array[$variableName] != '') { $valueToCompare = $chat->chat_variables_array[$variableName]; } } } else { $statusWorkflowPermit = erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.workflow.autoassign_permit', array( 'department' => & $department, 'chat' => & $chat, 'params' => & $params, )); if ($statusWorkflowPermit !== false) { if (isset($statusWorkflowPermit['stop']) && $statusWorkflowPermit['stop'] == true) { $valueToCompare = true; } } } // Variable was not found ignore chat for a while if ($valueToCompare === null) { self::$lastError = 'Auto delay vars not satisfied'; return; } } $db->beginTransaction(); // Lock chat record for update untill we finish this procedure // Avoids any other chat in the same department to be assigned to the same operators // erLhcoreClassChat::lockDepartment($department->id, $db); // Skip everything if lock error happens if (!erLhcoreClassChat::lockOperatorsByDepartment($department->id, $db)){ self::$lastError = 'Locking operators failed'; $db->rollback(); return; } if ($chat->status == erLhcoreClassModelChat::STATUS_PENDING_CHAT && ($chat->user_id == 0 || ($department->max_timeout_seconds > 0 && $chat->tslasign < $timestamp-$department->max_timeout_seconds))) { $statusWorkflow = erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.workflow.autoassign', array( 'department' => & $department, 'chat' => & $chat, 'is_online' => & $isOnlineUser, 'params' => & $params, )); // There was no callbacks or file not found etc, we try to download from standard location if ($statusWorkflow === false) { $condition = '(active_chats + pending_chats)'; if ($department->exclude_inactive_chats == 1) { $condition = '((pending_chats + active_chats) - inactive_chats)'; } if ($department->max_active_chats > 0) { $appendSQL = " AND ((max_chats = 0 AND {$condition} < :max_active_chats) OR (max_chats > 0 AND {$condition} < max_chats))"; } else { $appendSQL = " AND ((max_chats > 0 AND {$condition} < max_chats) OR (max_chats = 0))"; } if (!isset($params['include_ignored_users']) || $params['include_ignored_users'] == false) { $appendSQL .= " AND exclude_autoasign = 0 AND exc_indv_autoasign = 0"; } // Allow limit by provided user_ids // Usefull for extension which has custom auto assign workflow if (isset($params['user_ids'])) { if (empty($params['user_ids'])) { self::$lastError = 'user_ids not set'; $db->rollback(); return array('status' => erLhcoreClassChatEventDispatcher::STOP_WORKFLOW, 'user_id' => 0); } $appendSQL .= ' AND `lh_userdep`.`user_id` IN (' . implode(', ',$params['user_ids']) . ')'; } $sort = 'last_accepted ASC'; if (isset($botConfiguration['auto_lower_limit']) && $botConfiguration['auto_lower_limit'] == '1') { $sort = 'active_chats ASC, last_accepted ASC'; } if (isset($botConfiguration['assign_by_priority']) && $botConfiguration['assign_by_priority'] == '1') { $sort = 'assign_priority DESC, '.$sort; } $sql = "SELECT `lh_userdep`.`user_id`, `lh_userdep`.`last_accepted`, `lh_userdep`.`pending_chats`, `lh_userdep`.`active_chats`, `lh_userdep`.`inactive_chats` FROM lh_userdep WHERE last_accepted < :last_accepted AND ro = 0 AND hide_online = 0 AND dep_id = :dep_id AND (`lh_userdep`.`last_activity` > :last_activity OR `lh_userdep`.`always_on` = 1) AND user_id != :user_id {$appendSQL} ORDER BY {$sort} LIMIT 3"; self::$lastSuccess = $sql; $paramsFilterLog = []; $tryDefault = true; $byPriority = false; // Priority assignment workflow if (isset($botConfiguration['assign_by_priority_chat']) && $botConfiguration['assign_by_priority_chat'] == '1'&& !(isset($botConfiguration['min_chat_priority']) && (int)$botConfiguration['min_chat_priority'] != 0 && (int)$chat->priority < (int)$botConfiguration['min_chat_priority']) && !(isset($botConfiguration['max_chat_priority']) && (int)$botConfiguration['max_chat_priority'] != 0 && (int)$chat->priority > (int)$botConfiguration['max_chat_priority']) ) { $sortPriority = 'last_accepted ASC'; if (isset($botConfiguration['auto_lower_limit']) && $botConfiguration['auto_lower_limit'] == '1') { $sortPriority = 'active_chats ASC, last_accepted ASC'; } if (isset($botConfiguration['assign_by_priority_chat']) && $botConfiguration['assign_by_priority_chat'] == '1') { $sortPriority = 'assign_priority DESC,' . $sortPriority; } $appendSQLPriority = $appendSQL; if (isset($botConfiguration['min_agent_priority']) && (int)$botConfiguration['min_agent_priority'] != 0) { $appendSQLPriority .= ' AND assign_priority >= ' . (int)$botConfiguration['min_agent_priority']; } $appendSQLPriority .= ' AND (chat_max_priority = 0 OR chat_max_priority >= ' . (int)$chat->priority .') AND (chat_min_priority = 0 OR chat_min_priority <= ' . (int)$chat->priority .')'; $db = ezcDbInstance::get(); $sqlPriority = "SELECT `lh_userdep`.`user_id`, `lh_userdep`.`last_accepted`, `lh_userdep`.`pending_chats`, `lh_userdep`.`active_chats`, `lh_userdep`.`inactive_chats` FROM lh_userdep WHERE last_accepted < :last_accepted AND ro = 0 AND hide_online = 0 AND dep_id = :dep_id AND (`lh_userdep`.`last_activity` > :last_activity OR `lh_userdep`.`always_on` = 1) AND `lh_userdep`.`user_id` != :user_id {$appendSQLPriority} ORDER BY {$sortPriority} LIMIT 3"; self::$lastSuccess = $sqlPriority; $stmt = $db->prepare($sqlPriority); $stmt->bindValue(':dep_id',$department->id,PDO::PARAM_INT); $stmt->bindValue(':last_activity',($timestamp - $isOnlineUser),PDO::PARAM_INT); $stmt->bindValue(':user_id',$chat->user_id,PDO::PARAM_INT); $stmt->bindValue(':last_accepted',($timestamp - $department->delay_before_assign),PDO::PARAM_INT); $paramsFilterLog = [ 'last_activity' => ($timestamp - $isOnlineUser), 'user_id' => $chat->user_id, 'last_accepted' => ($timestamp - $department->delay_before_assign), ]; if ($department->max_active_chats > 0) { $paramsFilterLog['max_active_chats'] = $department->max_active_chats; $stmt->bindValue(':max_active_chats',$department->max_active_chats,PDO::PARAM_INT); } $stmt->execute(); $dataFetch = $stmt->fetch(PDO::FETCH_ASSOC); $user_id = $dataFetch['user_id'] ?? 0; if (is_numeric($user_id) && $user_id > 0) { $tryDefault = false; $byPriority = true; } } // Try to assign to operator speaking same language first if ($tryDefault == true && $department->assign_same_language == 1 && $chat->chat_locale != '') { $sqlLanguages = "SELECT `lh_userdep`.`user_id`, `lh_userdep`.`last_accepted`, `lh_userdep`.`pending_chats`, `lh_userdep`.`active_chats`, `lh_userdep`.`inactive_chats` FROM lh_userdep INNER JOIN lh_speech_user_language ON `lh_speech_user_language`.`user_id` = `lh_userdep`.`user_id` WHERE last_accepted < :last_accepted AND ro = 0 AND hide_online = 0 AND dep_id = :dep_id AND (`lh_userdep`.`last_activity` > :last_activity OR `lh_userdep`.`always_on` = 1) AND `lh_userdep`.`user_id` != :user_id AND `lh_speech_user_language`.`language` = :chatlanguage {$appendSQL} ORDER BY {$sort} LIMIT 3"; self::$lastSuccess = $sqlLanguages; $db = ezcDbInstance::get(); $stmt = $db->prepare($sqlLanguages); $stmt->bindValue(':dep_id',$department->id,PDO::PARAM_INT); $stmt->bindValue(':last_activity',($timestamp-$isOnlineUser),PDO::PARAM_INT); $stmt->bindValue(':user_id',$chat->user_id,PDO::PARAM_INT); $stmt->bindValue(':last_accepted',($timestamp - $department->delay_before_assign),PDO::PARAM_INT); $stmt->bindValue(':chatlanguage',$chat->chat_locale,PDO::PARAM_STR); $paramsFilterLog = [ 'last_activity' => ($timestamp - $isOnlineUser), 'user_id' => $chat->user_id, 'last_accepted' => ($timestamp - $department->delay_before_assign), 'chatlanguage' => $chat->chat_locale, ]; if ($department->max_active_chats > 0) { $paramsFilterLog['max_active_chats'] = $department->max_active_chats; $stmt->bindValue(':max_active_chats',$department->max_active_chats,PDO::PARAM_INT); } $stmt->execute(); $dataFetch = $stmt->fetch(PDO::FETCH_ASSOC); $user_id = $dataFetch['user_id'] ?? 0; if (is_numeric($user_id) && $user_id > 0) { $tryDefault = false; } } if ($tryDefault == true) { self::$lastSuccess = $sql; $db = ezcDbInstance::get(); $stmt = $db->prepare($sql); $stmt->bindValue(':dep_id',$department->id,PDO::PARAM_INT); $stmt->bindValue(':last_activity',($timestamp-$isOnlineUser),PDO::PARAM_INT); $stmt->bindValue(':user_id',$chat->user_id,PDO::PARAM_INT); $stmt->bindValue(':last_accepted',($timestamp - $department->delay_before_assign),PDO::PARAM_INT); $paramsFilterLog = [ 'last_activity' => ($timestamp - $isOnlineUser), 'user_id' => $chat->user_id, 'last_accepted' => ($timestamp - $department->delay_before_assign) ]; if ($department->max_active_chats > 0) { $paramsFilterLog['max_active_chats'] = $department->max_active_chats; $stmt->bindValue(':max_active_chats',$department->max_active_chats,PDO::PARAM_INT); } $stmt->execute(); $dataFetch = $stmt->fetch(PDO::FETCH_ASSOC); $user_id = $dataFetch['user_id'] ?? 0; } } else { $db = ezcDbInstance::get(); $user_id = $statusWorkflow['user_id']; } if ($user_id > 0) { $previousMessage = ''; $msg = new erLhcoreClassModelmsg(); $msg->chat_id = $chat->id; $msg->user_id = -1; $msg->time = $timestamp; // Update previously assigned operator statistic if ($chat->user_id > 0) { $userOld = erLhcoreClassModelUser::fetch($chat->user_id); $msg->name_support = $userOld->name_support; erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.before_msg_user_saved', array('msg' => & $msg, 'chat' => & $chat, 'user_id' => $chat->user_id)); $previousMessage = '[' . $chat->user_id . '] ' . $msg->name_support . ' '. erTranslationClassLhTranslation::getInstance()->getTranslation('chat/adminchat','did not accepted chat in time.') . ' '; erLhcoreClassChat::updateActiveChats($chat->user_id); } $userNew = erLhcoreClassModelUser::fetch($user_id); $msg->name_support = $userNew->name_support; erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.before_msg_user_saved', array('msg' => & $msg, 'chat' => & $chat, 'user_id' => $user_id)); $msg->msg = $previousMessage . erTranslationClassLhTranslation::getInstance()->getTranslation('chat/adminchat','Chat was assigned to') . ' [' . $userNew->id .'] ' . (isset($byPriority) && $byPriority === true ? '[' . $chat->priority . '] ' : '') . (isset($byPriority) && $byPriority === false && isset($tryDefault) && $tryDefault === false ? '[' . $chat->chat_locale . '] ' : '') . $msg->name_support; erLhcoreClassChat::getSession()->save($msg); // Set owner to a new user $chat->tslasign = $timestamp; $chat->user_id = $user_id; $chat->last_msg_id = $msg->id; $chat->updateThis(array('update' => array('last_msg_id','tslasign','user_id'))); $successLastAccepted = erLhcoreClassUserDep::updateLastAcceptedByUser($user_id, $timestamp); // Update fresh user statistic $successActiveChats = erLhcoreClassChat::updateActiveChats($chat->user_id); if ($dataFetch) { self::$lastSuccess .= "\n" . json_encode($dataFetch); $nextOperator = []; if (is_object($stmt)) { $nextOperatorRaw = $stmt->fetchAll(PDO::FETCH_ASSOC); // Next operator is the same if (isset($nextOperatorRaw[0]['user_id']) && $nextOperatorRaw[0]['user_id'] == $chat->user_id && isset($nextOperatorRaw[1]['user_id'])) { $nextOperator = $nextOperatorRaw[1]; } elseif (isset($nextOperatorRaw[0]['user_id']) && $nextOperatorRaw[0]['user_id'] != $chat->user_id) { $nextOperator = $nextOperatorRaw[0]; } else { $nextOperator = null; } self::$lastSuccess .= "\nNEXT OP - " . json_encode($nextOperatorRaw); } if (isset($paramsFilterLog)) { self::$lastSuccess .= "\nFILTER - " . json_encode($paramsFilterLog); } $meta_msg_array = ['content' => ['assign_action' => $dataFetch]]; $meta_msg_array['content']['assign_action']['assign_finished'] = time(); $meta_msg_array['content']['assign_action']['sac'] = $successActiveChats; $meta_msg_array['content']['assign_action']['sla'] = $successLastAccepted; $meta_msg_array['content']['assign_action']['next_op'] = $nextOperator; $msg->meta_msg = json_encode($meta_msg_array); $msg->updateThis(['update' => ['meta_msg']]); } } else { self::$lastError = 'Online operator was not found!'; } } if (isset($user_id) && $user_id > 0) { erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.data_changed_auto_assign',array('chat' => & $chat)); } $db->commit(); } catch (Exception $e) { $db->rollback(); throw $e; } } else { if (is_object($department)) { self::$lastError = $department->active_balancing ."== 1 && (" . $department->max_ac_dep_chats . " == 0 || " . $department->active_chats_counter . "<" . $department->max_ac_dep_chats . ") && (" . $chat->user_id . "== 0 || (" . $department->max_timeout_seconds ." > 0 && " . $chat->tslasign ." < ". $timestamp . "- " . $department->max_timeout_seconds ."))"; } } if (isset($user_id) && $user_id > 0) { return true; } } public static function presendCannedMsg($chat) { $statusWorkflow = erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.workflow.presend_canned_msg', array( 'chat' => & $chat, )); if ($statusWorkflow === false) { $session = erLhcoreClassChat::getSession(); $q = $session->createFindQuery( 'erLhcoreClassModelCannedMsg' ); $q->where( $q->expr->lOr( $q->expr->eq( 'department_id', $q->bindValue($chat->dep_id) ), $q->expr->lAnd($q->expr->eq( 'department_id', $q->bindValue( 0 ) ),$q->expr->eq( 'user_id', $q->bindValue( 0 ) )), $q->expr->eq( 'user_id', $q->bindValue($chat->user_id) ) ), $q->expr->eq( 'auto_send', $q->bindValue(1) ) ); $q->limit(1, 0); $q->orderBy('user_id DESC, position ASC, id ASC' ); // Questions with matched URL has higher priority $items = $session->find( $q ); } else { $items = $statusWorkflow['items']; } if (!empty($items)){ $cannedMsg = array_shift($items); $replaceArray = array( '{nick}' => $chat->nick, '{email}' => $chat->email, '{phone}' => $chat->phone, '{operator}' => (string)$chat->user->name_support ); $additionalData = $chat->additional_data_array; if (is_array($additionalData)) { foreach ($additionalData as $row) { if (isset($row['identifier']) && $row['identifier'] != '') { $replaceArray['{'.$row['identifier'].'}'] = $row['value']; } } } $items = array($cannedMsg); \LiveHelperChat\Models\Departments\UserDepAlias::getAlias(array('scope' => 'canned_replace', 'replace_array' => & $replaceArray, 'user' => $chat->user, 'chat' => $chat)); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.workflow.canned_message_replace',array('items' => & $items, 'user' => $chat->user, 'chat' => $chat, 'replace_array' => & $replaceArray)); $cannedMsg = $items[0]; // Set proper message by language $cannedMsg->setMessageByChatLocale($chat->chat_locale); $replaceCustomArgs = []; foreach (['msg','fallback_msg'] as $metaMsg) { $matchesMessage = []; preg_match_all('/\{[A-Za-z0-9\_]+\}/is',$cannedMsg->{$metaMsg}, $matchesMessage); if (isset($matchesMessage[0]) && !empty($matchesMessage[0])) { foreach ($matchesMessage[0] as $replaceItem) { if (key_exists($replaceItem,$replaceArray) == false) { $replaceCustomArgs[] = $replaceItem; } } } } $replaceCustomArgs = array_unique($replaceCustomArgs); if (!empty($replaceCustomArgs)) { $identifiers = []; $identifiersApplied = []; foreach ($replaceCustomArgs as $replaceArg) { $identifiers[] = str_replace(['{','}'],'', $replaceArg); } $replaceRules = erLhcoreClassModelCannedMsgReplace::getList(array( 'sort' => 'repetitiveness DESC', // Default translation will be the last one if more than one same identifier is found 'limit' => false, 'filterin' => array('identifier' => $identifiers)) ); foreach ($replaceRules as $replaceRule) { if ($replaceRule->is_active && !in_array($replaceRule->identifier,$identifiersApplied)) { $replaceArray['{' . $replaceRule->identifier . '}'] = $replaceRule->getValueReplace(['chat' => $chat, 'user' => $chat->user]); $identifiersApplied[] = $replaceRule->identifier; } } } $cannedMsg->setReplaceData($replaceArray); if (strpos($cannedMsg->msg, '{args.') !== false) { $matchesValues = array(); preg_match_all('~\{args\.((?:[^\{\}\}]++|(?R))*)\}~', $cannedMsg->msg, $matchesValues); if (!empty($matchesValues[0])) { foreach ($matchesValues[0] as $indexElement => $elementValue) { $valueAttribute = erLhcoreClassGenericBotActionRestapi::extractAttribute(array('user' => $cannedMsg->user, 'chat' => $chat), $matchesValues[1][$indexElement], '.'); $cannedMsg->msg = str_replace($elementValue, $valueAttribute['found'] == true ? $valueAttribute['value'] : '', $cannedMsg->msg); } } } $msg = new erLhcoreClassModelmsg(); $msg->msg = $cannedMsg->msg_to_user; if (strpos($msg->msg,'[html]') !== false && !erLhcoreClassUser::instance()->hasAccessTo('lhchat','htmlbbcodeenabled')) { $msg->msg = '[html] is disabled for you!'; $msg->user_id = -1; } $msg->chat_id = $chat->id; $msg->user_id = $chat->user_id; $msg->name_support = $chat->user->name_support; $chat->last_op_msg_time = $chat->last_user_msg_time = $msg->time = time(); $chat->has_unread_op_messages = 1; $chat->unread_op_messages_informed = 0; \LiveHelperChat\Models\Departments\UserDepAlias::getAlias(array('scope' => 'msg', 'msg' => & $msg, 'chat' => & $chat)); erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.workflow.canned_message_before_save',array('msg' => & $msg, 'chat' => & $chat)); erLhcoreClassChat::getSession()->save($msg); if ($chat->last_msg_id < $msg->id) { $chat->last_msg_id = $msg->id; } $chat->updateThis(array('update' => array( 'last_op_msg_time', 'last_user_msg_time', 'has_unread_op_messages', 'unread_op_messages_informed', 'last_msg_id' ))); } } public static function autoInformVisitor($minutesTimeout) { if ($minutesTimeout > 0) { $items = erLhcoreClassChat::getList(array('limit' => 10, 'filterlt' => array('last_op_msg_time' => (time() - (1*60))), 'filter' => array('has_unread_op_messages' => 1, 'unread_op_messages_informed' => 0))); // Update chats instantly foreach ($items as $item) { $item->has_unread_op_messages = 0; $item->unread_op_messages_informed = 1; $item->updateThis(array('update' => array('has_unread_op_messages','unread_op_messages_informed'))); } // Now inform visitors foreach ($items as $item) { erLhcoreClassChatMail::informVisitorUnreadMessage($item); } } } public static function getChatHistory($chat, $lastMessageId) { $messages = erLhcoreClassChat::getChatMessages($chat->id, erLhcoreClassChat::$limitMessages, $lastMessageId); $chatMessages = $chat->id; $messageId = 0; $hasMessages = true; if (count($messages) == erLhcoreClassChat::$limitMessages) { reset($messages); $message = current($messages); $messageId = $message['id']; } else { $hasMessages = false; $statusWorkflow = erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.workflow.get_chat_history', array( 'chat' => $chat, 'last_message_id' => $lastMessageId, )); if ($statusWorkflow === false) { if (erLhcoreClassUser::instance()->hasAccessTo('lhchat','prev_chats') && ($online_user = $chat->online_user) !== false) { $chatHistory = erLhcoreClassModelChat::findOne(array('sort' => 'id DESC','filterlt' => array('id' => $chat->id), 'filter' => array('online_user_id' => $online_user->id))); if ($chatHistory instanceof erLhcoreClassModelChat) { $chat = $chatHistory; $hasMessages = true; } } } else { $hasMessages = $statusWorkflow['has_messages']; $chat = $statusWorkflow['chat']; } } return array( 'chat_id' => (is_object($chat) ? $chat->id : null), 'chat' => (is_object($chat) ? $chat : null), 'last_message_chat_id' => $chatMessages, 'message_id' => $messageId, 'messages' => $messages, 'has_messages' => $hasMessages ); } public static function hasPreviousChats($params) { reset($params['messages']); $firstMessage = current($params['messages']); $chatHistory = $params['chat']; $hasMessages = erLhcoreClassChat::$limitMessages == count($params['messages']); $firstMessageId = $firstMessage['id']; $params['has_messages'] = $hasMessages; $statusWorkflow = erLhcoreClassChatEventDispatcher::getInstance()->dispatch('chat.workflow.has_previous_messages', $params); if ($statusWorkflow === false) { if ($hasMessages == false && erLhcoreClassUser::instance()->hasAccessTo('lhchat','prev_chats') && ($online_user = $params['chat']->online_user) !== false) { $chatHistory = erLhcoreClassModelChat::findOne(array('sort' => 'id DESC','filterlt' => array('id' => $params['chat']->id), 'filter' => array('online_user_id' => $online_user->id))); if ($chatHistory instanceof erLhcoreClassModelChat) { $hasMessages = true; $firstMessageId = 0; } } return array( 'has_messages' => $hasMessages, 'chat_history' => $chatHistory, 'message_id' => $firstMessageId ); } else { return $statusWorkflow; } } } ?>
| ver. 1.4 |
Github
|
.
| PHP 8.2.30 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�