Your IP : 18.188.125.151
<?php
namespace Bitrix\ImOpenLines;
use \Bitrix\Main,
\Bitrix\Main\Event,
\Bitrix\Main\Type\DateTime,
\Bitrix\Main\Localization\Loc;
use \Bitrix\Im\User as ImUser,
\Bitrix\Im\Model\ChatTable;
use \Bitrix\Pull;
use \Bitrix\Im\Model\RelationTable,
\Bitrix\ImOpenLines\Tools\DbNameLock,
\Bitrix\ImOpenlines\Model\ConfigTable,
\Bitrix\ImOpenLines\Model\OperatorTransferTable;
Loc::loadMessages(__FILE__);
class Chat
{
const FIELD_SESSION = 'LINES_SESSION';
const FIELD_CRM = 'LINES_CRM';
const FIELD_LIVECHAT = 'LIVECHAT_SESSION';
const FIELD_SILENT_MODE = 'LINES_SILENT_MODE';
const RATING_TYPE_CLIENT = 'CLIENT';
const RATING_TYPE_HEAD = 'HEAD';
const RATING_TYPE_COMMENT = 'COMMENT';
const RATING_TYPE_HEAD_AND_COMMENT = 'HEAD_AND_COMMENT';
const RATING_VALUE_LIKE = '5';
const RATING_VALUE_DISLIKE = '1';
public static $fieldAssoc = Array(
'LINES_SESSION' => 'ENTITY_DATA_1',
'LINES_CRM' => 'ENTITY_DATA_2',
'LIVECHAT_SESSION' => 'ENTITY_DATA_1',
);
const TRANSFER_MODE_AUTO = 'AUTO';
const TRANSFER_MODE_MANUAL = 'MANUAL';
const TRANSFER_MODE_BOT = 'BOT';
const TEXT_WELCOME = 'WELCOME';
const TEXT_DEFAULT = 'DEFAULT';
const CHAT_TYPE_OPERATOR = 'LINES';
const CHAT_TYPE_CLIENT = 'LIVECHAT';
private $error = null;
private $moduleLoad = false;
private $isCreated = false;
private $isDataLoaded = false;
private $joinByUserId = 0;
private $chat = [];
const IMOL_CRM_ERROR_NOT_GIVEN_CORRECT_DATA = 'IMOL CRM ERROR NOT GIVEN THE CORRECT DATA';
public const PREFIX_KEY_LOCK_NEW_SESSION = 'imol_start_session_by_message_chat_id_';
public const PREFIX_KEY_LOCK_ANSWER_SESSION = 'imol_answer_session_chat_id_';
public function __construct($chatId = 0, $params = Array())
{
$imLoad = \Bitrix\Main\Loader::includeModule('im');
$pullLoad = \Bitrix\Main\Loader::includeModule('pull');
if ($imLoad && $pullLoad)
{
$this->error = new BasicError(null, '', '');
$this->moduleLoad = true;
}
else
{
if (!$imLoad)
{
$this->error = new BasicError(__METHOD__, 'IM_LOAD_ERROR', Loc::getMessage('IMOL_CHAT_ERROR_IM_LOAD'));
}
elseif (!$pullLoad)
{
$this->error = new BasicError(__METHOD__, 'PULL_LOAD_ERROR', Loc::getMessage('IMOL_CHAT_ERROR_PULL_LOAD'));
}
}
if ($imLoad)
{
$chatId = intval($chatId);
if ($chatId > 0)
{
$chat = \Bitrix\Im\Model\ChatTable::getById($chatId)->fetch();
if (!empty($chat) && in_array($chat['ENTITY_TYPE'], Array(self::CHAT_TYPE_OPERATOR, self::CHAT_TYPE_CLIENT)))
{
if (isset($params['CONNECTOR']['chat']['description']) && $chat['DESCRIPTION'] != $params['CONNECTOR']['chat']['description'])
{
$chatManager = new \CIMChat(0);
$chatManager->SetDescription($chat['ID'], $params['CONNECTOR']['chat']['description']);
$chat['DESCRIPTION'] = $params['CONNECTOR']['chat']['description'];
}
$this->chat = $chat;
$this->isDataLoaded = true;
}
}
}
}
private function isModuleLoad()
{
return $this->moduleLoad;
}
public function load($params)
{
if (!$this->isModuleLoad())
{
return false;
}
$orm = \Bitrix\Im\Model\ChatTable::getList(array(
'filter' => array(
'=ENTITY_TYPE' => 'LINES',
'=ENTITY_ID' => $params['USER_CODE']
),
'limit' => 1
));
if($chat = $orm->fetch())
{
if (isset($params['CONNECTOR']['chat']['description']) && $chat['DESCRIPTION'] != $params['CONNECTOR']['chat']['description'])
{
$chatManager = new \CIMChat(0);
$chatManager->SetDescription($chat['ID'], $params['CONNECTOR']['chat']['description']);
$chat['DESCRIPTION'] = $params['CONNECTOR']['chat']['description'];
}
$this->chat = $chat;
$this->isDataLoaded = true;
return true;
}
else if ($params['ONLY_LOAD'] == 'Y')
{
return false;
}
$parsedUserCode = Session\Common::parseUserCode($params['USER_CODE']);
$connectorId = $parsedUserCode['CONNECTOR_ID'];
$avatarId = 0;
$userName = '';
$chatColorCode = '';
$addChat['USERS'] = false;
if ($params['USER_ID'])
{
$orm = \Bitrix\Main\UserTable::getById($params['USER_ID']);
if ($user = $orm->fetch())
{
if ($user['PERSONAL_PHOTO'] > 0)
{
$avatarId = $user['PERSONAL_PHOTO'];
}
$addChat['USERS'] = Array($params['USER_ID']);
if ($connectorId != 'livechat' || !empty($user['NAME']))
{
$userName = ImUser::getInstance($params['USER_ID'])->getFullName(false);
}
$chatColorCode = \Bitrix\Im\Color::getCodeByNumber($params['USER_ID']);
if (ImUser::getInstance($params['USER_ID'])->getGender() == 'M')
{
$replaceColor = \Bitrix\Im\Color::getReplaceColors();
if (isset($replaceColor[$chatColorCode]))
{
$chatColorCode = $replaceColor[$chatColorCode];
}
}
}
}
$description = '';
if (isset($params['CONNECTOR']['chat']['description']))
{
$description = trim($params['CONNECTOR']['chat']['description']);
}
$titleParams = $this->getTitle($params['LINE_NAME'], $userName, $chatColorCode);
$addChat['TYPE'] = IM_MESSAGE_OPEN_LINE;
$addChat['AVATAR_ID'] = $avatarId;
$addChat['TITLE'] = $titleParams['TITLE'];
$addChat['COLOR'] = $titleParams['COLOR'];
$addChat['DESCRIPTION'] = $description;
$addChat['ENTITY_TYPE'] = 'LINES';
$addChat['ENTITY_ID'] = $params['USER_CODE'];
$addChat['SKIP_ADD_MESSAGE'] = 'Y';
$chat = new \CIMChat(0);
$id = $chat->Add($addChat);
if (!$id)
{
return false;
}
$orm = \Bitrix\Im\Model\ChatTable::getById($id);
$this->chat = $orm->fetch();
$this->isCreated = true;
$this->isDataLoaded = true;
return true;
}
/**
* @param $userId
* @param bool $skipSession
* @param bool $skipMessage
* @return Result
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function answer($userId, $skipSession = false, $skipMessage = false)
{
$result = new Result();
$result->setResult(true);
$keyLock = self::PREFIX_KEY_LOCK_ANSWER_SESSION . $this->chat['ID'];
$session = null;
if ($this->chat['AUTHOR_ID'] == $userId)
{
$result->addError(new Error(Loc::getMessage('IMOL_CHAT_ERROR_ANSWER_ALREADY_RESPONSIBLE'), 'IMOL_CHAT_ERROR_ANSWER_ALREADY_RESPONSIBLE', __METHOD__, ['$userId' => $userId]));
}
if(!$this->isDataLoaded())
{
$result->addError(new Error(Loc::getMessage('IMOL_CHAT_ERROR_NOT_LOAD_DATA'), 'IMOL_CHAT_ERROR_NOT_LOAD_DATA', __METHOD__, ['chat' => $this->chat]));
}
if($result->isSuccess())
{
if (Tools\Lock::getInstance()->set($keyLock))
{
$chat = new \CIMChat(0);
$relations = \CIMChat::GetRelationById($this->chat['ID']);
if (!isset($relations[$userId]))
{
$chat->AddUser($this->chat['ID'], $userId, false, true);
}
if ($skipSession)
{
Tools\Lock::getInstance()->delete($keyLock);
}
else
{
$session = new Session();
$resultLoad = $session->load([
'USER_CODE' => $this->chat['ENTITY_ID'],
'MODE' => Session::MODE_OUTPUT,
'OPERATOR_ID' => $userId
]);
if (!$resultLoad)
{
Tools\Lock::getInstance()->delete($keyLock);
$result->setResult(false);
$result->addError(new Error(Loc::getMessage('IMOL_CHAT_ERROR_ANSWER_NOT_LOAD_SESSION'), 'IMOL_CHAT_ERROR_ANSWER_NOT_LOAD_SESSION', __METHOD__, ['USER_CODE' => $this->chat['ENTITY_ID'], 'MODE' => Session::MODE_OUTPUT, 'OPERATOR_ID' => $userId]));
}
else
{
if($this->validationAction($session->getData('CHAT_ID')))
{
if($session->isNowCreated())
{
Tools\Lock::getInstance()->delete($keyLock);
}
}
else
{
$result->addError(new Error(Loc::getMessage('IMOL_CHAT_ERROR_NOT_LOAD_DATA'), 'IMOL_CHAT_ERROR_NOT_LOAD_DATA', __METHOD__, ['chat' => $this->chat]));
}
}
}
if($result->isSuccess())
{
$config = [];
if ($skipSession)
{
//TODO: Replace with the method \Bitrix\ImOpenLines\Chat::parseLiveChatEntityId
list(, $lineId) = explode('|', $this->chat['ENTITY_ID']);
$configManager = new Config();
$config = $configManager->get($lineId);
}
else if ($session && !$session->isNowCreated())
{
$session->setOperatorId($userId, false, false);
if ($session->getData('CRM_ACTIVITY_ID') > 0)
{
$closeDate = new Main\Type\DateTime();
$closeDate->add(intval($session->getConfig('AUTO_CLOSE_TIME')).' SECONDS');
$closeDate->add('1 DAY');
$crmManager = new Crm($session);
if($crmManager->isLoaded())
{
$crmManager->setSessionAnswered(['DATE_CLOSE' => $closeDate]);
}
}
$sessionUpdate = Array(
'OPERATOR_ID' => $userId,
'WAIT_ACTION' => 'N',
'WAIT_ANSWER' => 'N',
'SEND_NO_ANSWER_TEXT' => 'Y'
);
if (!ImUser::getInstance($userId)->isBot() && $session->getData('DATE_OPERATOR_ANSWER') <= 0)
{
$currentDate = new DateTime();
$sessionUpdate['DATE_OPERATOR_ANSWER'] = $currentDate;
$sessionUpdate['TIME_ANSWER'] = $currentDate->getTimestamp()-$session->getData('DATE_CREATE')->getTimestamp();
}
$session->update($sessionUpdate);
$config = $session->getConfig();
}
else if ($session)
{
$config = $session->getConfig();
}
$relations = \CIMChat::GetRelationById($this->chat['ID']);
foreach ($relations as $relation)
{
if(
!ImUser::getInstance($relation['USER_ID'])->isConnector() &&
!ImUser::getInstance($relation['USER_ID'])->isBot() &&
$userId != $relation['USER_ID']
)
{
$chat->DeleteUser($this->chat['ID'], $relation['USER_ID'], false, true);
}
}
$this->update(Array(
'AUTHOR_ID' => $userId
));
Pull\Event::add($userId, Array(
'module_id' => 'imopenlines',
'command' => 'linesAnswer',
'params' => Array(
'chatId' => $this->chat['ID']
)
));
if (!$skipMessage)
{
$userAnswer = ImUser::getInstance($userId);
Im::addMessage(Array(
"FROM_USER_ID" => $userId,
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => Loc::getMessage('IMOL_CHAT_ANSWER_'.$userAnswer->getGender(), Array('#USER#' => '[USER='.$userAnswer->getId().'][/USER]')),
"SYSTEM" => 'Y',
));
}
Tools\Lock::getInstance()->delete($keyLock);
if ($session)
{
$eventData = array(
'RUNTIME_SESSION' => $session,
'USER_ID' => $userId,
);
$event = new Event("imopenlines", "OnChatAnswer", $eventData);
$event->send();
}
}
}
else
{
$result->addError(new Error(Loc::getMessage('IMOL_CHAT_ERROR_ANSWER_COMPETITIVE_REQUEST'), 'IMOL_CHAT_ERROR_ANSWER_COMPETITIVE_REQUEST', __METHOD__, ['$userId' => $userId]));
}
}
return $result;
}
/**
* @param $userId
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function intercept($userId)
{
$result = false;
if(
$this->isDataLoaded() &&
$this->chat['AUTHOR_ID'] > 0 &&
$this->chat['AUTHOR_ID'] != $userId
)
{
$previousOwnerId = $this->chat['AUTHOR_ID'];
$resultAnswer = $this->answer($userId, false, true);
if($resultAnswer->isSuccess())
{
$previousOwner = ImUser::getInstance($previousOwnerId);
$newOwner = ImUser::getInstance($userId);
\CIMChat::AddMessage(Array(
"FROM_USER_ID" => $userId,
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => Loc::getMessage('IMOL_CHAT_INTERCEPT_'.$newOwner->getGender(), Array(
'#USER_1#' => '[USER='.$newOwner->getId().'][/USER]',
'#USER_2#' => '[USER='.$previousOwner->getId().'][/USER]'
)),
"SYSTEM" => 'Y',
));
$result = true;
}
}
return $result;
}
/**
* Skip the dialogue.
*
* @param int $userId
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function skip($userId = 0)
{
$result = false;
if($this->isDataLoaded())
{
$session = new Session();
$resultLoad = $session->load(Array(
'USER_CODE' => $this->chat['ENTITY_ID'],
'SKIP_CREATE' => 'Y'
));
if ($resultLoad)
{
if($this->validationAction($session->getData('CHAT_ID')))
{
$eventData = array(
'RUNTIME_SESSION' => $session,
'USER_ID' => $userId,
);
$event = new Event("imopenlines", "OnChatSkip", $eventData);
$event->send();
if ($userId)
{
$userSkip = ImUser::getInstance($userId);
Im::addMessage(Array(
"FROM_USER_ID" => $userId,
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => Loc::getMessage('IMOL_CHAT_SKIP_'.$userSkip->getGender(), Array('#USER#' => '[USER='.$userSkip->getId().'][/USER]')),
"SYSTEM" => 'Y',
));
}
$result = $session->transferToNextInQueue();
}
}
else
{
if ($userId > 0)
{
$chat = new \CIMChat();
$chat->DeleteUser($this->chat['ID'], $userId, false);
}
}
}
return $result;
}
/**
* The end of the session of the bot.
*
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function endBotSession()
{
$result = false;
if($this->isDataLoaded())
{
$session = new Session();
$resultLoadSession = $session->load(Array(
'USER_CODE' => $this->chat['ENTITY_ID']
));
if ($resultLoadSession && ImUser::getInstance($session->getData('OPERATOR_ID'))->isBot())
{
if($this->validationAction($session->getData('CHAT_ID')))
{
$chat = new \CIMChat(0);
if ($session->getConfig('WELCOME_BOT_LEFT') != Config::BOT_LEFT_CLOSE)
{
$chat->DeleteUser($this->chat['ID'], $session->getData('OPERATOR_ID'), false, true);
}
else
{
$chat->SetOwner($this->chat['ID'], 0);
}
$session->transferToNextInQueue();
Im::addMessage(Array(
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => Loc::getMessage('IMOL_CHAT_TO_QUEUE_NEW'),
"SYSTEM" => 'Y',
));
$result = true;
}
}
}
return $result;
}
/**
* @param $userId
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function waitAnswer($userId)
{
$this->update([
'AUTHOR_ID' => $userId,
self::getFieldName(self::FIELD_SILENT_MODE) => 'N'
]);
}
/**
* @param $params
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function transfer($params)
{
$result = false;
if($this->isDataLoaded())
{
$keyLock = Queue\Queue::PREFIX_KEY_LOCK . $this->chat['ID'];
if(Tools\Lock::getInstance()->set($keyLock))
{
$mode = in_array($params['MODE'], [self::TRANSFER_MODE_AUTO, self::TRANSFER_MODE_BOT])? $params['MODE']: self::TRANSFER_MODE_MANUAL;
$selfExit = isset($params['LEAVE']) && $params['LEAVE'] == 'N'? false: true;
$skipCheck = isset($params['SKIP_CHECK']) && $params['SKIP_CHECK'] == 'Y';
$session = new Session();
$resultLoadSession = $session->load([
'USER_CODE' => $this->chat['ENTITY_ID']
]);
if ($resultLoadSession)
{
if($this->validationAction($session->getData('CHAT_ID')))
{
//Event
$event = new Event("imopenlines", "OnOperatorTransfer", [
'CHAT' => $this->chat,
'SESSION' => $session,
'TRANSFER' => [
'MODE' => $mode,
'FROM' => $params['FROM'],
'TO' => $params['TO'],
]
]);
$event->send();
foreach($event->getResults() as $eventResult)
{
if ($eventResult->getType() != \Bitrix\Main\EventResult::SUCCESS)
continue;
$newValues = $eventResult->getParameters();
if (!empty($newValues['TRANSFER_ID']))
{
$params['TO'] = $newValues['TRANSFER_ID'];
}
}
// END Event
//Transfer to queue
if (mb_substr($params['TO'], 0, 5) == 'queue')
{
$result = $this->transferToQueue($params, $session, $mode);
}
//Transfer to the operator
else
{
$result = $this->transferToOperator($params, $session, $mode, $selfExit, $skipCheck);
}
}
}
Tools\Lock::getInstance()->delete($keyLock);
}
}
return $result;
}
/**
* Transfer to queue.
*
* @param $params
* @param Session $session
* @param $mode
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
protected function transferToQueue($params, $session, $mode)
{
$result = false;
if($this->isDataLoaded())
{
$userFrom = ImUser::getInstance($params['FROM']);
$lineFromId = $session->getConfig('ID');
$lineFrom = $session->getConfig('LINE_NAME');
$userCode = $session->getData('USER_CODE');
//Transfer the same queue
if($params['TO'] == 'queue')
{
$queueId = $lineFromId;
}
else
{
$queueId = intval(mb_substr($params['TO'], 5));
}
$config = ConfigTable::getById($queueId)->fetch();
if ($config)
{
$session->setOperatorId(0, true, $mode == self::TRANSFER_MODE_MANUAL ? false : true);
$this->update(['AUTHOR_ID' => 0]);
$this->updateFieldData([Chat::FIELD_SESSION => ['LINE_ID' => $queueId]]);
$chat = new \CIMChat(0);
$relations = \CIMChat::GetRelationById($this->chat['ID']);
foreach ($relations as $relation)
{
if (ImUser::getInstance($relation['USER_ID'])->isConnector())
continue;
if (ImUser::getInstance($relation['USER_ID'])->isBot())
continue;
$chat->DeleteUser($this->chat['ID'], $relation['USER_ID'], false, true);
}
if($queueId == 0)
{
$queueId = $lineFromId;
}
Log::write([$params['FROM'], $queueId], 'TRANSFER TO LINE');
OperatorTransferTable::Add([
'CONFIG_ID' => $session->getData('CONFIG_ID'),
'SESSION_ID' => $session->getData('ID'),
'USER_ID' => $params['FROM'],
'TRANSFER_MODE' => $mode,
'TRANSFER_TYPE' => 'QUEUE',
'TRANSFER_LINE_ID' => $queueId
]);
$updateData = [
'CONFIG_ID' => $queueId,
'QUEUE_HISTORY' => [],
'SKIP_DATE_CLOSE' => true,
'DATE_MODIFY' => new DateTime(),
'OPERATOR_FROM_CRM' => 'N'
];
if ($userFrom->isBot() && !$session->getData('DATE_OPERATOR'))
{
$currentDate = new DateTime();
$updateData['DATE_OPERATOR'] = $currentDate;
$updateData['TIME_BOT'] = $currentDate->getTimestamp() - $session->getData('DATE_CREATE')->getTimestamp();
}
$session->update($updateData);
$lineTo = $session->getConfig('LINE_NAME');
if($params['TO'] == 'queue')
{
$message = Loc::getMessage('IMOL_CHAT_RETURNED_TO_QUEUE_NEW');
}
else if ($lineFromId == $queueId)
{
$message = Loc::getMessage('IMOL_CHAT_SKIP_'.$userFrom->getGender(), [
'#USER#' => '[USER='.$userFrom->getId().'][/USER]',
]);
}
else
{
$message = Loc::getMessage('IMOL_CHAT_TRANSFER_LINE_'.$userFrom->getGender(), [
'#USER_FROM#' => '[USER='.$userFrom->getId().'][/USER]',
'#LINE_FROM#' => '[b]'.$lineFrom.'[/b]',
'#LINE_TO#' => '[b]'.$lineTo.'[/b]',
]);
}
$session->transferToNextInQueue(false);
Im::addMessage([
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => $message,
"SYSTEM" => 'Y',
]);
$result = true;
}
}
return $result;
}
/**
* Transfer to the operator.
*
* @param $params
* @param Session $session
* @param $mode
* @param $selfExit
* @param $skipCheck
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
protected function transferToOperator($params, $session, $mode, $selfExit, $skipCheck)
{
$result = false;
if($this->isDataLoaded())
{
$transferUserId = intval($params['TO']);
if($skipCheck ||
(
!ImUser::getInstance($transferUserId)->isBot() &&
!ImUser::getInstance($transferUserId)->isExtranet() &&
!ImUser::getInstance($transferUserId)->isConnector()
))
{
$chat = new \CIMChat(0);
$relations = \CIMChat::GetRelationById($this->chat['ID']);
foreach ($relations as $relation)
{
if(
!ImUser::getInstance($relation['USER_ID'])->isConnector() &&
!ImUser::getInstance($relation['USER_ID'])->isBot() &&
$relation['USER_ID'] != $params['FROM']
)
{
$chat->DeleteUser($this->chat['ID'], $relation['USER_ID'], false, true);
}
}
if($params['FROM'] > 0 && $selfExit)
{
$chat->DeleteUser($this->chat['ID'], $params['FROM'], false, true);
}
if ($session->getConfig('ACTIVE') == 'Y')
{
$this->update(Array('AUTHOR_ID' => 0));
}
else
{
$this->update(Array('AUTHOR_ID' => $transferUserId));
}
if($transferUserId > 0)
{
$chat->AddUser($this->chat['ID'], $transferUserId, false, true);
}
$userFrom = ImUser::getInstance($params['FROM']);
if($transferUserId > 0)
{
$userTo = ImUser::getInstance($transferUserId);
}
Log::write(Array($params['FROM'], $transferUserId), 'TRANSFER TO USER');
if ($transferUserId > 0 && $params['FROM'] > 0 && ($mode == self::TRANSFER_MODE_MANUAL || $mode == self::TRANSFER_MODE_BOT))
{
$message = Loc::getMessage('IMOL_CHAT_TRANSFER_'.$userFrom->getGender(), [
'#USER_FROM#' => '[USER='.$userFrom->getId().'][/USER]',
'#USER_TO#' => '[USER='.$userTo->getId().'][/USER]']
);
}
else if(empty($transferUserId))
{
$message = Loc::getMessage('IMOL_CHAT_NO_OPERATOR_AVAILABLE_IN_QUEUE_NEW');
}
else
{
$message = Loc::getMessage('IMOL_CHAT_NEXT_IN_QUEUE_NEW', ['#USER_TO#' => '[USER='.$userTo->getId().'][/USER]']);
}
OperatorTransferTable::Add([
'CONFIG_ID' => $session->getData('CONFIG_ID'),
'SESSION_ID' => $session->getData('ID'),
'USER_ID' => intval($params['FROM']),
'TRANSFER_MODE' => $mode,
'TRANSFER_TYPE' => 'USER',
'TRANSFER_USER_ID' => $transferUserId
]);
Im::addMessage([
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => $message,
"SYSTEM" => 'Y',
]);
$updateDataSession = [
'OPERATOR_FROM_CRM' => 'N'
];
if ($userFrom->isBot() && !$session->getData('DATE_OPERATOR'))
{
$currentDate = new DateTime();
$updateDataSession['DATE_OPERATOR'] = $currentDate;
$updateDataSession['TIME_BOT'] = $currentDate->getTimestamp()-$session->getData('DATE_CREATE')->getTimestamp();
}
if ($mode == self::TRANSFER_MODE_MANUAL)
{
$this->answer($transferUserId, false, true);
$updateDataSession['DATE_MODIFY'] = new DateTime();
$updateDataSession['SKIP_DATE_CLOSE'] = true;
}
else
{
$session->setOperatorId($transferUserId, true, true);
}
$session->update($updateDataSession);
$result = true;
}
}
return $result;
}
/**
* Set the chat operators who see the chat.
*
* @param array $users
* @param bool $skipMessage
* @param bool $skipRecent
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function setOperators($users = [], $skipMessage = true, $skipRecent = false): bool
{
$result = false;
if($this->isDataLoaded() && is_array($users))
{
$users = array_unique($users);
$delete = [];
$relationList = RelationTable::getList([
"select" => ["ID", "USER_ID"],
"filter" => [
"=CHAT_ID" => $this->chat['ID']
],
]);
while ($relation = $relationList->fetch())
{
if(Queue::isRealOperator($relation['USER_ID']))
{
if(!in_array($relation['USER_ID'], $users))
{
$delete[] = $relation['USER_ID'];
}
}
}
if(!empty($users) || !empty($delete))
{
$chat = new \CIMChat($this->joinByUserId);
if(!empty($users))
{
$result = $chat->AddUser($this->chat['ID'], $users, false, $skipMessage, $skipRecent);
self::chatAutoAddRecent($this->chat['ID'], $users);
}
if(!empty($delete))
{
foreach ($delete as $userId)
{
$result = $chat->DeleteUser($this->chat['ID'], $userId, false, $skipMessage);
}
}
}
}
return $result;
}
/**
* Adding a user to the chat.
*
* @param $userId
* @param bool $skipMessage
* @param bool $skipRecent
* @return bool
*/
public function join($userId, $skipMessage = true, $skipRecent = false)
{
$result = false;
if($this->isDataLoaded() && !empty($userId))
{
$chat = new \CIMChat($this->joinByUserId);
$result = $chat->AddUser($this->chat['ID'], $userId, false, $skipMessage, $skipRecent);
}
return $result;
}
/**
* To exclude a user from chat.
*
* @param $userId
* @return bool
*/
public function leave($userId)
{
$result = false;
if ($this->isDataLoaded())
{
$chat = new \CIMChat(0);
$result = $chat->DeleteUser($this->chat['ID'], $userId, false, true);
}
return $result;
}
/**
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function close()
{
$result = false;
if($this->isDataLoaded())
{
$relationList = RelationTable::getList(array(
"select" => array("ID", "USER_ID", "EXTERNAL_AUTH_ID" => "USER.EXTERNAL_AUTH_ID"),
"filter" => array(
"=CHAT_ID" => $this->chat['ID']
),
));
while ($relation = $relationList->fetch())
{
if ($relation['EXTERNAL_AUTH_ID'] == "imconnector")
continue;
$this->leave($relation['USER_ID']);
}
$this->updateFieldData([Chat::FIELD_SESSION => [
'ID' => '0',
'PAUSE' => 'N',
'WAIT_ACTION' => 'N'
]]);
$this->update(Array(
'AUTHOR_ID' => 0,
self::getFieldName(self::FIELD_SILENT_MODE) => 'N'
));
$result = true;
}
return $result;
}
/**
* @param $userId
* @return bool
*/
public function setUserIdForJoin($userId)
{
$this->joinByUserId = intval($userId);
return true;
}
/**
* @param $params array
* (
* ACTIVE
* CRM
* CRM_ENTITY_TYPE
* CRM_ENTITY_ID
* LEAD
* COMPANY
* CONTACT
* DEAL
* )
* @return bool
* @throws Main\ArgumentException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function setCrmFlag($params)
{
$result = false;
$updateDate = [];
$sessionField = $this->getFieldData(self::FIELD_SESSION);
$sessionCrmField = $this->getFieldData(self::FIELD_CRM);
if(isset($params['ACTIVE']))
{
$params['ACTIVE'] = $params['ACTIVE'] == 'Y'? 'Y': 'N';
if($params['ACTIVE'] != $sessionField['CRM'])
{
$updateDate[self::FIELD_SESSION]['CRM'] = $params['ACTIVE'];
}
}
if(isset($params['CRM']))
{
$params['CRM'] = $params['CRM'] == 'Y'? 'Y': 'N';
if($params['CRM'] != $sessionField['CRM'])
{
$updateDate[self::FIELD_SESSION]['CRM'] = $params['CRM'];
}
}
if(isset($params['ENTITY_TYPE']))
{
if($params['ENTITY_TYPE'] != $sessionField['CRM_ENTITY_TYPE'])
{
$updateDate[self::FIELD_SESSION]['CRM_ENTITY_TYPE'] = $params['ENTITY_TYPE'];
}
}
if(isset($params['ENTITY_ID']))
{
$params['ENTITY_ID'] = intval($params['ENTITY_ID']);
if($params['ENTITY_ID'] != $sessionField['CRM_ENTITY_ID'])
{
$updateDate[self::FIELD_SESSION]['CRM_ENTITY_ID'] = $params['ENTITY_ID'];
}
}
if(isset($params['LEAD']))
{
$params['LEAD'] = intval($params['LEAD']);
if($params['LEAD'] != $sessionCrmField['LEAD'])
{
$updateDate[self::FIELD_CRM]['LEAD'] = $params['LEAD'];
}
}
if(isset($params['COMPANY']))
{
$params['COMPANY'] = intval($params['COMPANY']);
if($params['COMPANY'] != $sessionCrmField['COMPANY'])
{
$updateDate[self::FIELD_CRM]['COMPANY'] = $params['COMPANY'];
}
}
if(isset($params['CONTACT']))
{
$params['CONTACT'] = intval($params['CONTACT']);
if($params['CONTACT'] != $sessionCrmField['CONTACT'])
{
$updateDate[self::FIELD_CRM]['CONTACT'] = $params['CONTACT'];
}
}
if(isset($params['DEAL']))
{
$params['DEAL'] = intval($params['DEAL']);
if($params['DEAL'] != $sessionCrmField['DEAL'])
{
$updateDate[self::FIELD_CRM]['DEAL'] = $params['DEAL'];
}
}
if(!empty($updateDate))
{
$raw = $this->updateFieldData($updateDate);
if($raw->isSuccess())
{
$result = true;
}
}
return $result;
}
/**
* @param $status
* @return bool
*/
public function updateSessionStatus($status)
{
$result = false;
if($this->isDataLoaded())
{
$users = [];
$relations = \Bitrix\Im\Chat::getRelation($this->chat['ID'], [
'SELECT' => Array('USER_ID'),
'USER_DATA' => 'Y',
]);
foreach ($relations as $relation)
{
if ($relation['USER_DATA']["EXTERNAL_AUTH_ID"] == 'imconnector')
{
continue;
}
$users[] = $relation['USER_ID'];
}
Pull\Event::add($users, [
'module_id' => 'imopenlines',
'command' => 'updateSessionStatus',
'params' => [
'chatId' => $this->chat['ID'],
'status' => (int)$status
],
]);
$result = true;
}
return $result;
}
/**
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function finish()
{
$result = false;
if($this->isDataLoaded())
{
$session = new Session();
$resultLoadSession = $session->load([
'USER_CODE' => $this->chat['ENTITY_ID']
]);
if ($resultLoadSession)
{
if($this->validationAction($session->getData('CHAT_ID')))
{
$eventData = [
'RUNTIME_SESSION' => $session
];
$event = new Event("imopenlines", "OnChatFinish", $eventData);
$event->send();
$session->finish();
$result = true;
}
}
else
{
$this->validationAction();
}
}
return $result;
}
/**
* @param $userId
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function markSpamAndFinish($userId)
{
$result = false;
$session = new Session();
if (
$this->isDataLoaded() &&
$session->load([
'USER_CODE' => $this->chat['ENTITY_ID'],
'SKIP_CREATE' => 'Y'
])
)
{
if($this->validationAction($session->getData('CHAT_ID')))
{
$queueManager = Queue::initialization($session);
if($queueManager && $queueManager->startLock())
{
$user = ImUser::getInstance($userId);
$message = Loc::getMessage('IMOL_CHAT_MARK_SPAM_'.$user->getGender(), Array(
'#USER#' => '[USER='.$user->getId().'][/USER]',
));
Im::addMessage(Array(
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => $message,
"SYSTEM" => 'Y',
));
if (\Bitrix\ImOpenLines\Connector::isLiveChat($session->getData('SOURCE')))
{
$parsedUserCode = Session\Common::parseUserCode($session->getData('USER_CODE'));
$chatId = $parsedUserCode['EXTERNAL_CHAT_ID'];
$liveChat = new Chat($chatId);
$liveChat->updateFieldData([Chat::FIELD_LIVECHAT => [
'SESSION_ID' => 0,
'SHOW_FORM' => 'N'
]]);
}
$eventData = array(
'RUNTIME_SESSION' => $session,
'USER_ID' => $userId,
);
$event = new Event("imopenlines", "OnChatMarkSpam", $eventData);
$event->send();
$session->markSpam();
$session->finish();
$queueManager->stopLock();
$result = true;
}
}
}
else
{
$this->validationAction();
}
return $result;
}
/**
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function dismissedOperatorFinish()
{
$result = false;
if($this->isDataLoaded())
{
$session = new Session();
$params = [
'SKIP_CREATE' => 'Y',
'USER_CODE' => $this->chat['ENTITY_ID']
];
$parsedUserCode = Session\Common::parseUserCode($this->chat['ENTITY_ID']);
$params['USER_ID'] = $parsedUserCode['CONNECTOR_USER_ID'];
$params['SOURCE'] = $parsedUserCode['CONNECTOR_ID'];
$params['CHAT_ID'] = $parsedUserCode['EXTERNAL_CHAT_ID'];
$params['CONFIG_ID'] = $parsedUserCode['CONFIG_ID'];
$resultStart = $session->start($params);
if ($resultStart->isSuccess() && $resultStart->getResult() == true)
{
$session->dismissedOperatorFinish();
$result = true;
}
}
return $result;
}
/**
* @param $userId
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function startSession($userId)
{
$result = false;
if($this->isDataLoaded())
{
$session = new Session();
$resultLoad = $session->load(Array(
'USER_CODE' => $this->chat['ENTITY_ID'],
'MODE' => Session::MODE_OUTPUT,
'OPERATOR_ID' => $userId,
));
if($resultLoad)
{
if($this->validationAction($session->getData('CHAT_ID')))
{
if ($session->isNowCreated())
{
$dateClose = new DateTime();
$dateClose->add('1 MONTH');
$sessionUpdate = Array(
'CHECK_DATE_CLOSE' => $dateClose
);
$session->update($sessionUpdate);
}
else
{
$this->join($userId, false);
}
$result = true;
}
}
}
return $result;
}
/**
* Create a new dialog based on an old message.
*
* @param $userId
* @param $messageId
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function startSessionByMessage($userId, $messageId)
{
$result = false;
if($this->isDataLoaded())
{
$keyLock = self::PREFIX_KEY_LOCK_NEW_SESSION . $this->chat['ENTITY_ID'];
if (Tools\Lock::getInstance()->set($keyLock))
{
$session = new Session();
$resultLoad = $session->load([
'USER_CODE' => $this->chat['ENTITY_ID']
]);
if ($resultLoad)
{
if($this->validationAction($session->getData('CHAT_ID')))
{
$message = \CIMMessenger::GetById($messageId);
if ($message['CHAT_ID'] == $this->chat['ID'])
{
$user = ImUser::getInstance($userId);
Im::addMessage(Array(
"TO_CHAT_ID" => $this->chat['ID'],
"SYSTEM" => 'Y',
"MESSAGE" => Loc::getMessage('IMOL_CHAT_CLOSE_FOR_OPEN_'.$user->getGender(), Array(
'#USER#' => '[USER='.$user->getId().'][/USER]',
)),
));
$configId = $session->getData('CONFIG_ID');
$sessionId = $session->getData('SESSION_ID');
$session->finish(false, true, false);
$session = new Session();
$session->load(Array(
'USER_CODE' => $this->chat['ENTITY_ID'],
'MODE' => Session::MODE_OUTPUT,
'OPERATOR_ID' => $userId,
'CONFIG_ID' => $configId,
'PARENT_ID' => $sessionId
));
if ($this->chat['AUTHOR_ID'] == $userId)
{
$resultAnswer = true;
}
else
{
$resultAnswer = $this->answer($userId, false, true)->isSuccess();
}
if($resultAnswer)
{
Im::addMessage(Array(
"TO_CHAT_ID" => $this->chat['ID'],
"FROM_USER_ID" => $message['AUTHOR_ID'],
"MESSAGE" => $message['MESSAGE'],
"PARAMS" => $message['PARAMS'],
"SKIP_CONNECTOR" => 'Y',
));
$dateClose = new DateTime();
$dateClose->add('1 MONTH');
$sessionUpdate = Array(
'CHECK_DATE_CLOSE' => $dateClose
);
$session->update($sessionUpdate);
$result = true;
}
}
}
}
Tools\Lock::getInstance()->delete($keyLock);
}
}
return $result;
}
/**
* @param bool $active
* @return bool
* @throws Main\LoaderException
*/
public function setSilentMode($active = true)
{
$result = false;
if($this->isDataLoaded())
{
$active = $active? 'Y': '';
if ($this->chat[self::getFieldName(self::FIELD_SILENT_MODE)] == $active)
{
$result = true;
}
else
{
\Bitrix\Im\Model\ChatTable::update($this->chat['ID'], Array(
self::getFieldName(self::FIELD_SILENT_MODE) => $active
));
Im::addMessage(Array(
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => Loc::getMessage($active? 'IMOL_CHAT_STEALTH_ON': 'IMOL_CHAT_STEALTH_OFF'),
"SYSTEM" => 'Y',
));
$result = true;
}
}
return $result;
}
/**
* @return bool
*/
public function isSilentModeEnabled()
{
$result = false;
if($this->isDataLoaded())
{
$result = $this->chat[self::getFieldName(self::FIELD_SILENT_MODE)] == 'Y';;
}
return $result;
}
/**
* @param $params
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function setPauseFlag($params)
{
$result = false;
$pause = $params['ACTIVE'] == 'Y'? 'Y': 'N';
$sessionField = $this->getFieldData(self::FIELD_SESSION);
if ($sessionField['PAUSE'] == $pause)
{
$result = true;
}
elseif($this->isDataLoaded())
{
$session = new Session();
$resultLoad = $session->load([
'USER_CODE' => $this->chat['ENTITY_ID']
]);
if ($resultLoad)
{
if($this->validationAction($session->getData('CHAT_ID')))
{
if(empty($params['USER_ID']) || $params['USER_ID'] == $session->getData('OPERATOR_ID'))
{
$queueManager = Queue::initialization($session);
if($queueManager && $queueManager->startLock())
{
$session->pause($pause == 'Y');
$this->updateFieldData([self::FIELD_SESSION => [
'PAUSE' => $pause
]]);
if ($pause == 'Y')
{
$datePause = new DateTime();
$datePause->add('1 WEEK');
$formattedDate = \FormatDate('d F', $datePause->getTimestamp());
Im::addMessage([
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => Loc::getMessage('IMOL_CHAT_ASSIGN_ON', ['#DATE#' => '[b]'.$formattedDate.'[/b]']),
"SYSTEM" => 'Y',
]);
}
else
{
Im::addMessage([
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => Loc::getMessage('IMOL_CHAT_ASSIGN_OFF'),
"SYSTEM" => 'Y',
]);
}
$queueManager->stopLock();
$result = true;
}
}
}
}
}
return $result;
}
/**
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function createLead()
{
$result = false;
$sessionField = $this->getFieldData(self::FIELD_SESSION);
if ($sessionField['CRM'] == 'Y')
{
$result = true;
}
elseif($this->isDataLoaded())
{
$session = new Session();
if($session->load([
'USER_CODE' => $this->chat['ENTITY_ID']
]))
{
if($this->validationAction($session->getData('CHAT_ID')))
{
$crmManager = new Crm($session);
if($crmManager->isLoaded())
{
$crmFieldsManager = $crmManager->getFields();
$crmFieldsManager->setTitle($session->getChat()->getData('TITLE'));
$crmFieldsManager->setDataFromUser();
$crmManager->setSkipSearch();
$crmManager->setSkipAutomationTrigger();
$rawResult = $crmManager->registrationChanges();
$crmManager->sendCrmImMessages();
if($rawResult->isSuccess())
{
$result = true;
}
}
}
}
}
return $result;
}
/**
* @param $field
* @return array
*/
public function getFieldData($field)
{
$data = [];
if ($this->isDataLoaded() &&
in_array($field, [self::FIELD_CRM, self::FIELD_SESSION, self::FIELD_LIVECHAT])
)
{
if ($field == self::FIELD_SESSION)
{
$data = [
'ID' => time(),
'CRM' => 'N',
'CRM_ENTITY_TYPE' => 'NONE',
'CRM_ENTITY_ID' => '0',
'PAUSE' => 'N',
'WAIT_ACTION' => 'N',
'DATE_CREATE' => '0',
'LINE_ID' => 0
];
$fieldData = explode("|", $this->chat[self::getFieldName($field)]);
if (isset($fieldData[0]) && $fieldData[0] == 'Y')
{
$data['CRM'] = $fieldData[0];
}
if (isset($fieldData[1]))
{
$data['CRM_ENTITY_TYPE'] = $fieldData[1];
}
if (isset($fieldData[2]))
{
$data['CRM_ENTITY_ID'] = $fieldData[2];
}
if (isset($fieldData[3]) && $fieldData[3] == 'Y')
{
$data['PAUSE'] = $fieldData[3];
}
if (isset($fieldData[4]) && $fieldData[4] == 'Y')
{
$data['WAIT_ACTION'] = $fieldData[4];
}
if (isset($fieldData[5]))
{
$data['ID'] = intval($fieldData[5]);
}
if (isset($fieldData[6]))
{
$data['DATE_CREATE'] = intval($fieldData[6]);
}
if (isset($fieldData[7]) && $fieldData[7] > 0)
{
$data['LINE_ID'] = intval($fieldData[7]);
}
if (isset($fieldData[8]))
{
$data['BLOCK_DATE'] = (int)$fieldData[8];
}
if (isset($fieldData[9]))
{
$data['BLOCK_REASON'] = $fieldData[9];
}
}
else if ($field == self::FIELD_CRM)
{
$data = [
'LEAD' => 0,
'COMPANY' => 0,
'CONTACT' => 0,
'DEAL' => 0,
];
$fieldData = explode("|", $this->chat[self::getFieldName($field)]);
$countFields = count($fieldData);
for($i = 0; $countFields>$i; $i=$i+2)
{
if(isset($data[$fieldData[$i]]) && isset($fieldData[$i+1]))
{
$data[$fieldData[$i]] = $fieldData[$i+1];
}
}
}
else if ($field == self::FIELD_LIVECHAT)
{
$data = [
'READED' => 'N',
'READED_ID' => '0',
'READED_TIME' => false,
'SESSION_ID' => '0',
'SHOW_FORM' => 'Y',
];
$fieldData = explode("|", $this->chat[self::getFieldName($field)]);
if (isset($fieldData[0]) && $fieldData[0] == 'Y')
{
$data['READED'] = $fieldData[0];
}
if (isset($fieldData[1]))
{
$data['READED_ID'] = intval($fieldData[1]);
}
if (isset($fieldData[2]))
{
$data['READED_TIME'] = $fieldData[2];
}
if (isset($fieldData[3]))
{
$data['SESSION_ID'] = intval($fieldData[3]);
}
if (isset($fieldData[4]))
{
$data['SHOW_FORM'] = $fieldData[4] == 'N'? 'N': 'Y';
}
}
}
return $data;
}
/**
* @param $lineName
* @param string $userName
* @param string $userColor
* @return array
*/
public function getTitle($lineName, $userName = '', $userColor = '')
{
if (!$userName)
{
$result = self::getGuestName($userColor);
$userName = $result['USER_NAME'];
$userColor = $result['USER_COLOR'];
}
if (!$userColor)
{
$userColor = \Bitrix\Im\Color::getRandomCode();
}
return Array(
'TITLE' => Loc::getMessage('IMOL_CHAT_CHAT_NAME', Array("#USER_NAME#" => $userName, "#LINE_NAME#" => $lineName)),
'COLOR' => $userColor
);
}
/**
* @param $fields
* @return Result
* @throws Main\ArgumentException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function updateFieldData($fields)
{
$result = new Result;
$updateDate = [];
if(!$this->isDataLoaded())
{
$result->addError(new Error(Loc::getMessage('IMOL_CHAT_ERROR_NOT_LOAD_DATA'), 'IMOL_CHAT_ERROR_NOT_LOAD_DATA', __METHOD__, ['chat' => $this->chat]));
}
if($result->isSuccess() && is_array($fields))
{
foreach ($fields as $fieldType => $fieldData)
{
if (in_array($fieldType, [self::FIELD_CRM, self::FIELD_SESSION, self::FIELD_LIVECHAT]) && !empty($fieldData))
{
if ($fieldType == self::FIELD_SESSION)
{
$data = self::getFieldData($fieldType);
if (isset($fieldData['CRM']))
{
$data['CRM'] = $fieldData['CRM'];
}
if (isset($fieldData['CRM_ENTITY_TYPE']))
{
$data['CRM_ENTITY_TYPE'] = $fieldData['CRM_ENTITY_TYPE'];
}
if (isset($fieldData['CRM_ENTITY_ID']))
{
$data['CRM_ENTITY_ID'] = $fieldData['CRM_ENTITY_ID'];
}
if (isset($fieldData['PAUSE']))
{
$data['PAUSE'] = $fieldData['PAUSE'];
}
if (isset($fieldData['WAIT_ACTION']))
{
$data['WAIT_ACTION'] = $fieldData['WAIT_ACTION'];
}
if (isset($fieldData['ID']))
{
$data['ID'] = $fieldData['ID'];
}
if (isset($fieldData['DATE_CREATE']))
{
$data['DATE_CREATE'] = $fieldData['DATE_CREATE'] instanceof DateTime? $fieldData['DATE_CREATE']->getTimestamp(): intval($fieldData['DATE_CREATE']);
}
if (isset($fieldData['LINE_ID']) && intval($fieldData['LINE_ID']) > 0)
{
$data['LINE_ID'] = intval($fieldData['LINE_ID']);
}
if (isset($fieldData['BLOCK_DATE']))
{
$data['BLOCK_DATE'] = $fieldData['BLOCK_DATE'] instanceof DateTime? $fieldData['BLOCK_DATE']->getTimestamp(): (int)$fieldData['BLOCK_DATE'];
}
if (isset($fieldData['BLOCK_REASON']))
{
$data['BLOCK_REASON'] = $fieldData['BLOCK_REASON'];
}
$this->chat[self::getFieldName($fieldType)] = $data['CRM'].'|'
.$data['CRM_ENTITY_TYPE'].'|'
.$data['CRM_ENTITY_ID'].'|'
.$data['PAUSE'].'|'
.$data['WAIT_ACTION'].'|'
.$data['ID'].'|'
.$data['DATE_CREATE'].'|'
.$data['LINE_ID'].'|'
.$data['BLOCK_DATE'].'|'
.$data['BLOCK_REASON'];
$updateDate[self::getFieldName($fieldType)] = $this->chat[self::getFieldName($fieldType)];
}
else if ($fieldType == self::FIELD_CRM)
{
$strungData = '';
$data = self::getFieldData($fieldType);
if (isset($fieldData['LEAD']))
{
$data['LEAD'] = $fieldData['LEAD'];
}
if (isset($fieldData['COMPANY']))
{
$data['COMPANY'] = $fieldData['COMPANY'];
}
if (isset($fieldData['CONTACT']))
{
$data['CONTACT'] = $fieldData['CONTACT'];
}
if (isset($fieldData['DEAL']))
{
$data['DEAL'] = $fieldData['DEAL'];
}
foreach ($data as $type => $value)
{
if(!empty($strungData))
$strungData .= '|';
$strungData .= $type . '|' . $value;
}
if(!empty($strungData))
{
$updateDate[self::getFieldName($fieldType)] = $this->chat[self::getFieldName($fieldType)] = $strungData;
}
}
elseif ($fieldType == self::FIELD_LIVECHAT)
{
$data = self::getFieldData($fieldType);
if (isset($fieldData['READED']))
{
$data['READED'] = $fieldData['READED'];
}
if (isset($fieldData['READED_ID']))
{
$data['READED_ID'] = intval($fieldData['READED_ID']);
}
if (isset($fieldData['READED_TIME']))
{
$data['READED_TIME'] = $fieldData['READED_TIME'] instanceof DateTime? date('c', $fieldData['READED_TIME']->getTimestamp()): false;
}
if (isset($fieldData['SESSION_ID']))
{
$data['SESSION_ID'] = intval($fieldData['SESSION_ID']);
}
if (isset($fieldData['SHOW_FORM']))
{
$data['SHOW_FORM'] = $fieldData['SHOW_FORM'] == 'N'? 'N': 'Y';
}
$updateDate[self::getFieldName($fieldType)] = $this->chat[self::getFieldName($fieldType)] = $data['READED'].'|'.$data['READED_ID'].'|'.$data['READED_TIME'].'|'.$data['SESSION_ID'].'|'.$data['SHOW_FORM'];
}
}
}
}
if($result->isSuccess() && empty($updateDate))
{
$result->addError(new Error(Loc::getMessage('IMOL_CRM_ERROR_NOT_GIVEN_CORRECT_DATA'), self::IMOL_CRM_ERROR_NOT_GIVEN_CORRECT_DATA, __METHOD__));
}
if($result->isSuccess())
{
$rawUpdate = ChatTable::update($this->chat['ID'], $updateDate);
if(!$rawUpdate->isSuccess())
{
$result->addErrors($rawUpdate->getErrors());
}
}
if($result->isSuccess())
{
$users = [];
$relationList = RelationTable::getList([
"select" => array("ID", "USER_ID", "EXTERNAL_AUTH_ID" => "USER.EXTERNAL_AUTH_ID"),
"filter" => array(
"=CHAT_ID" => $this->chat['ID']
)
]);
while ($relation = $relationList->fetch())
{
if (
!ImUser::getInstance($relation['USER_ID'])->isBot() &&
!ImUser::getInstance($relation['USER_ID'])->isNetwork() &&
(isset($fields[self::FIELD_LIVECHAT]) || !ImUser::getInstance($relation['USER_ID'])->isConnector())
)
{
\CIMContactList::CleanChatCache($relation['USER_ID']);
$users[] = $relation['USER_ID'];
}
}
if (!empty($users))
{
foreach ($updateDate as $name => $value)
{
Pull\Event::add($users, Array(
'module_id' => 'im',
'command' => 'chatUpdateParam',
'params' => Array(
'chatId' => (int)$this->chat['ID'],
'name' => mb_strtolower($name),
'value' => $value
),
'extra' => \Bitrix\Im\Common::getPullExtra()
));
}
}
}
return $result;
}
/**
* @param $fields
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function update($fields)
{
$result = false;
if($this->isDataLoaded())
{
foreach($fields as $field => $value)
{
if ($this->chat[$field] === $value)
{
unset($fields[$field]);
}
else
{
$this->chat[$field] = $value;
}
}
if (!empty($fields))
{
\Bitrix\Im\Model\ChatTable::update($this->chat['ID'], $fields);
$relations = \CIMChat::GetRelationById($this->chat['ID']);
foreach ($relations as $rel)
{
\CIMContactList::CleanChatCache($rel['USER_ID']);
if (isset($fields['AUTHOR_ID']))
{
if ($rel['USER_ID'] == $this->chat['AUTHOR_ID'])
{
RelationTable::update($rel['ID'], Array('MANAGER' => 'N'));
}
if ($rel['USER_ID'] == $fields['AUTHOR_ID'])
{
RelationTable::update($rel['ID'], Array('MANAGER' => 'Y'));
}
}
}
if (array_key_exists('AUTHOR_ID', $fields))
{
//CRM
if(!empty($fields['AUTHOR_ID']) && !ImUser::getInstance($fields['AUTHOR_ID'])->isBot())
{
$session = new Session();
$loadSession = $session->load(Array(
'USER_CODE' => $this->chat['ENTITY_ID']
));
if($loadSession)
{
$crmManager = new Crm($session);
$crmManager->setOperatorId($fields['AUTHOR_ID'], false);
}
}
//END CRM
$parsedUserCode = Session\Common::parseUserCode($this->chat['ENTITY_ID']);
if (\Bitrix\ImOpenLines\Connector::isLiveChat($parsedUserCode['CONNECTOR_ID']))
{
$lineId = Queue::getActualLineId([
'LINE_ID' => $parsedUserCode['CONFIG_ID'],
'USER_CODE' => $this->chat['ENTITY_ID']
]);
Pull\Event::add($parsedUserCode['CONNECTOR_USER_ID'], Array(
'module_id' => 'imopenlines',
'command' => 'sessionOperatorChange',
'params' => Array(
'chatId' => (int)$parsedUserCode['EXTERNAL_CHAT_ID'],
'operatorChatId' => (int)$this->chat['ID'],
'operator' => Rest::objectEncode(
Queue::getUserData($lineId, $fields['AUTHOR_ID'])
)
)
));
}
}
}
$result = true;
}
return $result;
}
/**
* @param string $field
* @return array|bool|false|mixed|null
*/
public function getData($field = '')
{
$result = false;
if($this->isDataLoaded())
{
if ($field)
{
$result = isset($this->chat[$field])? $this->chat[$field]: null;
}
else
{
$result = $this->chat;
}
}
return $result;
}
public static function getGuestName($chatColorCode = '')
{
if (!\Bitrix\Main\Loader::includeModule('im'))
return false;
if (\Bitrix\Im\Color::isEnabled())
{
if (!$chatColorCode)
{
\CGlobalCounter::Increment('im_chat_color_id', \CGlobalCounter::ALL_SITES, false);
$chatColorId = \CGlobalCounter::GetValue('im_chat_color_id', \CGlobalCounter::ALL_SITES);
$chatColorCode = \Bitrix\Im\Color::getCodeByNumber($chatColorId);
}
\CGlobalCounter::Increment('im_chat_color_'.$chatColorCode, \CGlobalCounter::ALL_SITES, false);
$chatColorCodeCount = \CGlobalCounter::GetValue('im_chat_color_'.$chatColorCode, \CGlobalCounter::ALL_SITES);
if ($chatColorCodeCount == 99)
{
\CGlobalCounter::Set('im_chat_color_'.$chatColorCode, 1, \CGlobalCounter::ALL_SITES, '', false);
}
$userName = Loc::getMessage('IMOL_CHAT_CHAT_NAME_COLOR_GUEST', Array("#COLOR#" => \Bitrix\Im\Color::getName($chatColorCode), "#NUMBER#" => $chatColorCodeCount+1));
}
else
{
$guestId = \CGlobalCounter::GetValue('imol_guest_id', \CGlobalCounter::ALL_SITES);
\CGlobalCounter::Increment('imol_guest_id', \CGlobalCounter::ALL_SITES, false);
if ($guestId == 99)
{
\CGlobalCounter::Set('imol_guest_id', 1, \CGlobalCounter::ALL_SITES, '', false);
}
$userName = Loc::getMessage('IMOL_CHAT_CHAT_NAME_GUEST', Array("#NUMBER#" => $guestId+1));
}
return Array(
'USER_NAME' => $userName,
'USER_COLOR' => $chatColorCode,
);
}
public static function getFieldName($field)
{
return self::$fieldAssoc[$field];
}
/**
* @param $userList
* @param bool $userCrm
* @return bool|int
* @throws Main\LoaderException
*/
public function sendJoinMessage($userList, $userCrm = false)
{
$result = false;
if (!empty($userList) && $this->isDataLoaded())
{
if (count($userList) == 1)
{
$toUserId = $userList[0];
$userName = ImUser::getInstance($toUserId)->getFullName(false);
if($userCrm === true)
{
$message = Loc::getMessage('IMOL_CHAT_ASSIGN_OPERATOR_CRM_NEW', ['#USER#' => '[USER='.$toUserId.'][/USER]']);
}
else
{
$message = Loc::getMessage('IMOL_CHAT_ASSIGN_OPERATOR_NEW', ['#USER#' => '[USER='.$toUserId.'][/USER]']);
}
}
else
{
$message = Loc::getMessage('IMOL_CHAT_ASSIGN_OPERATOR_LIST_NEW');
}
$messageId = Im::addMessage([
"TO_CHAT_ID" => $this->chat['ID'],
"FROM_USER_ID" => 0,
"MESSAGE" => $message,
"SYSTEM" => 'Y',
"IMPORTANT_CONNECTOR" => 'N'
]);
$result = $messageId;
}
return $result;
}
/**
* @param null $type
* @param string $message
* @return bool|int
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function sendAutoMessage($type = null, $message = '')
{
$result = false;
if (!$type)
{
$result = true;
}
elseif($this->isDataLoaded())
{
$session = new Session();
$resultLoadSession = $session->load([
'USER_CODE' => $this->chat['ENTITY_ID']
]);
if ($resultLoadSession)
{
if($this->validationAction($session->getData('CHAT_ID')))
{
$messageId = false;
if ($type == self::TEXT_WELCOME)
{
$messageId = (new AutomaticAction\Welcome($session))->sendMessage();
}
elseif($type == self::TEXT_DEFAULT)
{
if (!empty($message))
{
$messageId = Im::addMessage(
[
"TO_CHAT_ID" => $this->chat['ID'],
"MESSAGE" => $message,
"SYSTEM" => 'Y',
"IMPORTANT_CONNECTOR" => 'Y',
"PARAMS" => [
"CLASS" => "bx-messenger-content-item-ol-output"
]
]
);
}
}
$result = $messageId;
}
}
}
return $result;
}
/**
* @param $entityId
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public function updateChatLineData($entityId)
{
$this->update(array('ENTITY_ID' => $entityId));
//TODO: Replace with the method \Bitrix\ImOpenLines\Chat::parseLinesChatEntityId
$entity = explode('|', $entityId);
if(mb_strtolower($entity[0] == 'livechat'))
{
$relationChat = new self($entity[2]);
$relationEntityId = $entity[1] . '|' . $entity[3];
$relationChat->update(array('ENTITY_ID' => $relationEntityId));
}
}
/**
* Check before action that the same dialog was loaded.
*
* @param $loadChatId
* @return bool
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
protected function validationAction($loadChatId = 0)
{
$result = false;
if($this->isDataLoaded())
{
if($this->chat['ID'] == $loadChatId)
{
$result = true;
}
else
{
$this->close();
}
}
return $result;
}
/**
* @return bool
*/
public function isNowCreated()
{
return $this->isCreated;
}
/**
* @return bool
*/
public function isDataLoaded()
{
return $this->isDataLoaded;
}
/**
* @return BasicError|null
*/
public function getError()
{
return $this->error;
}
/**
* @param $type
* @param $sessionId
* @param $rating
* @param $toUserId
* @param null $fromUserId
* @return bool
* @throws Main\LoaderException
*/
public static function sendRatingNotify($type, $sessionId, $rating, $toUserId, $fromUserId = null)
{
$result = false;
$toUserId = intval($toUserId);
$fromUserId = intval($fromUserId);
if ($fromUserId <= 0)
{
$fromUserId = $GLOBALS['USER']->GetId();
}
if (
\Bitrix\Main\Loader::includeModule('im') &&
in_array($type, Array(self::RATING_TYPE_CLIENT, self::RATING_TYPE_HEAD, self::RATING_TYPE_HEAD_AND_COMMENT, self::RATING_TYPE_COMMENT)) &&
$toUserId > 0 &&
$toUserId != $fromUserId
)
{
$commentValue = null;
$ratingValue = null;
if($type == self::RATING_TYPE_CLIENT || $type == self::RATING_TYPE_HEAD)
{
$rating = intval($rating);
if ($rating < 6 && $rating > 0)
{
$ratingValue = $rating;
}
}
elseif($type == self::RATING_TYPE_COMMENT)
{
$commentValue = htmlspecialcharsbx($rating);
}
elseif($type == self::RATING_TYPE_HEAD_AND_COMMENT)
{
if ($rating['vote'] < 6 && $rating['vote'] > 0)
{
$ratingValue = $rating['vote'];
}
$commentValue = htmlspecialcharsbx($rating['comment']);
}
if($commentValue !== null || $ratingValue !== null)
{
$userName = '';
if ($type == self::RATING_TYPE_CLIENT)
{
$notifyMessageName = $ratingValue == self::RATING_VALUE_DISLIKE? 'IMOL_CHAT_NOTIFY_RATING_CLIENT_DISLIKE_NEW': 'IMOL_CHAT_NOTIFY_RATING_CLIENT_LIKE_NEW';
$ratingImage = $ratingValue == self::RATING_VALUE_DISLIKE? '[dislike]': '[like]';
$ratingText = Loc::getMessage('IMOL_CHAT_NOTIFY_RATING_VALUE_'.($ratingValue == self::RATING_VALUE_DISLIKE? 'DISLIKE': 'LIKE'));
$commentText = '';
}
else
{
$userName = ImUser::getInstance($fromUserId)->getFullName(false);
$userGender = ImUser::getInstance($fromUserId)->getGender();
if($type == self::RATING_TYPE_HEAD)
{
$notifyMessageName = 'IMOL_CHAT_NOTIFY_RATING_HEAD_' . $userGender . '_LIKE';
$ratingImage = "[RATING=" . $ratingValue . "]";
$ratingText = Loc::getMessage('IMOL_CHAT_NOTIFY_RATING_VALUE_' . $ratingValue);
$commentText = '';
}
elseif($type == self::RATING_TYPE_COMMENT)
{
$notifyMessageName = 'IMOL_CHAT_NOTIFY_RATING_HEAD_' . $userGender . '_COMMENT';
$ratingImage = "[RATING=" . $ratingValue . "]";
$ratingText = '';
$commentText = $commentValue;
}
else
{
$notifyMessageName = 'IMOL_CHAT_NOTIFY_RATING_HEAD_'.$userGender.'_LIKE_AND_COMMENT';
$ratingImage = "[RATING=" . $ratingValue . "]";
$ratingText = Loc::getMessage('IMOL_CHAT_NOTIFY_RATING_VALUE_' . $ratingValue);
$commentText = $commentValue;
}
}
$userViewChat = \CIMContactList::InRecent($toUserId, IM_MESSAGE_OPEN_LINE, $sessionId);
\CIMNotify::DeleteBySubTag("IMOL|RATING|".$type.'|'.$sessionId);
\CIMNotify::Add(array(
"TO_USER_ID" => $toUserId,
"NOTIFY_TYPE" => IM_NOTIFY_SYSTEM,
"NOTIFY_MODULE" => "imopenlines",
"NOTIFY_EVENT" => $type == self::RATING_TYPE_CLIENT? 'rating_client': 'rating_head',
"NOTIFY_SUB_TAG" => "IMOL|RATING|".$type.'|'.$sessionId,
"NOTIFY_MESSAGE" => '[b]'.Loc::getMessage('IMOL_CHAT_NOTIFY_RATING_TITLE').'[/b][br]'.Loc::getMessage($notifyMessageName, Array(
'#NUMBER#' => '[CHAT=imol|'.$sessionId.']'.$sessionId.'[/CHAT]',
'#USER#' => '[USER='.$fromUserId.']'.$userName.'[/USER]',
'#RATING#' => $ratingImage,
'#COMMENT#' => $commentText,
)),
"NOTIFY_MESSAGE_OUT" => '[b]'.Loc::getMessage('IMOL_CHAT_NOTIFY_RATING_TITLE').'[/b][br]'.Loc::getMessage($notifyMessageName, Array(
'#NUMBER#' => '[URL=/online/?IM_HISTORY=imol|'.$sessionId.']'.$sessionId.'[/URL]',
'#USER#' => $userName,
'#RATING#' => $ratingText,
'#COMMENT#' => $commentText,
)),
"RECENT_ADD" => $userViewChat? 'Y': 'N'
));
$result = true;
}
}
return $result;
}
/**
* @return array
*/
public static function onGetNotifySchema()
{
return [
"imopenlines" => [
"rating_client" => [
"NAME" => Loc::getMessage('IMOL_CHAT_NOTIFY_SCHEMA_RATING_CLIENT_new'),
"LIFETIME" => 86400*7
],
"rating_head" => [
"NAME" => Loc::getMessage('IMOL_CHAT_NOTIFY_SCHEMA_RATING_HEAD'),
"LIFETIME" => 86400*7
],
],
];
}
/**
* @param $icon
* @param null $lang
* @return array|bool
*/
public static function onAppLang($icon, $lang = null)
{
if ($icon === 'quick')
{
$title = Loc::getMessage('IMOL_CHAT_APP_ICON_QUICK_TITLE', null, $lang);
$description = Loc::getMessage('IMOL_CHAT_APP_ICON_QUICK_DESCRIPTION', null, $lang);
$result = false;
if ($title <> '')
{
$result = [
'TITLE' => $title,
'DESCRIPTION' => $description,
'COPYRIGHT' => ''
];
}
}
else if ($icon === 'imessage')
{
$result = [
'TITLE' => 'Apple Business Chat extension',
'DESCRIPTION' => '',
'COPYRIGHT' => ''
];
}
return $result;
}
/**
* @param $dialogId
* @param $user
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public static function chatAutoAddRecent($dialogId, $user)
{
if (Main\Loader::includeModule("im"))
{
if (!is_array($user))
{
$user = [$user];
}
foreach($user as $userId)
{
\Bitrix\Im\Recent::show($dialogId, $userId);
}
}
}
/**
* Parsing entity Id into components for open line chat.
*
* @param $entityId
* @return array
*/
public static function parseLinesChatEntityId($entityId)
{
$result = [
'connectorId' => null,
'lineId' => null,
'connectorChatId' => null,
'connectorUserId' => null
];
if(!empty($entityId))
{
list($result['connectorId'], $result['lineId'], $result['connectorChatId'], $result['connectorUserId']) = explode('|', $entityId);
}
return $result;
}
/**
* Parsing entity Id into components for open live chat.
*
* @param $entityId
* @return array
*/
public static function parseLiveChatEntityId($entityId)
{
$result = [
'connectorId' => null,
'lineId' => null,
];
if(!empty($entityId))
{
list($result['connectorId'], $result['lineId']) = explode('|', $entityId);
}
return $result;
}
/**
* @deprecated Use \Bitrix\ImOpenLines\Crm\Common::getLastChatIdByCrmEntity instead.
*
* @param $crmEntityType
* @param $crmEntityId
* @return int
* @throws Main\ArgumentException
* @throws Main\LoaderException
* @throws Main\ObjectPropertyException
* @throws Main\SystemException
*/
public static function getLastChatIdByCrmEntity($crmEntityType, $crmEntityId): int
{
return \Bitrix\ImOpenLines\Crm\Common::getLastChatIdByCrmEntity($crmEntityType, $crmEntityId);
}
public static function hasAccess(int $chatId): bool
{
if (!Main\Loader::includeModule('im'))
{
return false;
}
$chat = \Bitrix\Im\Model\ChatTable::getByPrimary($chatId, ['select' => ['TYPE', 'ENTITY_TYPE', 'ENTITY_DATA_1']])->fetch();
if (!$chat)
{
return false;
}
if (!(
$chat['TYPE'] === \Bitrix\Im\Chat::TYPE_OPEN_LINE
|| $chat['TYPE'] === \Bitrix\Im\Chat::TYPE_GROUP && $chat['ENTITY_TYPE'] === 'LINES'
))
{
return false;
}
$crmEntityType = null;
$crmEntityId = null;
if ($chat['ENTITY_DATA_1'] <> '')
{
$fieldData = explode("|", $chat['ENTITY_DATA_1']);
if ($fieldData[0] === 'Y')
{
$crmEntityType = $fieldData[1];
$crmEntityId = $fieldData[2];
}
}
return \Bitrix\ImOpenLines\Config::canJoin($chatId, $crmEntityType, $crmEntityId);
}
public static function getChatIdBySession(int $sessionId)
{
if (!$sessionId)
{
return null;
}
$session = \Bitrix\ImOpenLines\Model\SessionTable::getById($sessionId)->fetch();
if (!$session)
{
return null;
}
return (int)$session['CHAT_ID'];
}
public static function getChatIdByUserCode(string $userCode)
{
if (!Main\Loader::includeModule('im'))
{
return null;
}
$chatData = \Bitrix\Im\Model\ChatTable::getList([
'select' => ['ID'],
'filter' => [
'=ENTITY_TYPE' => 'LINES',
'=ENTITY_ID' => $userCode,
]
])->fetch();
if (!$chatData)
{
return null;
}
return $chatData['ID'];
}
}