Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
ViewedService.php
1<?php
2
4
8use Bitrix\Im\V2\Common\ContextCustomer;
15
17{
18 use ContextCustomer;
19
20 public function __construct(?int $userId = null)
21 {
22 if (isset($userId))
23 {
24 $context = new Context();
25 $context->setUser($userId);
26 $this->setContext($context);
27 }
28 }
29
30 public function add(MessageCollection $messages): void
31 {
32 $insertFields = $this->prepareInsertFields($messages);
33 MessageViewedTable::multiplyInsertWithoutDuplicate($insertFields, ['DEADLOCK_SAFE' => true]);
34 }
35
36 public function addTo(Message $message): Result
37 {
38 $lowerBound = $this->getLastViewedMessageId($message->getChatId());
39 $includeBound = false;
40 if ($lowerBound === null)
41 {
42 $lowerBound = $message->getChat()->getStartId($this->getContext()->getUserId());
43 $includeBound = true;
44 }
45
46 $messageIds = $this->getLastMessageIdsBetween($message, $lowerBound, $includeBound);
47 $dateViewed = new DateTime();
48 $userId = $this->getContext()->getUserId();
49 $chatId = $message->getChatId();
50 $insertFields = [];
51
52 foreach ($messageIds as $messageId)
53 {
54 $insertFields[] = [
55 'USER_ID' => $userId,
56 'CHAT_ID' => $chatId,
57 'MESSAGE_ID' => $messageId,
58 'DATE_CREATE' => $dateViewed,
59 ];
60 }
61
62 MessageViewedTable::multiplyInsertWithoutDuplicate($insertFields, ['DEADLOCK_SAFE' => true]);
63
64 return (new Result())->setResult(['VIEWED_MESSAGES' => $messageIds]);
65 }
66
67 public function getLastViewedMessageId(int $chatId): ?int
68 {
69 $result = MessageViewedTable::query()
70 ->setSelect(['LAST_VIEWED' => new ExpressionField('LAST_VIEWED', 'MAX(%s)', ['MESSAGE_ID'])])
71 ->where('CHAT_ID', $chatId)
72 ->where('USER_ID', $this->getContext()->getUserId())
73 ->fetch()
74 ;
75
76 return ($result && isset($result['LAST_VIEWED'])) ? (int)$result['LAST_VIEWED'] : null;
77 }
78
79 public function getDateViewedByMessageId(int $messageId): ?DateTime
80 {
81 $result = MessageViewedTable::query() //todo: add unique index (MESSAGE_ID, USER_ID, DATE_CREATE)
82 ->setSelect(['DATE_CREATE'])
83 ->where('USER_ID', $this->getContext()->getUserId())
84 ->where('MESSAGE_ID', $messageId)
85 ->fetch()
86 ;
87
88 return $result ? $result['DATE_CREATE'] : null;
89 }
90
91 public function getDateViewedByMessageIdForEachUser(int $messageId, array $userIds): array
92 {
93 if (empty($userIds))
94 {
95 return [];
96 }
97
98 $result = MessageViewedTable::query() //todo: add unique index (MESSAGE_ID, USER_ID, DATE_CREATE)
99 ->setSelect(['DATE_CREATE', 'USER_ID'])
100 ->whereIn('USER_ID', $userIds)
101 ->where('MESSAGE_ID', $messageId)
102 ->fetchAll()
103 ;
104
105 $dateViewedByUsers = [];
106
107 foreach ($result as $row)
108 {
109 $dateViewedByUsers[(int)$row['USER_ID']] = $row['DATE_CREATE'];
110 }
111
112 return $dateViewedByUsers;
113 }
114
115 public function getMessageStatus(int $messageId): string
116 {
117 $isMessageRead = MessageViewedTable::query()
118 ->setSelect(['MESSAGE_ID'])
119 ->where('MESSAGE_ID', $messageId) //todo add index
120 ->setLimit(1)
121 ->fetch()
122 ;
123
124 return $isMessageRead ? \IM_MESSAGE_STATUS_DELIVERED : \IM_MESSAGE_STATUS_RECEIVED;
125 }
126
127 public function getMessageViewersIds(int $messageId, ?int $limit = null, ?int $offset = null): array
128 {
129 $query = MessageViewedTable::query()
130 ->setSelect(['USER_ID'])
131 ->where('MESSAGE_ID', $messageId)
132 ->setOrder(['ID' => 'ASC'])
133 ;
134
135 if (isset($limit))
136 {
137 $query->setLimit($limit);
138 }
139 if (isset($offset))
140 {
141 $query->setOffset($offset);
142 }
143
144 $viewedMessages = $query->fetchCollection();
145 $viewersIds = [];
146
147 foreach ($viewedMessages as $viewedMessage)
148 {
149 $userId = $viewedMessage->getUserId();
150 $viewersIds[$userId] = $userId;
151 }
152
153 return $viewersIds;
154 }
155
156 public function getMessageStatuses(array $messageIds): array
157 {
158 if (empty($messageIds))
159 {
160 return [];
161 }
162
163 $viewedMessageResult = MessageViewedTable::query()
164 ->setSelect(['MESSAGE_ID'])
165 ->setDistinct()
166 ->whereIn('MESSAGE_ID', $messageIds) //todo index
167 ->exec()
168 ;
169
170 $deliveredMessages = [];
171
172 while ($row = $viewedMessageResult->fetch())
173 {
174 $deliveredMessages[(int)$row['MESSAGE_ID']] = \IM_MESSAGE_STATUS_DELIVERED;
175 }
176
177 $messageStatuses = [];
178
179 foreach ($messageIds as $messageId)
180 {
181 $messageStatuses[$messageId] = $deliveredMessages[$messageId] ?? \IM_MESSAGE_STATUS_RECEIVED;
182 }
183
184 return $messageStatuses;
185 }
186
187 public function deleteStartingFrom(Message $message): void
188 {
189 $userId = $this->getContext()->getUserId();
190 MessageViewedTable::deleteByFilter(['>=MESSAGE_ID' => $message->getMessageId(), '=CHAT_ID' => $message->getChatId(), '=USER_ID' => $userId]);
191 }
192
193 public function deleteByMessageIds(array $messageIds, int $chatId): void
194 {
195 if (empty($messageIds))
196 {
197 return;
198 }
199
200 MessageViewedTable::deleteByFilter(['=MESSAGE_ID' => $messageIds, '=CHAT_ID' => $chatId, '=USER_ID' => $this->getContext()->getUserId()]);
201 }
202
203 public function deleteByMessageIdForAll(int $messageId): void
204 {
205 MessageViewedTable::deleteByFilter(['=MESSAGE_ID' => $messageId]); //todo add index
206 }
207
208 public function deleteByMessageIdsForAll(array $messageIds): void
209 {
210 MessageViewedTable::deleteByFilter(['=MESSAGE_ID' => $messageIds]); //todo add index
211 }
212
213 public function deleteByChatId(int $chatId): void
214 {
215 MessageViewedTable::deleteByFilter(['=CHAT_ID' => $chatId, '=USER_ID' => $this->getContext()->getUserId()]);
216 }
217
218 private function prepareInsertFields(MessageCollection $messages): array
219 {
220 $insertFields = [];
221 $userId = $this->getContext()->getUserId();
222 $dateCreate = new DateTime();
223
224 foreach ($messages as $message)
225 {
226 if ($message->getAuthorId() === $userId && $message->getChat()->getType() !== \IM_MESSAGE_SYSTEM)
227 {
228 continue;
229 }
230 $insertFields[] = [
231 'USER_ID' => $userId,
232 'CHAT_ID' => $message->getChatId(),
233 'MESSAGE_ID' => $message->getMessageId(),
234 'DATE_CREATE' => $dateCreate,
235 ];
236 }
237
238 return $insertFields;
239 }
240
241 private function getLastMessageIdsBetween(Message $message, int $lowerBound, bool $includeBound): array
242 {
243 $operator = $includeBound ? '>=' : '>';
244
245 $query = MessageTable::query()
246 ->setSelect(['ID'])
247 ->where('CHAT_ID', $message->getChatId())
248 ->where('ID', '<=', $message->getMessageId())
249 ->where('ID', $operator, $lowerBound)
250 ->setOrder(['DATE_CREATE' => 'DESC', 'ID' => 'DESC'])
251 ->setLimit(100)
252 ;
253 if ($message->getChat()->getType() !== \IM_MESSAGE_SYSTEM)
254 {
255 $query->whereNot('AUTHOR_ID', $this->getContext()->getUserId());
256 }
257
258 return $query->fetchCollection()->getIdList();
259 }
260}
add(MessageCollection $messages)
deleteByMessageIdsForAll(array $messageIds)
deleteByMessageIds(array $messageIds, int $chatId)
getMessageViewersIds(int $messageId, ?int $limit=null, ?int $offset=null)
getDateViewedByMessageIdForEachUser(int $messageId, array $userIds)