Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
ImportService.php
1<?php
2
3namespace Bitrix\Im\V2\Import;
4
7use Bitrix\Im\Model\EO_Relation;
8use Bitrix\Im\Model\EO_Relation_Collection;
22
24{
25 public const IMPORT_GROUP_CHAT_ENTITY_TYPE = 'IMPORT_GROUP';
26 public const IMPORT_PRIVATE_CHAT_ENTITY_TYPE = 'IMPORT_PRIVATE';
27 public const IMPORT_GROUP_FINISH_ENTITY_TYPE = 'IMPORT_GROUP_FINISH';
28 public const IMPORT_PRIVATE_FINISH_ENTITY_TYPE = 'IMPORT_PRIVATE_FINISH';
29 public const IMPORT_ARCHIVE_ENTITY_TYPE = 'IMPORT_ARCHIVE';
30
31 private int $userId;
32 private array $chat;
33 private ImportSendingService $sendingService;
34
35 public function __construct(array $chat, ?int $userId = null, ?ImportSendingService $sendingService = null)
36 {
37 $this->chat = $chat;
38 if (isset($userId))
39 {
40 $this->userId = $userId;
41 }
42 if (isset($sendingService))
43 {
44 $this->sendingService = $sendingService;
45 }
46 else
47 {
48 $this->sendingService = new ImportSendingService($chat);
49 }
50 }
51
52 public static function create(array $chatData): Result
53 {
54 $result = new Result();
55
56 $chatData['ENTITY_TYPE'] =
57 $chatData['TYPE'] === \IM_MESSAGE_PRIVATE
60 ;
61
62 $chatService = new \CIMChat(0);
63 $chatId = $chatService->Add($chatData);
64
65 if ($chatId === 0)
66 {
67 return $result->addError(new ChatError(ChatError::CREATION_ERROR));
68 }
69
70 return $result->setResult([
71 'CHAT_ID' => $chatId,
72 'TYPE' => $chatData['TYPE']
73 ]);
74 }
75
76 public function addMessages(array $messages): Result
77 {
78 return $this->sendingService->addMessages($messages);
79 }
80
81 public function updateMessages(array $messages): Result
82 {
83 return $this->sendingService->updateMessages($messages);
84 }
85
86 public function abort(): Result
87 {
88 $result = new Result();
89 \CIMChat::deleteChat($this->chat);
90
91 return $result;
92 }
93
94 public function commitGroup(array $users, string $clientId): Result
95 {
96 return $this->commitCommon(
97 $users,
98 $clientId,
99 [
100 'ENTITY_TYPE' => self::IMPORT_GROUP_FINISH_ENTITY_TYPE,
101 'ENTITY_ID' => null,
102 'ENTITY_DATA_1' => $clientId
103 ]
104 );
105 }
106
107 public function commitPrivate(bool $newIsMain, bool $hideOriginal, string $clientId): Result
108 {
109 $result = new Result();
110
111 $initUsers = $this->getInitUsers();
112 $originalChat = $this->getOriginalChat($initUsers);
113 $originalChatId = null;
114 if ($originalChat !== null)
115 {
116 $originalChatId = (int)$originalChat['ID'];
117 if ($this->hasRealMessages($originalChat))
118 {
119 if ($newIsMain)
120 {
121 if ($hideOriginal)
122 {
123 $this->hideChat($originalChat, $initUsers);
124 }
125 else
126 {
127 $this->convertOriginalToGroup($originalChat, $initUsers);
128 }
129 }
130 else
131 {
132 $this->convertToGroup($initUsers);
133 $this->chat['MESSAGE_TYPE'] = \IM_MESSAGE_CHAT;
134 }
135 }
136 else
137 {
138 $this->hideChat($originalChat, $initUsers);
139 }
140 }
141
142 $this->commitCommon(
143 $initUsers,
144 $clientId,
145 [
146 'ENTITY_TYPE' => self::IMPORT_PRIVATE_FINISH_ENTITY_TYPE,
147 'ENTITY_ID' => $originalChatId,
148 'ENTITY_DATA_1' => $clientId
149 ]
150 );
151
152 if ($this->chat['MESSAGE_TYPE'] === \IM_MESSAGE_CHAT)
153 {
154 $chatService = new \CIMChat(0);
155 $managers = [];
156 foreach ($initUsers as $user)
157 {
158 $managers[$user] = true;
159 }
160 $chatService->SetManagers((int)$this->chat['ID'], $managers, false);
161 }
162
163 return $result;
164 }
165
166 private function hideChat(array $chat, array $users): void
167 {
168 $id = (int)$chat['ID'];
169
170 RelationTable::deleteByFilter(['=CHAT_ID' => $id]);
171 Recent::hide($users[0], $users[1]);
172 Recent::hide($users[1], $users[0]);
173 sort($users);
174 ChatTable::update($id, ['ENTITY_TYPE' => self::IMPORT_ARCHIVE_ENTITY_TYPE, 'ENTITY_ID' => "{$users[0]}|{$users[1]}"]);
175 }
176
177 private function getOriginalChat(array $users): ?array
178 {
179 $originalChatId = \CIMMessage::GetChatId($users[0], $users[1], false);
180 if ($originalChatId === 0)
181 {
182 return null;
183 }
184
185 return Chat::getById($originalChatId);
186 }
187
188 private function hasRealMessages(array $chat): bool
189 {
190 if ((int)$chat['MESSAGE_COUNT'] === 0)
191 {
192 return false;
193 }
194
195 if ((int)$chat['MESSAGE_COUNT'] === 1)
196 {
197 return \CIMMessageParam::Get((int)$chat['LAST_MESSAGE_ID'], 'USER_JOIN') !== null;
198 }
199
200 return true;
201 }
202
203 private function getInitUsers(): array
204 {
205 $initUsers = [];
206 [$initUsers[0], $initUsers[1]] = explode('|', $this->chat['ENTITY_DATA_1']);
207
208 return array_map('intval', $initUsers);
209 }
210
211 private function commitCommon(array $users, string $clientId, array $finishEntityData = []): Result
212 {
213 $result = new Result();
214 $chatId = (int)$this->chat['ID'];
215
216 $users = array_map('intval', $users);
217 $folderMembers = $users;
218 if (!in_array($this->userId, $users, true))
219 {
220 \CIMDisk::ChangeFolderMembers($chatId, $this->userId, false);
221 }
222 else
223 {
224 foreach ($folderMembers as $index => $folderMember)
225 {
226 if ($folderMember === $this->userId)
227 {
228 unset($folderMembers[$index]);
229 }
230 }
231 }
232
233 $this->fillChatActualData();
234 $this->addUsersInChat($this->chat, $users);
235 \CIMDisk::ChangeFolderMembers($chatId, $users);
236 ChatTable::update(
237 $chatId,
238 [
239 'ENTITY_TYPE' => $finishEntityData['ENTITY_TYPE'] ?? null,
240 'ENTITY_ID' => $finishEntityData['ENTITY_ID'] ?? null,
241 'ENTITY_DATA_1' => $finishEntityData['ENTITY_DATA_1'] ?? null,
242 'USER_COUNT' => count($users),
243 'MESSAGE_COUNT' => $this->chat['MESSAGE_COUNT'],
244 'LAST_MESSAGE_ID' => $this->chat['LAST_MESSAGE_ID'],
245 'PREV_MESSAGE_ID' => $this->chat['PREV_MESSAGE_ID'],
246 ]
247 );
248 $this->showInRecent($this->chat);
249 $this->sendFinishMessage($users, $clientId);
250
251 return $result;
252 }
253
254 private function sendFinishMessage(array $users, string $clientId): void
255 {
256 $appName = $this->getRestAppName($clientId) ?? '';
257 \CIMMessenger::Add([
258 'MESSAGE' => Loc::getMessage('IM_IMPORT_FINISH_MESSAGE', ['#APP_NAME#' => $appName]),
259 'FROM_USER_ID' => $this->chat['MESSAGE_TYPE'] === \IM_MESSAGE_PRIVATE ? $users[0] : 0,
260 'TO_CHAT_ID' => (int)$this->chat['ID'],
261 'MESSAGE_TYPE' => $this->chat['MESSAGE_TYPE'],
262 'SYSTEM' => 'Y',
263 ]);
264 }
265
266 private function fillChatActualData(): void
267 {
268 $lastMessageIds = $this->getLastMessageIds((int)$this->chat['ID']);
269 $this->chat['MESSAGE_COUNT'] = $this->getMessageCount((int)$this->chat['ID']);
270 $this->chat['LAST_MESSAGE_ID'] = $lastMessageIds[0] ?? 0;
271 $this->chat['PREV_MESSAGE_ID'] = $lastMessageIds[1] ?? 0;
272 }
273
274 private function getMessageCount(int $chatId): int
275 {
276 return MessageTable::getCount(Query::filter()->where('CHAT_ID', $chatId));
277 }
278
279 private function getLastMessageIds(int $chatId): array
280 {
281 $result = [];
282
283 $messages = MessageTable::query()
284 ->setSelect(['ID'])
285 ->where('CHAT_ID', $chatId)
286 ->setOrder(['DATE_CREATE' => 'DESC'])
287 ->setLimit(2)
288 ->fetchCollection()
289 ;
290
291 foreach ($messages as $message)
292 {
293 $result[] = $message->getId();
294 }
295
296 return $result;
297 }
298
299 private function showInRecent(array $chatData): Result
300 {
301 $relations = Chat::getRelation((int)$chatData['ID'], ['WITHOUT_COUNTERS' => 'Y']);
302
303 foreach ($relations as $userId => $relation)
304 {
305 $entityId =
306 $chatData['MESSAGE_TYPE'] === \IM_MESSAGE_PRIVATE
307 ? $this->getEntityIdForPrivateChat($relations, (int)$relation['USER_ID'])
308 : (int)$chatData['ID']
309 ;
310 \CIMContactList::SetRecent(Array(
311 'ENTITY_ID' => $entityId,
312 'MESSAGE_ID' => (int)$chatData['LAST_MESSAGE_ID'],
313 'CHAT_TYPE' => $chatData['MESSAGE_TYPE'],
314 'USER_ID' => $relation['USER_ID'],
315 'CHAT_ID' => $relation['CHAT_ID'],
316 'RELATION_ID' => $relation['ID'],
317 ));
318 }
319
320 return new Result();
321 }
322
323 private function addUsersInChat(array $chatData, array $users): void
324 {
325 $relationCollection = new EO_Relation_Collection();
326 $lastRead = new DateTime();
327
328 foreach ($users as $user)
329 {
330 $relation = new EO_Relation();
331 $relation
332 ->setChatId((int)$chatData['ID'])
333 ->setMessageType($chatData['MESSAGE_TYPE'])
334 ->setUserId($user)
335 ->setStartId(0)
336 ->setLastId((int)$chatData['LAST_MESSAGE_ID'])
337 ->setLastSendId((int)$chatData['LAST_MESSAGE_ID'])
338 ->setLastFileId(0)
339 ->setStartCounter(0)
340 ->setLastRead($lastRead)
341 ;
342 $relationCollection->add($relation);
343 }
344
345 $relationCollection->save(true);
346 }
347
348 private function getEntityIdForPrivateChat(array $relations, int $userId): int
349 {
350 foreach ($relations as $relation)
351 {
352 if ((int)$relation['USER_ID'] !== $userId)
353 {
354 return (int)$relation['USER_ID'];
355 }
356 }
357
358 return 0;
359 }
360
361 private function convertToGroup(array $users): void
362 {
364 'IM_IMPORT_GROUP_FROM_PRIVATE_CHAT_TITLE',
365 [
366 '#USER_NAME_1#' => User::getInstance($users[0])->getFullName(false),
367 '#USER_NAME_2#' => User::getInstance($users[1])->getFullName(false),
368 ]
369 );
370 ChatTable::update((int)$this->chat['ID'], ['TYPE' => \IM_MESSAGE_CHAT, 'TITLE' => $title]);
371 }
372
373 private function convertOriginalToGroup(array $originalChat, array $users): void
374 {
375 $chatId = (int)$originalChat['ID'];
377 'IM_IMPORT_GROUP_FROM_ORIGINAL_PRIVATE_CHAT_TITLE',
378 [
379 '#USER_NAME_1#' => User::getInstance($users[0])->getFullName(false),
380 '#USER_NAME_2#' => User::getInstance($users[1])->getFullName(false),
381 ]
382 );
383 Recent::hide($users[0], $users[1]);
384 Recent::hide($users[1], $users[0]);
385 ChatTable::update((int)$originalChat['ID'], ['TYPE' => \IM_MESSAGE_CHAT, 'TITLE' => $title]);
386 $originalChat['MESSAGE_TYPE'] = \IM_MESSAGE_CHAT;
387 $sqlUpdateRelation = "UPDATE b_im_relation SET MESSAGE_TYPE= '" . \IM_MESSAGE_CHAT . "' WHERE CHAT_ID={$chatId}";
388 Application::getConnection()->query($sqlUpdateRelation);
389 $this->showInRecent($originalChat);
390 }
391
392 private function getRestAppName(string $clientId): ?string
393 {
394 $app = AppTable::getByClientId($clientId);
395 if (!is_array($app))
396 {
397 return null;
398 }
399
400 $appNamesByPriority = [$app['MENU_NAME'], $app['MENU_NAME_DEFAULT'], $app['MENU_NAME_LICENSE'], $app['APP_NAME']];
401
402 foreach ($appNamesByPriority as $appName)
403 {
404 if ($appName !== '')
405 {
406 return $appName;
407 }
408 }
409
410 return null;
411 }
412
413 public function hasAccess(): bool
414 {
415 return $this->isImportInProgress() && self::isAdmin($this->userId);
416 }
417
418 public static function isAdmin(int $userId): bool
419 {
420 global $USER;
421 if (Loader::includeModule('bitrix24'))
422 {
423 if (
424 $USER instanceof \CUser
425 && $USER->isAuthorized()
426 && $USER->isAdmin()
427 && (int)$USER->getId() === $userId
428 )
429 {
430 return true;
431 }
432
433 return \CBitrix24::isPortalAdmin($userId);
434 }
435
436 if (
437 $USER instanceof \CUser
438 && $USER->isAuthorized()
439 && (int)$USER->getId() === $userId
440 )
441 {
442 return $USER->isAdmin();
443 }
444
445 $result = false;
446 $groups = UserTable::getUserGroupIds($userId);
447 foreach ($groups as $groupId)
448 {
449 if ((int)$groupId === 1)
450 {
451 $result = true;
452 break;
453 }
454 }
455
456 return $result;
457 }
458
459 private function isImportInProgress(): bool
460 {
461 $entityType = $this->chat['ENTITY_TYPE'] ?? '';
462
463 return (
464 $entityType === self::IMPORT_PRIVATE_CHAT_ENTITY_TYPE
465 || $entityType === self::IMPORT_GROUP_CHAT_ENTITY_TYPE
466 );
467 }
468}
static getById(int $id)
static getRelation($chatId, $params=[])
Definition chat.php:84
static hide($dialogId, $userId=null)
Definition recent.php:1508
static getInstance($userId=null)
Definition user.php:44
commitGroup(array $users, string $clientId)
static create(array $chatData)
commitPrivate(bool $newIsMain, bool $hideOriginal, string $clientId)
__construct(array $chat, ?int $userId=null, ?ImportSendingService $sendingService=null)
static getConnection($name="")
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29