1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
PrivateChat.php
См. документацию.
1<?php
2
3namespace Bitrix\Im\V2\Chat;
4
5use Bitrix\Im\Model\RelationTable;
6use Bitrix\Im\Model\RecentTable;
7use Bitrix\Im\User;
8use Bitrix\Im\Recent;
9use Bitrix\Im\Notify;
10use Bitrix\Im\V2\Call\CallToken;
11use Bitrix\Im\V2\Chat;
12use Bitrix\Im\V2\Entity\User\NullUser;
13use Bitrix\Im\V2\Entity\User\UserBot;
14use Bitrix\Im\V2\Entity\User\UserPopupItem;
15use Bitrix\Im\V2\Message;
16use Bitrix\Im\V2\Message\Send\PushService;
17use Bitrix\Im\V2\Message\Send\SendingConfig;
18use Bitrix\Im\V2\MessageCollection;
19use Bitrix\Im\V2\Relation;
20use Bitrix\Im\V2\Relation\AddUsersConfig;
21use Bitrix\Im\V2\Rest\PopupData;
22use Bitrix\Im\V2\Rest\PopupDataAggregatable;
23use Bitrix\Im\V2\Result;
24use Bitrix\Im\V2\Service\Context;
25use Bitrix\Im\V2\Service\Locator;
26use Bitrix\ImBot\Bot\Network;
27use Bitrix\Main\Loader;
28use Bitrix\Main\Localization\Loc;
29use Bitrix\Main\Type\DateTime;
30use Bitrix\Pull\Event;
31
32class PrivateChat extends Chat implements PopupDataAggregatable
33{
34 protected const EXTRANET_CAN_SEE_HISTORY = true;
35 protected array $dialogIdCache = [];
36
37 protected function getDefaultType(): string
38 {
39 return self::IM_TYPE_PRIVATE;
40 }
41
42 public function setDialogId(string $dialogId): self
43 {
44 parent::setDialogId($dialogId);
45 $this->dialogIdCache[$this->getContext()->getUserId()] = $dialogId;
46
47 return $this;
48 }
49
50 protected function checkAccessInternal(int $userId): Result
51 {
52 return $this->getCompanion($userId)->checkAccess($userId);
53 }
54
59 public function allowMention(): bool
60 {
61 return false;
62 }
63
64 public function setManageSettings(string $manageSettings): Chat
65 {
66 return $this;
67 }
68
69 public function setManageUsersAdd(string $manageUsersAdd): Chat
70 {
71 return $this;
72 }
73
74 public function setManageUsersDelete(string $manageUsersDelete): Chat
75 {
76 return $this;
77 }
78
79 public function setManageUI(string $manageUI): Chat
80 {
81 return $this;
82 }
83
84 public function setManageMessages(string $manageMessages): Chat
85 {
86 return $this;
87 }
88
89 public function getDefaultManageMessagesAutoDelete(): string
90 {
91 return Chat::MANAGE_RIGHTS_MEMBER;
92 }
93
94 public function getDialogId(?int $contextUserId = null): ?string
95 {
96 $userId = $contextUserId ?? $this->getContext()->getUserId();
97 if (!isset($this->dialogIdCache[$userId]))
98 {
99 $this->dialogIdCache[$userId] = $this->getCompanion($contextUserId)->getId();
100 }
101
102 return $this->dialogIdCache[$userId];
103 }
104
105 public function hasDialogId(): bool
106 {
107 return $this->dialogId !== null;
108 }
109
110 public function getDialogContextId(): ?string
111 {
112 return $this->getDialogId() . ':' .$this->getContext()->getUserId();
113 }
114
115 public function getStartId(?int $userId = null): int
116 {
117 return 0;
118 }
119
120 public function getMultidialogData(): array
121 {
122 if (!Loader::includeModule('imbot'))
123 {
124 return [];
125 }
126
127 $bot = null;
128
129 foreach ($this->getRelations() as $relation)
130 {
131 $user = $relation->getUser();
132
133 if (!$user instanceof UserBot)
134 {
135 continue;
136 }
137
138 $botType = $user->getBotData()->toRestFormat()['type'] ?? null;
139 if ($botType === 'support24' || $botType === 'network')
140 {
141 $bot = $user;
142 }
143 }
144
145 if (!$bot)
146 {
147 return [];
148 }
149
150 $otherUser = $this->getCompanion($bot->getId());
151
152 return Network::getBotAsMultidialog($bot->getId(), $otherUser->getId());
153 }
154
155 public function filterUsersToMentionAnchor(array $userIds): array
156 {
157 $companionId = $this->getCompanionId();
158 if (in_array($companionId, $userIds, true))
159 {
160 return [$companionId => $companionId];
161 }
162
163 return [];
164 }
165
166 protected function prepareMessage(Message $message): void
167 {
168 parent::prepareMessage($message);
169
170 if (!$message->getAuthorId())
171 {
172 $message->setAuthorId($this->getContext()->getUserId());
173 }
174
176 ->setNotifyModule('im')
177 ->setNotifyEvent($message->isSystem() ? Notify::EVENT_PRIVATE_SYSTEM : Notify::EVENT_PRIVATE)
178 ;
179 }
180
182 {
183 $result = parent::onBeforeMessageSend($message, $config);
184
185 if (!$message->getAuthorId())
186 {
187 return $result->addError(new Message\MessageError(Message\MessageError::WRONG_SENDER));
188 }
189
190 return $result;
191 }
192
193 public function getCompanion(?int $userId = null): \Bitrix\Im\V2\Entity\User\User
194 {
195 $userId = $userId ?? $this->getContext()->getUserId();
196
197 $relations = $this->getRelations();
198
199 if (!$relations->hasUser($userId, $this->getChatId()))
200 {
201 return new NullUser();
202 }
203
204 foreach ($relations as $relation)
205 {
206 if ($relation->getUserId() !== $userId)
207 {
208 return $relation->getUser();
209 }
210 }
211
212 return new NullUser();
213 }
214
215 public function getCompanionId(?int $userId = null): ?int
216 {
217 return $this->getCompanion($userId)->getId();
218 }
219
220 protected function getUsersToAddToRecent(): array
221 {
222 // We always return both users because the merge strategy is used for private chats.
223 return $this->getRelations()->getUserIds();
224 }
225
226 protected function updateRecentItems(Message $message): void
227 {
228 // We do not update recent items because the merge strategy is chosen for private chats.
229 return;
230 }
231
233 {
234 $fields = parent::getFieldsForRecent($userId, $message);
235 if (empty($fields))
236 {
237 return [];
238 }
239 $fields['ITEM_ID'] = $this->getCompanion($userId)->getId();
240
241 return $fields;
242 }
243
244 protected function insertRecent(array $fields): void
245 {
246 foreach ($fields as $item)
247 {
248 RecentTable::merge($item, $item, ['USER_ID', 'ITEM_TYPE', 'ITEM_ID']);
249 }
250 }
251
252 public function getDisplayedTitle(): ?string
253 {
254 return Loc::getMessage(
255 'IM_PRIVATE_CHAT_TITLE',
256 [
257 //todo: replace to $this->getContext()->getUser() when ->getUser will return V2 User
258 '#CHAT_MEMBER_NAME_1#' => \Bitrix\Im\V2\Entity\User\User::getInstance($this->getContext()->getUserId())->getName(),
259 '#CHAT_MEMBER_NAME_2#' => $this->getCompanion()->getName(),
260 ]
261 );
262 }
263
264 public function addUsers(array $userIds, AddUsersConfig $config = new AddUsersConfig()): Chat
265 {
266 return $this;
267 }
268
270 {
271 $pushFormat = new Message\PushFormat($message);
272 $push = $pushFormat->formatMessageUpdate();
273 $authorId = $message->getAuthorId();
274 $opponentId = $this->getCompanion($authorId)->getId();
275
276 $push['params']['dialogId'] = $authorId;
277 $push['params']['fromUserId'] = $authorId;
278 $push['params']['toUserId'] = $opponentId;
279 Event::add($opponentId, $push);
280
281 $push['params']['dialogId'] = $opponentId;
282 $push['params']['fromUserId'] = $opponentId;
283 $push['params']['toUserId'] = $authorId;
284 Event::add($authorId, $push);
285 }
286
291
292 protected function sendPushReadSelf(MessageCollection $messages, int $lastId, int $counter): void
293 {
294 $companionId = $this->getDialogId();
295 \Bitrix\Pull\Event::add($this->getContext()->getUserId(), [
296 'module_id' => 'im',
297 'command' => 'readMessage',
298 'params' => [
299 'dialogId' => $companionId,
300 'chatId' => $this->getChatId(),
301 'senderId' => $this->getContext()->getUserId(),
302 'id' => (int)$companionId,
303 'userId' => (int)$companionId,
304 'lastId' => $lastId,
305 'counter' => $counter,
306 'muted' => false,
307 'unread' => Recent::isUnread($this->getContext()->getUserId(), $this->getType(), $this->getDialogId() ?? ''),
308 'viewedMessages' => $messages->getIds(),
309 'counterType' => $this->getCounterType()->value,
310 'recentConfig' => $this->getRecentConfig()->toPullFormat(),
311 ],
312 'extra' => \Bitrix\Im\Common::getPullExtra()
313 ]);
314 }
315
317 {
318 $companionId = $this->getDialogId();
319 $pushMessage = [
320 'module_id' => 'im',
321 'command' => 'readMessageOpponent',
322 'expiry' => 3600,
323 'params' => [
324 'dialogId' => $this->getContext()->getUserId(),
325 'chatId' => $this->getChatId(),
326 'userId' => $this->getContext()->getUserId(),
327 'userName' => User::getInstance($this->getContext()->getUserId())->getFullName(false),
328 'lastId' => $lastId,
329 'date' => (new DateTime())->format('c'),
330 'chatMessageStatus' => $this->getReadService()->getChatMessageStatus($this->getChatId()),
331 'viewedMessages' => $messages->getIds(),
332 ],
334 ];
335 \Bitrix\Pull\Event::add($companionId, $pushMessage);
336
337 return $pushMessage;
338 }
339
340 protected function sendEventRead(int $startId, int $endId, int $counter, bool $byEvent): void
341 {
342 foreach(GetModuleEvents("im", "OnAfterUserRead", true) as $arEvent)
343 {
344 ExecuteModuleEventEx($arEvent, array(Array(
345 'DIALOG_ID' => $this->getDialogId(),
346 'CHAT_ID' => $this->getChatId(),
347 'CHAT_ENTITY_TYPE' => 'USER',
348 'CHAT_ENTITY_ID' => '',
349 'START_ID' => $startId,
350 'END_ID' => $endId,
351 'COUNT' => $counter,
352 'USER_ID' => $this->getContext()->getUserId(),
353 'BY_EVENT' => $byEvent
354 )));
355 }
356 }
357
372 public static function find(array $params, ?Context $context = null): Result
373 {
374 $result = new Result;
375
376 if (isset($params['CHAT_ID']))
377 {
378 $chatId = (int)$params['CHAT_ID'];
379 $relations = \CIMChat::getRelationById($chatId, false, true, false);
380
381 $params['TO_USER_ID'] = (int)$params['FROM_USER_ID'];//check for self-personal chat
382 foreach ($relations as $rel)
383 {
384 if (
385 $params['TO_USER_ID']
386 && $rel['USER_ID'] == $params['FROM_USER_ID']
387 )
388 {
389 continue;
390 }
391
392 $params['TO_USER_ID'] = (int)$rel['USER_ID'];
393 }
394 }
395
396 if (empty($params['FROM_USER_ID']))
397 {
398 $context = $context ?? Locator::getContext();
399 $params['FROM_USER_ID'] = $context->getUserId();
400 }
401
402 $params['FROM_USER_ID'] = (int)$params['FROM_USER_ID'];
403 $params['TO_USER_ID'] = (int)$params['TO_USER_ID'];
404
405 if ($params['FROM_USER_ID'] <= 0)
406 {
407 return $result->addError(new ChatError(ChatError::WRONG_SENDER));
408 }
409 if ($params['TO_USER_ID'] <= 0)
410 {
411 return $result->addError(new ChatError(ChatError::WRONG_RECIPIENT));
412 }
413
415
416 $res = $connection->query("
417 SELECT
418 C.*
419 FROM
420 b_im_chat C,
421 b_im_relation RF,
422 b_im_relation RT
423 WHERE
424 C.ID = RT.CHAT_ID
425 AND RF.CHAT_ID = RT.CHAT_ID
426 AND C.TYPE = '" . self::IM_TYPE_PRIVATE . "'
427 AND RF.USER_ID = " . $params['FROM_USER_ID'] . "
428 AND RT.USER_ID = " . $params['TO_USER_ID'] . "
429 AND RF.MESSAGE_TYPE = '" . self::IM_TYPE_PRIVATE . "'
430 AND RT.MESSAGE_TYPE = '" . self::IM_TYPE_PRIVATE . "'
431 ");
432 if ($row = $res->fetch())
433 {
434 $result->setResult([
435 'ID' => (int)$row['ID'],
436 'TYPE' => $row['TYPE'],
437 'ENTITY_TYPE' => $row['ENTITY_TYPE'],
438 'ENTITY_ID' => $row['ENTITY_ID'],
439 ]);
440 }
441
442 return $result;
443 }
444
445 public function add(array $params, ?Context $context = null): Result
446 {
447 $result = new Result;
448
449 $paramsResult = $this->prepareParams($params);
450 if (!$paramsResult->isSuccess())
451 {
452 return $result->addErrors($paramsResult->getErrors());
453 }
454
455 $params = $paramsResult->getResult();
456
457 if (!\Bitrix\Im\Dialog::hasAccess($params['FROM_USER_ID'], $params['TO_USER_ID']))
458 {
459 return $result->addError(new ChatError(ChatError::ACCESS_DENIED));
460 }
461
462 if ($params['FROM_USER_ID'] == $params['TO_USER_ID'])
463 {
464 return (new FavoriteChat($params))->add($params);
465 }
466
467 $chatResult = self::find($params);
468 if ($chatResult->isSuccess() && $chatResult->hasResult())
469 {
470 $chatParams = $chatResult->getResult();
471
472 return $result->setResult([
473 'CHAT_ID' => (int)$chatParams['ID'],
474 'CHAT' => self::load($chatParams),
475 ]);
476 }
477
478 $chat = new static($params);
479 $chat->save();
480
481 if ($chat->getChatId() <= 0)
482 {
483 return $result->addError(new ChatError(ChatError::CREATION_ERROR));
484 }
485
486 \Bitrix\Im\Model\RelationTable::add([
487 'CHAT_ID' => $chat->getChatId(),
488 'MESSAGE_TYPE' => \IM_MESSAGE_PRIVATE,
489 'USER_ID' => $params['FROM_USER_ID'],
490 ]);
491 \Bitrix\Im\Model\RelationTable::add([
492 'CHAT_ID' => $chat->getChatId(),
493 'MESSAGE_TYPE' => \IM_MESSAGE_PRIVATE,
494 'USER_ID' => $params['TO_USER_ID'],
495 ]);
496
497 $botJoinFields = [
498 'CHAT_TYPE' => \IM_MESSAGE_PRIVATE,
499 'MESSAGE_TYPE' => \IM_MESSAGE_PRIVATE
500 ];
501 if (
502 User::getInstance($params['FROM_USER_ID'])->isExists()
503 && !User::getInstance($params['FROM_USER_ID'])->isBot()
504 )
505 {
506 $botJoinFields['BOT_ID'] = $params['TO_USER_ID'];
507 $botJoinFields['USER_ID'] = $params['FROM_USER_ID'];
508 $botJoinFields['TO_USER_ID'] = $params['TO_USER_ID'];
509 $botJoinFields['FROM_USER_ID'] = $params['FROM_USER_ID'];
510 \Bitrix\Im\Bot::onJoinChat($params['FROM_USER_ID'], $botJoinFields);
511 }
512 elseif (
513 User::getInstance($params['TO_USER_ID'])->isExists()
514 && !User::getInstance($params['TO_USER_ID'])->isBot()
515 )
516 {
517 $botJoinFields['BOT_ID'] = $params['FROM_USER_ID'];
518 $botJoinFields['USER_ID'] = $params['TO_USER_ID'];
519 $botJoinFields['TO_USER_ID'] = $params['TO_USER_ID'];
520 $botJoinFields['FROM_USER_ID'] = $params['FROM_USER_ID'];
521 \Bitrix\Im\Bot::onJoinChat($params['TO_USER_ID'], $botJoinFields);
522 }
523
524 $chat->isFilledNonCachedData = false;
525
526 return $result->setResult([
527 'CHAT_ID' => $chat->getChatId(),
528 'CHAT' => $chat,
529 ]);
530 }
531
532 protected function prepareParams(array $params = []): Result
533 {
534 $result = new Result();
535
536 if (isset($params['FROM_USER_ID']))
537 {
538 $params['AUTHOR_ID'] = $params['FROM_USER_ID'] = (int)$params['FROM_USER_ID'];
539 }
540 if ($params['FROM_USER_ID'] <= 0)
541 {
542 return $result->addError(new ChatError(ChatError::WRONG_SENDER));
543 }
544
545 if (isset($params['TO_USER_ID']))
546 {
547 $params['TO_USER_ID'] = (int)$params['TO_USER_ID'];
548 }
549 else
550 {
551 $params['TO_USER_ID'] = 0;
552 }
553
554 if ($params['TO_USER_ID'] <= 0)
555 {
556 return $result->addError(new ChatError(ChatError::WRONG_RECIPIENT));
557 }
558
559 $result->setResult($params);
560
561 return $result;
562 }
563
564 protected function addIndex(): Chat
565 {
566 return $this;
567 }
568
569 protected function updateIndex(): Chat
570 {
571 return $this;
572 }
573
574 public function getPopupData(array $excludedList = []): PopupData
575 {
576 $userId = $this->getContext()->getUserId();
577
578 return parent::getPopupData($excludedList)
579 ->add(new UserPopupItem([$userId, $this->getCompanion()->getId()]))
580 ->add(new Chat\MessagesAutoDelete\MessagesAutoDeleteConfigs([$this->getChatId()]))
581 ->add(new CallToken($this->getId(), $userId))
582 ;
583 }
584
585 public static function getDialogIds(array $chatIds, int $contextUserId): array
586 {
587 $dialogIds = [];
588
589 if (empty($chatIds))
590 {
591 return [];
592 }
593
594 $result = RelationTable::query()
595 ->setSelect(['CHAT_ID', 'USER_ID'])
596 ->whereIn('CHAT_ID', $chatIds)
597 ->where('MESSAGE_TYPE', Chat::IM_TYPE_PRIVATE)
598 ->whereNot('USER_ID', $contextUserId)
599 ->fetchAll()
600 ;
601
602 foreach ($result as $row)
603 {
604 $dialogIds[(int)$row['CHAT_ID']] = $row['USER_ID'];
605 }
606
607 return $dialogIds;
608 }
609}
$connection
Определения actionsdefinitions.php:38
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static getType($chatData, bool $camelCase=true)
Определения chat.php:45
static getPullExtra()
Определения common.php:127
static hasAccess($dialogId, $userId=null)
Определения dialog.php:184
const EVENT_PRIVATE_SYSTEM
Определения notify.php:24
const EVENT_PRIVATE
Определения notify.php:23
static isUnread(int $userId, string $itemType, string $dialogId)
Определения recent.php:1819
const CREATION_ERROR
Определения ChatError.php:23
const WRONG_RECIPIENT
Определения ChatError.php:14
const ACCESS_DENIED
Определения ChatError.php:19
const WRONG_SENDER
Определения ChatError.php:13
checkAccessInternal(int $userId)
Определения PrivateChat.php:50
getFieldsForRecent(int $userId, Message $message)
Определения PrivateChat.php:232
setDialogId(string $dialogId)
Определения PrivateChat.php:42
prepareMessage(Message $message)
Определения PrivateChat.php:166
sendPushUpdateMessage(Message $message)
Определения PrivateChat.php:269
setManageUsersDelete(string $manageUsersDelete)
Определения PrivateChat.php:74
sendPushReadSelf(MessageCollection $messages, int $lastId, int $counter)
Определения PrivateChat.php:292
add(array $params, ?Context $context=null)
Определения PrivateChat.php:445
getPopupData(array $excludedList=[])
Определения PrivateChat.php:574
updateRecentItems(Message $message)
Определения PrivateChat.php:226
getPushService(\Bitrix\Im\V2\Message $message, SendingConfig $config)
Определения PrivateChat.php:287
addUsers(array $userIds, AddUsersConfig $config=new AddUsersConfig())
Определения PrivateChat.php:264
onBeforeMessageSend(Message $message, SendingConfig $config)
Определения PrivateChat.php:181
sendEventRead(int $startId, int $endId, int $counter, bool $byEvent)
Определения PrivateChat.php:340
static getDialogIds(array $chatIds, int $contextUserId)
Определения PrivateChat.php:585
sendPushReadOpponent(MessageCollection $messages, int $lastId)
Определения PrivateChat.php:316
setManageUI(string $manageUI)
Определения PrivateChat.php:79
const EXTRANET_CAN_SEE_HISTORY
Определения PrivateChat.php:34
setManageSettings(string $manageSettings)
Определения PrivateChat.php:64
insertRecent(array $fields)
Определения PrivateChat.php:244
getStartId(?int $userId=null)
Определения PrivateChat.php:115
prepareParams(array $params=[])
Определения PrivateChat.php:532
setManageUsersAdd(string $manageUsersAdd)
Определения PrivateChat.php:69
getDefaultManageMessagesAutoDelete()
Определения PrivateChat.php:89
setManageMessages(string $manageMessages)
Определения PrivateChat.php:84
getCompanionId(?int $userId=null)
Определения PrivateChat.php:215
getDialogId(?int $contextUserId=null)
Определения PrivateChat.php:94
filterUsersToMentionAnchor(array $userIds)
Определения PrivateChat.php:155
static find(array $params, ?Context $context=null)
Определения PrivateChat.php:372
array $dialogIdCache
Определения PrivateChat.php:35
getCompanion(?int $userId=null)
Определения PrivateChat.php:193
static getInstance()
Определения application.php:98
static getConnection($name="")
Определения application.php:638
Определения result.php:20
static add($recipient, array $parameters, $channelType=\CPullChannel::TYPE_PRIVATE)
Определения event.php:22
if(!\Bitrix\Main\Loader::includeModule('clouds')) $lastId
Определения sync.php:68
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
const IM_MESSAGE_PRIVATE
Определения include.php:22
$context
Определения csv_new_setup.php:223
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
Определения Uuid.php:3
Определения ActionUuid.php:3
Определения culture.php:9
Определения ufield.php:9
$user
Определения mysql_to_pgsql.php:33
$message
Определения payment.php:8
$counter
Определения options.php:5
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$config
Определения quickway.php:69
$messages
Определения template.php:8
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$fields
Определения yandex_run.php:501