1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
mailboxsyncmanager.php
См. документацию.
1<?php
2namespace Bitrix\Mail\Helper\Mailbox;
3
4use COption;
5use Bitrix\Mail\MailboxTable;
6use Bitrix\Main\Type\DateTime;
7use Bitrix\Mail\Internals\MailEntityOptionsTable;
8use Bitrix\Mail\MailFilterTable;
9use Bitrix\Main\Loader;
10use Bitrix\Mail\Helper;
11
13{
14 private $userId;
15 private $mailCheckInterval;
16
19
20 public function __construct($userId)
21 {
22 $this->userId = $userId;
23 $this->mailCheckInterval = COption::getOptionString('intranet', 'mail_check_period', 10) * 60;
24 }
25
26 public static function checkSyncWithCrm(int $mailboxId): bool
27 {
28 if (Loader::includeModule('crm'))
29 {
30 return (bool)MailFilterTable::getCount([
31 '=MAILBOX_ID' => $mailboxId,
32 '=ACTION_TYPE' => 'crm_imap',
33 ]);
34 }
35
36 return false;
37 }
38
39 public function getFailedToSyncMailboxes()
40 {
41 $mailboxes = [];
42 $mailboxesSyncInfo = $this->getMailboxesSyncInfo();
43
44 foreach ($mailboxesSyncInfo as $mailboxId => $lastMailCheckData)
45 {
46 if (!$lastMailCheckData['isSuccess'])
47 {
48 $mailboxes[$mailboxId] = $lastMailCheckData;
49 }
50 }
51 return $mailboxes;
52 }
53
54 public function getSuccessSyncedMailboxes()
55 {
56 $mailboxesToSync = [];
57 $mailboxesSyncInfo = $this->getMailboxesSyncInfo();
58
59 foreach ($mailboxesSyncInfo as $mailboxId => $lastMailCheckData)
60 {
61 if ($lastMailCheckData['isSuccess'])
62 {
63 $mailboxesToSync[$mailboxId] = $lastMailCheckData;
64 }
65 }
66 return $mailboxesToSync;
67 }
68
69 /*
70 * It's time for synchronization for at least one mailbox.
71 */
72 public function isMailNeedsToBeSynced()
73 {
74 return count($this->getNeedToBeSyncedMailboxes()) > 0;
75 }
76
77 /*
78 * Returns mailboxes that are recommended to be synchronized.
79 */
81 {
82 $mailboxesSyncData = $this->getSuccessSyncedMailboxes();
83 $mailboxesToSync = [];
84 foreach ($mailboxesSyncData as $mailboxId => $lastMailCheckData)
85 {
86 if ($lastMailCheckData['timeStarted'] >= 0 && (time() - intval($lastMailCheckData['timeStarted']) >= $this->mailCheckInterval))
87 {
88 $mailboxesToSync[$mailboxId] = $lastMailCheckData;
89 }
90 }
91 return $mailboxesToSync;
92 }
93
94 public function getMailCheckInterval()
95 {
96 return $this->mailCheckInterval;
97 }
98
99 public function deleteSyncData($mailboxId): \Bitrix\Main\DB\Result
100 {
101 return MailEntityOptionsTable::deleteList($this->getOptionFilter($mailboxId, MailEntityOptionsTable::SYNC_STATUS_PROPERTY_NAME));
102 }
103
104 public function setDefaultSyncData($mailboxId)
105 {
106 $this->saveSyncStatus($mailboxId, true, 0);
107 }
108
109 private function buildTimeForSyncStatus($time): int
110 {
111 if($time !== null && (int)$time >= 0)
112 {
113 return (int)$time;
114 }
115
116 return time();
117 }
118
119 public function setSyncStartedData($mailboxId, $time = null)
120 {
121 $this->saveSyncStatus($mailboxId, true, $this->buildTimeForSyncStatus($time));
122 }
123
124 public function setSyncStatus(int $mailboxId, bool $isSuccess, ?int $time = null): void
125 {
126 $this->saveSyncStatus($mailboxId, $isSuccess, $this->buildTimeForSyncStatus($time));
127
128 if ($isSuccess)
129 {
130 $this->removeConnectErrorCache($mailboxId);
131 }
132 }
133
134 public function getCachedConnectionStatus(int $mailboxId): bool
135 {
136 $lastMailboxSyncStatus = $this->getLastMailboxSyncIsSuccessStatus($mailboxId);
137
138 if ($lastMailboxSyncStatus)
139 {
140 $this->removeConnectErrorCache($mailboxId);
141
142 return true;
143 }
144
145 $mailboxHelper = Helper\Mailbox::createInstance($mailboxId, false);
146
147 if (!$mailboxHelper)
148 {
149 // The mailbox was legally disabled,
150 // therefore the connection should be considered successful to avoid future notifications and error outputs.
151 return true;
152 }
153
154 if ($mailboxHelper->isAuthenticated())
155 {
156 $this->removeConnectErrorCache($mailboxId);
157
158 return true;
159 }
160
161 $error = $this->getConnectError($mailboxId);
162
163 $dateAttempt = new DateTime();
164 $connectErrorAttempt = isset($error['VALUE']) ? (int) $error['VALUE'] + 1 : 0;
165
166 if ($connectErrorAttempt > 0)
167 {
168 if ($error['DATE_INSERT'] <= (clone $dateAttempt)->add('- '.self::MIN_INTERVAL_BETWEEN_CONNECTION_ATTEMPTS.' seconds'))
169 {
170 $this->updateConnectError($mailboxId, $connectErrorAttempt, $dateAttempt);
171 }
172 }
173 else
174 {
175 $this->addConnectError($mailboxId);
176 }
177
178 if ($connectErrorAttempt >= self::MAX_CONNECTION_ATTEMPTS_BEFORE_UNAVAILABLE)
179 {
180 return false;
181 }
182
183 return true;
184 }
185
186 private function getOptionFilter(int $mailboxId, string $propertyName): array
187 {
188 return [
189 '=MAILBOX_ID' => $mailboxId,
190 '=ENTITY_TYPE' => MailEntityOptionsTable::MAILBOX_TYPE_NAME,
191 '=ENTITY_ID' => $mailboxId,
192 '=PROPERTY_NAME' => $propertyName,
193 ];
194 }
195
196 private function removeConnectErrorCache(int $mailboxId): void
197 {
198 MailEntityOptionsTable::deleteList($this->getOptionFilter($mailboxId, MailEntityOptionsTable::CONNECT_ERROR_ATTEMPT_COUNT_PROPERTY_NAME));
199 }
200
201 private function getConnectError(int $mailboxId): array|null
202 {
203 return MailEntityOptionsTable::getRow([
204 'select' => [
205 'DATE_INSERT',
206 'VALUE',
207 ],
208 'filter' => $this->getOptionFilter($mailboxId, MailEntityOptionsTable::CONNECT_ERROR_ATTEMPT_COUNT_PROPERTY_NAME),
209 ]);
210 }
211
212 private function updateConnectError(int $mailboxId, int $attemptNumber, DateTime $dateAttempt = new DateTime()): void
213 {
214 MailEntityOptionsTable::update(
215 [
216 'MAILBOX_ID' => $mailboxId,
217 'ENTITY_TYPE' => MailEntityOptionsTable::MAILBOX_TYPE_NAME,
218 'ENTITY_ID' => $mailboxId,
219 'PROPERTY_NAME' => MailEntityOptionsTable::CONNECT_ERROR_ATTEMPT_COUNT_PROPERTY_NAME,
220 ],
221 [
222 'DATE_INSERT' => $dateAttempt,
223 'VALUE' => $attemptNumber,
224 ],
225 );
226 }
227
228 private function addConnectError(int $mailboxId, DateTime $dateAttempt = new DateTime()): void
229 {
230 MailEntityOptionsTable::insertIgnore(
231 $mailboxId,
232 $mailboxId,
233 MailEntityOptionsTable::MAILBOX_TYPE_NAME,
234 MailEntityOptionsTable::CONNECT_ERROR_ATTEMPT_COUNT_PROPERTY_NAME,
235 1,
236 $dateAttempt
237 );
238 }
239
240 private function saveSyncStatus(int $mailboxId, bool $status, int $timestamp): void
241 {
242 $date = DateTime::createFromTimestamp($timestamp);
243
244 if(MailEntityOptionsTable::getCount($this->getOptionFilter($mailboxId, MailEntityOptionsTable::SYNC_STATUS_PROPERTY_NAME)))
245 {
246 MailEntityOptionsTable::update(
247 [
248 'MAILBOX_ID' => $mailboxId,
249 'ENTITY_TYPE' => MailEntityOptionsTable::MAILBOX_TYPE_NAME,
250 'ENTITY_ID' => $mailboxId,
251 'PROPERTY_NAME' => MailEntityOptionsTable::SYNC_STATUS_PROPERTY_NAME,
252 ],
253 [
254 'DATE_INSERT' => $date,
255 'VALUE' => $status,
256 ],
257 );
258 }
259 else
260 {
261 MailEntityOptionsTable::insertIgnore(
262 $mailboxId,
263 $mailboxId,
264 MailEntityOptionsTable::MAILBOX_TYPE_NAME,
265 MailEntityOptionsTable::SYNC_STATUS_PROPERTY_NAME,
266 $status,
267 $date
268 );
269 }
270 }
271
276 public function getCachedMailboxesIdsWithConnectionError(?int $userId = null): array
277 {
278 global $USER;
279
280 if (!$userId && is_object($USER) && $USER->isAuthorized())
281 {
282 $userId = (int)$USER->getId();
283 }
284
285 if (!$userId)
286 {
287 return [];
288 }
289
290 static $userMailboxesIdsWithConnectionError = [];
291
292 if (isset($userMailboxesIdsWithConnectionError[$userId]))
293 {
294 return $userMailboxesIdsWithConnectionError[$userId];
295 }
296
297 $userMailboxesIdsWithConnectionError[$userId] = [];
298
299 $userMailboxIds = array_keys(MailboxTable::getUserMailboxes($userId, true));
300
301 if (empty($userMailboxIds))
302 {
303 return $userMailboxesIdsWithConnectionError[$userId];
304 }
305
306 $mailboxesWithConnectionError = MailEntityOptionsTable::getList(
307 [
308 'select' => [
309 'ENTITY_ID',
310 'VALUE',
311 ],
312 'filter' => [
313 '=ENTITY_TYPE' => MailEntityOptionsTable::MAILBOX_TYPE_NAME,
314 '=ENTITY_ID' => $userMailboxIds,
315 '=PROPERTY_NAME' => MailEntityOptionsTable::CONNECT_ERROR_ATTEMPT_COUNT_PROPERTY_NAME,
316 ],
317 ]
318 );
319
320 while ($error = $mailboxesWithConnectionError->fetch())
321 {
322 if ((int)$error['VALUE'] >= self::MAX_CONNECTION_ATTEMPTS_BEFORE_UNAVAILABLE)
323 {
324 $userMailboxesIdsWithConnectionError[$userId][] = (int)$error['ENTITY_ID'];
325 }
326 }
327
328 return $userMailboxesIdsWithConnectionError[$userId];
329 }
330
331 public function getMailboxesSyncInfo(): array
332 {
333 static $mailboxesSyncInfo = null;
334
335 if (is_null($mailboxesSyncInfo))
336 {
337 $mailboxesSyncInfo = [];
338
339 $userMailboxIds = array_keys(MailboxTable::getUserMailboxes(onlyIds: true));
340
341 if (empty($userMailboxIds))
342 {
343 return $mailboxesSyncInfo;
344 }
345
346 $datesLastOpening = MailEntityOptionsTable::getList(
347 [
348 'select' => [
349 'ENTITY_ID',
350 'VALUE',
351 'DATE_INSERT',
352 ],
353 'filter' => [
354 '=ENTITY_TYPE' => MailEntityOptionsTable::MAILBOX_TYPE_NAME,
355 '=ENTITY_ID' => $userMailboxIds,
356 '=PROPERTY_NAME' => MailEntityOptionsTable::SYNC_STATUS_PROPERTY_NAME,
357 ],
358 ]
359 )->fetchAll();
360
361 foreach ($datesLastOpening as $date)
362 {
363 if (isset($date['VALUE']))
364 {
365 $mailboxesSyncInfo[(int)$date['ENTITY_ID']] = [
366 'isSuccess' => (bool)$date['VALUE'],
367 'timeStarted' => $date['DATE_INSERT']->getTimestamp(),
368 ];
369 }
370 }
371
372 }
373
374 return $mailboxesSyncInfo;
375 }
376
380 public function getNextTimeToSync($lastMailCheckData)
381 {
382 return intval($lastMailCheckData['timeStarted']) + $this->mailCheckInterval - time();
383 }
384
385 /*
386 * Returns the time remaining until the required recommended mail synchronization.
387 * If it's time to synchronize, it will return 0.
388 */
389 public function getTimeBeforeNextSync()
390 {
391 $mailboxesSuccessSynced = $this->getSuccessSyncedMailboxes();
392 $timeBeforeNextSyncMailboxes = [];
393
394 foreach ($mailboxesSuccessSynced as $mailboxId => $lastMailCheckData)
395 {
396 $timeBeforeNextSyncMailboxes[] = intval($lastMailCheckData['timeStarted']) + $this->mailCheckInterval - time();
397 }
398
399 return !empty($timeBeforeNextSyncMailboxes) && min($timeBeforeNextSyncMailboxes) > 0 ? min($timeBeforeNextSyncMailboxes) : 0;
400 }
401
405 public function getFirstFailedToSyncMailboxId(): ?int
406 {
407 return $this->getCachedMailboxesIdsWithConnectionError()[0] ?? null;
408 }
409
417 public function getLastMailboxSyncIsSuccessStatus(int $mailboxId): ?bool
418 {
419 $mailboxesOptions = $this->getMailboxesSyncInfo();
420 if (!(isset($mailboxesOptions[$mailboxId]) && array_key_exists('isSuccess', $mailboxesOptions[$mailboxId])))
421 {
422 return null;
423 }
424
425 if (isset($mailboxesOptions[$mailboxId]['isSuccess']))
426 {
427 return (bool)$mailboxesOptions[$mailboxId]['isSuccess'];
428 }
429
430 return null;
431 }
432
433 public function getLastMailboxSyncTime($mailboxId)
434 {
435 $mailboxesOptions = $this->getMailboxesSyncInfo();
436 if (!(isset($mailboxesOptions[$mailboxId]) && array_key_exists('timeStarted', $mailboxesOptions[$mailboxId])))
437 {
438 return null;
439 }
440 return $mailboxesOptions[$mailboxId]['timeStarted'];
441 }
442}
getLastMailboxSyncIsSuccessStatus(int $mailboxId)
Определения mailboxsyncmanager.php:417
setSyncStatus(int $mailboxId, bool $isSuccess, ?int $time=null)
Определения mailboxsyncmanager.php:124
getNextTimeToSync($lastMailCheckData)
Определения mailboxsyncmanager.php:380
static checkSyncWithCrm(int $mailboxId)
Определения mailboxsyncmanager.php:26
getCachedMailboxesIdsWithConnectionError(?int $userId=null)
Определения mailboxsyncmanager.php:276
setSyncStartedData($mailboxId, $time=null)
Определения mailboxsyncmanager.php:119
static getUserMailboxes($userId=null, bool $onlyIds=false)
Определения mailbox.php:339
Определения result.php:20
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
global $USER
Определения csv_new_run.php:40
$status
Определения session.php:10
Определения arrayresult.php:2
$time
Определения payment.php:61
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$error
Определения subscription_card_product.php:20