Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
ReactionService.php
1<?php
2
4
7use Bitrix\Im\V2\Common\ContextCustomer;
10use Bitrix\Imopenlines\MessageParameter;
13
15{
16 use ContextCustomer;
17
18 private bool $withLegacy;
19 private Message $message;
20
21 public function __construct(Message $message, bool $withLegacy = true)
22 {
23 $this->message = $message;
24 $message->setContext($this->context);
25 $this->withLegacy = $withLegacy;
26 }
27
28 public function addReaction(string $reaction, bool $byEvent = false): Result
29 {
30 $result = new Result();
31 $reactionItem = new ReactionItem();
32 $reactionItem
33 ->setMessageId($this->message->getMessageId())
34 ->setChatId($this->message->getChatId())
35 ->setUserId($this->getContext()->getUserId())
36 ->setContext($this->getContext())
37 ->setReaction($reaction)
38 ;
39
40 $this->deleteAllReactions();
41
42 try
43 {
44 $saveResult = $reactionItem->save();
45 if (!$saveResult->isSuccess())
46 {
47 return $result->addErrors($saveResult->getErrors());
48 }
49 }
50 catch (SystemException $exception)
51 {
52 return $result->addError(new ReactionError(ReactionError::ALREADY_SET));
53 }
54
55 if (!$byEvent && $this->isMessageLiveChat())
56 {
57 $this->processAddForLiveChat($reaction);
58 }
59
60 if ($this->withLegacy)
61 {
62 $this->addLegacy();
63 }
64
65 $this->sendNotification($reactionItem);
66
67 (new PushService())->add($reactionItem);
68
69 return $result;
70 }
71
72 public function deleteReaction(string $reaction, bool $byEvent = false): Result
73 {
74 $result = new Result();
75 $reactionItem = ReactionItem::getByMessage($this->message->getMessageId(), $reaction, $this->getContext()->getUserId());
76
77 if ($reactionItem === null)
78 {
79 return $result->addError(new ReactionError(ReactionError::NOT_FOUND));
80 }
81
82 $deleteResult = $reactionItem->delete();
83
84 if (!$deleteResult->isSuccess())
85 {
86 return $result->addErrors($deleteResult->getErrors());
87 }
88
89 if (!$byEvent && $this->isMessageLiveChat())
90 {
91 $this->processDeleteForLiveChat($reaction);
92 }
93
94 if ($this->withLegacy)
95 {
96 $this->deleteLegacy();
97 }
98
99 (new PushService())->delete($reactionItem);
100
101 return $result;
102 }
103
104 private function sendNotification(ReactionItem $reaction): void
105 {
106 $authorId = $this->message->getAuthorId();
107 if (
108 $authorId === 0
109 || $authorId === $this->getContext()->getUserId()
110 || Chat::getInstance($reaction->getChatId())->getEntityType() === 'LIVECHAT'
111 || !Chat::getInstance($reaction->getChatId())->hasAccess($authorId)
112 )
113 {
114 return;
115 }
116
117 $arMessageFields = [
118 'MESSAGE_TYPE' => IM_MESSAGE_SYSTEM,
119 'TO_USER_ID' => $this->message->getAuthorId(),
120 'FROM_USER_ID' => $this->getContext()->getUserId(),
121 'NOTIFY_TYPE' => IM_NOTIFY_FROM,
122 'NOTIFY_MODULE' => 'im',
123 'NOTIFY_EVENT' => 'like',
124 'NOTIFY_TAG' => $this->getNotifyTag($reaction),
125 'NOTIFY_MESSAGE' => $this->getTextNotification($reaction),
126 ];
127 \CIMNotify::Add($arMessageFields);
128 }
129
130 private function getNotifyTag(ReactionItem $reaction): string
131 {
132 $chat = Chat::getInstance($reaction->getChatId());
133 if ($chat instanceof Chat\PrivateChat)
134 {
135 $type = 'P';
136 $id = $this->getContext()->getUserId();
137 }
138 else
139 {
140 $type = 'G';
141 $id = $chat->getChatId();
142 }
143
144 return "RATING|IM|{$type}|{$id}|{$reaction->getMessageId()}|{$reaction->getReaction()}";
145 }
146
147 private function getTextNotification(ReactionItem $reaction): callable
148 {
149 $genderModifier = "_{$this->getContext()->getUser()->getGender()}";
150 $chat = Chat::getInstance($reaction->getChatId())->withContext($this->context);
151 $code = "IM_MESSAGE_REACTION{$genderModifier}";
152
153 if ($chat instanceof Chat\PrivateChat)
154 {
155 return fn (?string $languageId = null) => Loc::getMessage(
156 "{$code}_PRIVATE",
157 [
158 '#DIALOG_ID#' => $chat->getDialogContextId(),
159 '#MESSAGE_ID#' => $this->message->getMessageId(),
160 '#QOUTED_MESSAGE#' => $this->message->getForPush(),
161 '#REACTION_NAME#' => $reaction->getLocName($languageId),
162 ],
163 $languageId);
164 }
165
166 return fn (?string $languageId = null) => Loc::getMessage(
167 "{$code}_PRIVATE",
168 [
169 '#DIALOG_ID#' => $chat->getDialogContextId(),
170 '#MESSAGE_ID#' => $this->message->getMessageId(),
171 '#QOUTED_MESSAGE#' => $this->message->getForPush(),
172 '#CHAT_ID#' => $this->message->getChatId(),
173 '#CHAT_TITLE#' => $chat->getTitle(),
174 '#REACTION_NAME#' => $reaction->getLocName($languageId),
175 ],
176 $languageId);
177 }
178
179 private function processAddForLiveChat(string $reaction): void
180 {
181 $connectorMid = $this->message->getParams()->get(MessageParameter::CONNECTOR_MID)->getValue();
182
183 foreach ($connectorMid as $messageId)
184 {
185 $service = new static(new Message((int)$messageId), false);
186 $service->setContext($this->getContext());
187 $service->addReaction($reaction, true);
188 }
189 }
190
191 private function processDeleteForLiveChat(string $reaction): void
192 {
193 $connectorMid = $this->message->getParams()->get(MessageParameter::CONNECTOR_MID)->getValue();
194
195 foreach ($connectorMid as $messageId)
196 {
197 $service = new static(new Message((int)$messageId), false);
198 $service->setContext($this->getContext());
199 $service->deleteReaction($reaction, true);
200 }
201 }
202
203 private function isMessageLiveChat(): bool
204 {
205 $chat = $this->message->getChat();
206 $isLiveChat = $chat->getEntityType() === 'LIVECHAT';
207 $isToLiveChat = false;
208 if ($chat->getEntityType() === 'LINES')
209 {
210 [$connectorType] = explode('|', $chat->getEntityId());
211 $isToLiveChat = $connectorType === 'livechat';
212 }
213
214 return $isLiveChat || $isToLiveChat;
215 }
216
217 private function hasAnyReaction(): bool
218 {
219 $result = ReactionTable::query()
220 ->setSelect(['MESSAGE_ID'])
221 ->where('MESSAGE_ID', $this->message->getMessageId())
222 ->where('USER_ID', $this->getContext()->getUserId())
223 ->setLimit(1)
224 ->fetch()
225 ;
226
227 return $result !== false;
228 }
229
230 public function deleteAllReactions(): void
231 {
232 ReactionTable::deleteByFilter(['=MESSAGE_ID' => $this->message->getMessageId(), '=USER_ID' => $this->getContext()->getUserId()]);
233 }
234
235 private function addLegacy(): void
236 {
237 \CIMMessenger::Like($this->message->getMessageId(), 'plus', $this->getContext()->getUserId(), false, false);
238 }
239
240 private function deleteLegacy(): void
241 {
242 if (!$this->hasAnyReaction())
243 {
244 \CIMMessenger::Like($this->message->getMessageId(), 'minus', $this->getContext()->getUserId(), false, false);
245 }
246 }
247}
static getByMessage(int $messageId, string $reaction, int $userId)
__construct(Message $message, bool $withLegacy=true)
addReaction(string $reaction, bool $byEvent=false)
deleteReaction(string $reaction, bool $byEvent=false)
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29