1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
Converter.php
См. документацию.
1<?php
2
3namespace Bitrix\Im\V2\Chat;
4
5use Bitrix\Im\Model\ChatTable;
6use Bitrix\Im\Model\MessageUnreadTable;
7use Bitrix\Im\Model\RecentTable;
8use Bitrix\Im\Model\RelationTable;
9use Bitrix\Im\V2\Chat;
10use Bitrix\Im\V2\Integration\Socialnetwork\Collab\Collab;
11use Bitrix\Im\V2\Message\CounterService;
12use Bitrix\Im\V2\Permission;
13use Bitrix\Im\V2\Result;
14use Bitrix\Main\Application;
15
17{
18 private const PUSH_CONVERT_NAME = 'chatConvert';
19 private const VALID_CONVERSIONS = [
20 Chat::IM_TYPE_OPEN => [Chat::IM_TYPE_CHAT, Chat::IM_TYPE_CHANNEL, Chat::IM_TYPE_OPEN_CHANNEL],
21 Chat::IM_TYPE_CHAT => [Chat::IM_TYPE_OPEN, Chat::IM_TYPE_CHANNEL, Chat::IM_TYPE_OPEN_CHANNEL, Chat::IM_TYPE_COLLAB],
22 Chat::IM_TYPE_OPEN_CHANNEL => [Chat::IM_TYPE_CHANNEL, Chat::IM_TYPE_CHAT, Chat::IM_TYPE_OPEN],
23 Chat::IM_TYPE_CHANNEL => [Chat::IM_TYPE_OPEN_CHANNEL, Chat::IM_TYPE_CHAT, Chat::IM_TYPE_OPEN],
24 Chat::IM_TYPE_COPILOT => [Chat::IM_TYPE_AI_ASSISTANT],
25 ];
26 private const OPEN_TYPES = [Chat::IM_TYPE_OPEN, Chat::IM_TYPE_OPEN_CHANNEL];
27 private const CHANNEL_TYPES = [Chat::IM_TYPE_CHANNEL, Chat::IM_TYPE_OPEN_CHANNEL];
28 private int $chatId;
29 private ?Chat $chat;
30 private string $oldType;
31 private string $oldRestType;
32 private string $newType;
33
34 public function __construct(int $chatId, string $newType)
35 {
36 $this->chatId = $chatId;
37 $this->initOldTypes();
38 $this->newType = $newType;
39 }
40
41 public function convert(): Result
42 {
43 $result = new Result();
44
45 $checkResult = $this->isAvailable();
46
47 if (!$checkResult->isSuccess())
48 {
49 return $result->addErrors($checkResult->getErrors());
50 }
51
52 Application::getConnection()->startTransaction();
53 try {
54 $this
55 ->convertChatInfo()
56 ->updateDiskRights()
57 ->convertRelations()
58 ->convertRecent()
59 ->convertCounters()
60 ;
61 Application::getConnection()->commitTransaction();
62 }
63 catch (\Throwable $exception)
64 {
65 Application::getConnection()->rollbackTransaction();
66
67 return $result->addError(new ChatError(ChatError::CONVERT_ERROR));
68 }
69
70 $this->onAfterConvert();
71
72 return $result;
73 }
74
75 protected function isAvailable(): Result
76 {
77 $result = new Result();
78
79 $validConversions = self::VALID_CONVERSIONS[$this->oldType] ?? [];
80 if (!in_array($this->newType, $validConversions, true) || $this->getChat() instanceof Chat\VideoConfChat)
81 {
82 return $result->addError(new ChatError(ChatError::WRONG_CHAT_TYPE));
83 }
84
85 if ($this->toCollab() && !$this->canConvertToCollab())
86 {
87 return $result->addError(new ChatError(ChatError::WRONG_CHAT_TYPE));
88 }
89
90 return $result;
91 }
92
93 protected function canConvertToCollab(): bool
94 {
95 return $this->isSonetChat() && Collab::isCollab($this->getChat()->getEntityId());
96 }
97
98 protected function isSonetChat(): bool
99 {
100 return $this->getChat()->getEntityType() === Chat\ExtendedType::Sonet->value && $this->getChat()->getEntityId() > 0;
101 }
102
103 protected function onAfterConvert(): void
104 {
105 Chat::cleanCache($this->chatId);
106 Chat::cleanAccessCache($this->chatId);
108 $this->sendPush();
109 }
110
115 protected function convertChatInfo(): self
116 {
117 $fields = ['TYPE' => $this->newType];
118 if ($this->toCollab())
119 {
120 $fields['DISK_FOLDER_ID'] = null;
121 }
122
123 ChatTable::update($this->chatId, $fields);
124 $this->chat = null;
126
127 return $this;
128 }
129
130 protected function updateDiskRights(): self
131 {
132 if ($this->fromCloseToOpenType())
133 {
135 }
136 elseif ($this->fromOpenToCloseType())
137 {
139 }
140
141 return $this;
142 }
143
144 protected function convertRelations(): self
145 {
146 RelationTable::updateByFilter(['=CHAT_ID' => $this->chatId], ['MESSAGE_TYPE' => $this->newType]);
147
148 return $this;
149 }
150
151 protected function convertRecent(): self
152 {
153 RecentTable::updateByFilter(['=ITEM_TYPE' => $this->oldType, '=ITEM_ID' => $this->chatId], ['ITEM_TYPE' => $this->newType]);
154
155 return $this;
156 }
157
158 protected function convertCounters(): self
159 {
160 MessageUnreadTable::updateByFilter(['=CHAT_ID' => $this->chatId], ['CHAT_TYPE' => $this->newType]);
161 if ($this->fromChannelToOther())
162 {
163 return $this->deleteChildrenCounters();
164 }
165
166 return $this;
167 }
168
169 protected function deleteChildrenCounters(): self
170 {
171 $chatIds = CounterService::getChildrenWithCounters($this->getChat());
172
173 if (!empty($chatIds))
174 {
175 MessageUnreadTable::deleteByFilter(['=CHAT_ID' => $chatIds]);
176 }
177
178 return $this;
179 }
180
181 protected function sendPush(): void
182 {
183 $chat = $this->getChat();
184 $pushParams = [
185 'module_id' => 'im',
186 'command' => self::PUSH_CONVERT_NAME,
187 'params' => [
188 'id' => $this->chatId,
189 'dialogId' => 'chat' . $this->chatId,
190 'oldType' => $this->oldRestType,
191 'newType' => $chat->getExtendedType(),
192 'newPermissions' => $chat->getPermissions(),
193 'newTypeParams' => null,
194 ],
196 ];
197
198 if ($chat instanceof CollabChat)
199 {
200 $collabInfo = new Chat\Collab\CollabInfo($chat);
201 $pushParams['params']['newTypeParams'][$collabInfo::getRestEntityName()] = $collabInfo->toRestFormat();
202 }
203
204 \Bitrix\Pull\Event::add($chat->getRelations()->getUserIds(), $pushParams);
205 if (\CIMMessenger::needToSendPublicPull($this->newType) || \CIMMessenger::needToSendPublicPull($this->oldType))
206 {
207 \CPullWatch::AddToStack('IM_PUBLIC_' . $this->chatId, $pushParams);
208 }
209 }
210
211 protected function initOldTypes(): void
212 {
213 $this->oldType = $this->getChat()->getType();
214 $this->oldRestType = $this->getChat()->getExtendedType();
215 }
216
217 protected function addDepartmentToDiskRights(): void
218 {
219 $folder = $this->getChat()->getOrCreateDiskFolder();
220 if (!$folder)
221 {
222 return;
223 }
224
225 $departmentCode = \CIMDisk::GetTopDepartmentCode();
226 if (!$departmentCode)
227 {
228 return;
229 }
230
231 $driver = \Bitrix\Disk\Driver::getInstance();
232 $rightsManager = $driver->getRightsManager();
233 $departmentRight = [[
234 'ACCESS_CODE' => $departmentCode,
235 'TASK_ID' => $rightsManager->getTaskIdByName($rightsManager::TASK_READ)
236 ]];
237 $rightsManager->append($folder, $departmentRight);
238 }
239
240 protected function deleteDepartmentFromDiskRights(): void
241 {
242 $folder = $this->getChat()->getOrCreateDiskFolder();
243 if (!$folder)
244 {
245 return;
246 }
247
248 $driver = \Bitrix\Disk\Driver::getInstance();
249 $rightsManager = $driver->getRightsManager();
250 $accessProvider = new \Bitrix\Im\Access\ChatAuthProvider;
251
252 $accessCodes = [];
253 $accessCodes[] = [
254 'ACCESS_CODE' => $accessProvider->generateAccessCode($this->chatId),
255 'TASK_ID' => $rightsManager->getTaskIdByName($rightsManager::TASK_EDIT)
256 ];
257 $rightsManager->set($folder, $accessCodes);
258 }
259
260 protected function fromCloseToOpenType(): bool
261 {
262 $isOldTypeClose = !in_array($this->oldType, self::OPEN_TYPES, true);
263 $isNewTypeOpen = in_array($this->newType, self::OPEN_TYPES, true);
264
265 return $isOldTypeClose && $isNewTypeOpen;
266 }
267
268 protected function fromOpenToCloseType(): bool
269 {
270 $isOldTypeOpen = in_array($this->oldType, self::OPEN_TYPES, true);
271 $isNewTypeClose = !in_array($this->newType, self::OPEN_TYPES, true);
272
273 return $isOldTypeOpen && $isNewTypeClose;
274 }
275
276 protected function fromChannelToOther(): bool
277 {
278 $isOldTypeChannel = in_array($this->oldType, self::CHANNEL_TYPES, true);
279 $isNewTypeNotChannel = !in_array($this->newType, self::CHANNEL_TYPES, true);
280
281 return $isOldTypeChannel && $isNewTypeNotChannel;
282 }
283
284 protected function toCollab(): bool
285 {
286 return $this->oldType === Chat::IM_TYPE_CHAT && $this->newType === Chat::IM_TYPE_COLLAB;
287 }
288
289 protected function setChatPermissionToDefaultValues(): void
290 {
291 $emptyPermissions = [];
292 foreach (Permission\ActionGroup::cases() as $permission)
293 {
294 $emptyPermissions[$permission->value] = '';
295 }
296 $this->getChat()->fill($emptyPermissions);
297 $this->getChat()->save();
298 }
299
300 protected function getChat(): Chat
301 {
302 $this->chat ??= Chat::getInstance($this->chatId);
303
304 return $this->chat;
305 }
306}
static getPullExtra()
Определения common.php:127
const CONVERT_ERROR
Определения ChatError.php:33
const WRONG_CHAT_TYPE
Определения ChatError.php:34
canConvertToCollab()
Определения Converter.php:93
deleteChildrenCounters()
Определения Converter.php:169
fromCloseToOpenType()
Определения Converter.php:260
deleteDepartmentFromDiskRights()
Определения Converter.php:240
convertChatInfo()
Определения Converter.php:115
convertCounters()
Определения Converter.php:158
fromChannelToOther()
Определения Converter.php:276
fromOpenToCloseType()
Определения Converter.php:268
updateDiskRights()
Определения Converter.php:130
addDepartmentToDiskRights()
Определения Converter.php:217
convertRelations()
Определения Converter.php:144
setChatPermissionToDefaultValues()
Определения Converter.php:289
__construct(int $chatId, string $newType)
Определения Converter.php:34
static isCollab(int $collabId)
Определения Collab.php:125
static getInstance()
Определения application.php:98
static getConnection($name="")
Определения application.php:638
static clearCache($moduleId)
Определения option.php:464
Определения result.php:20
static cleanCache()
Определения datamanager.php:1983
static add($recipient, array $parameters, $channelType=\CPullChannel::TYPE_PRIVATE)
Определения event.php:22
static GetTopDepartmentCode()
Определения im_disk.php:2502
$result
Определения get_property_values.php:14
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$fields
Определения yandex_run.php:501