Contacts > Chat * @copyright Tamaranga */ class ChatPage extends AccountPage { /** @var array */ public $i = []; /** @var array */ public $me = []; /** @var bool */ public $more; /** @var array */ public $messages = []; /** @var array */ public $items = []; /** @var string */ public $tme = ''; /** @var int */ public $companyId = 0; public function init() { parent::init(); $this->setTitle(_t('users', 'Chat')); $this->setKey('internalmail.chat.page'); $this->setTemplate('account/chat/page', 'internalmail'); } public function handle() { $userLogin = $this->input->getpost('user', TYPE_NOTAGS); if (empty($userLogin)) { if (! bff::businessEnabled()) { return $this->errors->error404(); } $companyKey = $this->input->getpost('company', TYPE_NOTAGS); if (preg_match('/(.*)\-([\d]+)$/Ui', $companyKey, $matches) && empty($matches[2])) { return $this->errors->error404(); } $companyId = intval($matches[2]); } else { $company = $this->input->getpost('company', TYPE_BOOL); if ($company) { $this->companyId = User::companyID(); } } if (User::guest()) { $p = []; if ($userLogin) { $p['user'] = $userLogin; if ($company) { $p['company'] = 1; } } else { $p['company'] = $companyKey; } return Redirect::to(Users::url('login', ['ref' => InternalMail::url('account.chat', $p)])); } if ($userLogin) { $this->loadInterlocutorUser($userLogin); } else { $this->loadInterlocutorCompany($companyId, $companyKey); } if (empty($this->i['user_id'])) { return InternalMail::showForbidden( _t('', 'Error'), _t('internalmail', 'The specified interlocutor was not found or was blocked') ); } if (! empty($this->i['is_company'])) { if (! in_array($this->i['status'], [Business::STATUS_ACTIVE, Business::STATUS_BLOCKED])) { return InternalMail::showForbidden( _t('', 'Error'), _t('internalmail', 'Chat with the company is temporarily unavailable') ); } } $this->loadMe(); return $this; } public function blocks() { $this->addTemplateBlock('list', 'account/chat/list', 'internalmail'); } public function onSubmitAction() { $this->loadList(); $this->with('messages', $this->messages); $this->with('tme', $this->tme); $this->with('imgDefault', Listings::itemImages()->urlDefault('m:svg')); return $this->getActionResponse([ 'list' => $this->getBlock('list'), 'more' => $this->more, ]); } public function onSendAction() { $this->iframeResponse = true; $response = []; do { $message = $this->input->post('message', TYPE_STR); $message = InternalMail::model()->cleanMessage($message, 4000, false); if (mb_strlen($message) < 2) { $this->errors->set(_t('internalmail', 'Message text is too short'), 'message'); break; } if ( $this->i['im_noreply'] || InternalMail::model()->isUserInFolder($this->me['user_id'], $this->i['user_id'], $this->companyId, InternalMail::FOLDER_IGNORE) ) { $this->errors->set(_t('internalmail', 'User prohibited sending messages to him')); break; } InternalMail::attach()->setAssignErrors(true); $attachment = InternalMail::attachUpload(); if ($this->errors->any()) { break; } $res = InternalMail::model()->sendMessage($this->me['user_id'], $this->i['user_id'], $message, ['company_id' => $this->companyId, 'attach' => $attachment]); if (empty($res)) { if ($this->errors->no()) { $this->errors->reloadPage(); } break; } else { if (!$this->i['is_company'] && !$this->i['activated']) { # для неактивированного аккаунта отправляем спец. письмо $activateData = Users::getActivationInfo([ 'msg' => join('-', [$this->i['user_id'], $this->me['user_id'], rand(12345, 54321)]) ], $this->i['activate_key']); if (! isset($this->i['lang'])) { $user = Users::model()->userDataEnotify($this->i['user_id']); $this->i['lang'] = $user['lang'] ?? $this->locale->current(); } if (empty($this->i['fake'])) { $this->app->sendMailTemplate([ 'author' => User::login(), 'link_activate' => $activateData['link'], 'message' => tpl::truncate(strip_tags($message), 250), 'user_id' => $this->i['user_id'], ], 'internalmail_new_message_newuser', $this->i['email'], false, '', '', $this->i['lang']); } # продлеваем период действия ссылки активации Users::model()->userSave($this->i['user_id'], [ 'activate_expire' => $activateData['expire'], ]); } } } while (false); return $this->getActionResponse($response); } public function data() { $data = parent::data(); $this->loadList(); $data['imgDefault'] = Listings::itemImages()->urlDefault('m:svg'); $data['url_back'] = HTML::escape(InternalMail::url('account.messages')); $data['folders'] = InternalMail::model()->getInterlocutorFolders($this->me['user_id'], [$this->i['user_id']], true); if (! empty($data['folders'])) { $data['folders'] = reset($data['folders']); if ($this->companyId) { $data['folders'] = $data['folders'][$this->companyId] ?? []; } else { $data['folders'] = $data['folders'][0] ?? []; } } $this->i['ignoring'] = ( $this->i['im_noreply'] || ( InternalMail::foldersEnabled() && InternalMail::model()->isUserInFolder($this->me['user_id'], $this->i['user_id'], $this->companyId, InternalMail::FOLDER_IGNORE) ) ); return $data; } protected function userFieds() { return [ 'user_id', 'avatar', 'sex', 'name', 'login', 'email', 'im_noreply', 'fake', 'blocked', 'blocked_reason', 'activated', 'activate_key', 'last_activity', ]; } public function loadInterlocutorUser($login) { $data = Users::model()->userDataByFilter(['login' => $login], $this->userFieds()); if (empty($data)) { return; } $data['avatar_normal'] = UsersAvatar::url( $data['user_id'], $data['avatar'], null, $data['sex'] ); $data['avatar_block'] = UsersAvatar::block($data['user_id'], $data); $data['avatar'] = UsersAvatar::url($data['user_id'], $data['avatar'], null, $data['sex']); $data['url_profile'] = Users::urlProfile($data['login']); $data['url_title'] = (! empty($data['name']) ? $data['name'] : $data['login']); if ($data['blocked']) { $data['blocked_message'] = _t( 'users', 'User blocked due to: [reason]', [ 'reason' => $data['blocked_reason'], ] ); } $data['is_company'] = false; $this->i = $data; } public function loadInterlocutorCompany($companyId, $companyKey) { $data = Business::model()->companyData($companyId, [ 'id','user_id','title','link','logo','status','blocked_reason', ]); if (empty($data)) { return; } $this->companyId = $companyId; $companysLogo = Business::logo(); $data['avatar_normal'] = $companysLogo->url($companyId, $data['logo'], $companysLogo::szSmall, false, true); $data['avatar'] = $companysLogo->url($companyId, $data['logo'], $companysLogo::szMini, false, true); $data['blocked'] = ($data['status'] == Business::STATUS_BLOCKED); $data['url_profile'] = Url::dynamic($data['link']); $data['url_title'] = $data['title']; $data['company_key'] = $companyKey; $data['im_noreply'] = false; if ($data['blocked']) { $data['blocked_message'] = _t('internalmail', 'The company was blocked due to: [reason]', [ 'reason' => $data['blocked_reason'], ]); } $data['is_company'] = true; $this->i = $data; } public function loadMe($userId = 0) { if (! $userId) { $userId = User::id(); } $data = Users::model()->userData($userId, $this->userFieds()); $data['avatar'] = UsersAvatar::url($userId, $data['avatar'], null, $data['sex']); $this->me = $data; } public function loadList() { $perPage = 100; $opts = [ 'order' => 'M.id DESC', 'limit' => $this->db->prepareLimit(0, $perPage + 1), ]; $first = $this->input->post('first', TYPE_UINT); $last = $this->input->post('last', TYPE_UINT); $this->tme = $this->input->post('tme', TYPE_STR); if ($first) { $opts['filter'] = ['id' => ['<', $first]]; } elseif ($last) { $opts['filter'] = ['id' => ['>', $last]]; } $messages = InternalMail::model()->getConversationMessages($this->me['user_id'], $this->i['user_id'], $this->companyId, false, $opts); $more = count($messages) > $perPage; if ($more) { array_pop($messages); } $this->more = $more; $messages = array_reverse($messages); # прикрепляем данные об объявлениях if (!empty($messages)) { $itemsID = []; foreach ($messages as $v) { if ($v['item_id']) { $itemsID[] = $v['item_id']; } } if (!empty($itemsID)) { $this->items = Listings::model()->itemsListChat($itemsID); } } # формируем список сообщений foreach ($messages as &$v) { $v['created_date'] = strtotime($v['created_date']); } unset($v); $this->messages = $messages; # отмечаем как прочитанные все новые сообщения, в которых пользователь является получателем $newItems = []; $newViewed = 0; if (!empty($messages)) { foreach ($messages as $v) { if ($v['new']) { $newViewed++; if ($v['item_id'] > 0) { if (!isset($newItems[$v['item_id']])) { $newItems[$v['item_id']] = 0; } $newItems[$v['item_id']]++; } } } } if ($newViewed > 0) { InternalMail::model()->setMessagesReaded($this->me['user_id'], $this->i['user_id'], $this->companyId, true); User::refresh(); } if (!empty($newItems)) { Listings::model()->itemsListChatSetReaded($newItems); } } }