1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
calendar_sync.php
См. документацию.
1<?php
2
17
19{
20 public const SYNC_TIME = 86400;
21 public static $attendeeList = [];
23 public static $doNotSendToGoogle = false;
24 private static $mobileBannerDisplay;
25
26
35 public static function ModifyEvent($calendarId, $arFields, $params = [])
36 {
37 [$sectionId, $entityType, $entityId] = $calendarId;
38 $userId = $entityType === 'user' ? $entityId : 0;
39 $eventId = false;
40
41 $bExchange = CCalendar::IsExchangeEnabled($userId) && $entityType === 'user';
42
43 CCalendar::SetSilentErrorMode();
44 if ($sectionId && ($section = CCalendarSect::GetById((int)$sectionId, false)))
45 {
46 CCalendar::SetOffset(false, CCalendar::GetOffset($userId));
47 $eventId = ((isset($arFields['ID']) && ((int)$arFields['ID'] > 0)) ? (int)$arFields['ID'] : 0);
48 $arNewFields = [
49 'DAV_XML_ID' => $arFields['XML_ID'],
50 'CAL_DAV_LABEL' => (isset($arFields['PROPERTY_BXDAVCD_LABEL']) && $arFields['PROPERTY_BXDAVCD_LABEL']) ? $arFields['PROPERTY_BXDAVCD_LABEL'] : '',
51 'DAV_EXCH_LABEL' => (isset($arFields['PROPERTY_BXDAVEX_LABEL']) && $arFields['PROPERTY_BXDAVEX_LABEL']) ? $arFields['PROPERTY_BXDAVEX_LABEL'] : '',
52 'ID' => $eventId,
53 'NAME' => $arFields['NAME'] ?: GetMessage('EC_NONAME_EVENT'),
54 'CAL_TYPE' => $section['CAL_TYPE'],
55 'OWNER_ID' => $section['OWNER_ID'],
56 'DESCRIPTION' => $arFields['DESCRIPTION'] ?? '',
57 'SECTIONS' => [$sectionId],
58 'ACCESSIBILITY' => $arFields['ACCESSIBILITY'] ?? 'busy',
59 'IMPORTANCE' => $arFields['IMPORTANCE'] ?? 'normal',
60 'REMIND' => (isset($arFields['REMIND']) && is_array($arFields['REMIND'])) ? $arFields['REMIND'] : [],
61 'RRULE' => (isset($arFields['RRULE']) && is_array($arFields['RRULE'])) ? $arFields['RRULE'] : [],
62 'VERSION' => isset($arFields['VERSION']) ? (int)$arFields['VERSION'] : 1,
63 'PRIVATE_EVENT' => (bool)($arFields['PRIVATE_EVENT'] ?? null)
64 ];
65
66 $currentEvent = CCalendarEvent::getList([
67 'arFilter' => [
68 'DAV_XML_ID' => $arNewFields['DAV_XML_ID'],
69 'DELETED' => 'N',
70 ],
71 'limit' => 1,
72 ]);
73
74 if ($currentEvent)
75 {
76 $currentEvent = $currentEvent[0];
77 }
78
79 $arNewFields['DATE_FROM'] = $arFields['DATE_FROM'];
80 $arNewFields['DATE_TO'] = $arFields['DATE_TO'];
81 $arNewFields['TZ_FROM'] = $arFields['TZ_FROM'];
82 $arNewFields['TZ_TO'] = $arFields['TZ_TO'];
83 $arNewFields['SKIP_TIME'] = $arFields['SKIP_TIME'];
84
85 if (isset($arFields['RECURRENCE_ID']))
86 {
87 $arNewFields['RECURRENCE_ID'] = $arFields['RECURRENCE_ID'];
88 }
89
90 if (isset($arFields['RECURRENCE_ID_DATE']) && $arFields['RECURRENCE_ID_DATE'])
91 {
92 $arNewFields['ORIGINAL_DATE_FROM'] = $arFields['RECURRENCE_ID_DATE'];
93 }
94
95 if (isset($arNewFields['SKIP_TIME']) && $arNewFields['SKIP_TIME'])
96 {
97 $arNewFields['DATE_FROM'] = CCalendar::Date(CCalendar::Timestamp($arNewFields['DATE_FROM']), false);
98 $arNewFields['DATE_TO'] = CCalendar::Date(CCalendar::Timestamp($arNewFields['DATE_TO']) - CCalendar::GetDayLen(), false);
99 }
100
101 if (!empty($arFields['PROPERTY_REMIND_SETTINGS']))
102 {
103 if (is_array($arFields['PROPERTY_REMIND_SETTINGS']))
104 {
105 foreach ($arFields['PROPERTY_REMIND_SETTINGS'] as $remindSetting)
106 {
107 $ar = explode('_', $remindSetting);
108 $arNewFields = self::prepareRemind($ar, $arNewFields);
109 }
110 }
111 else
112 {
113 $ar = explode('_', $arFields['PROPERTY_REMIND_SETTINGS']);
114 $arNewFields = self::prepareRemind($ar, $arNewFields);
115 }
116 }
117
118 if (!empty($arFields['PROPERTY_ACCESSIBILITY']))
119 {
120 $arNewFields['ACCESSIBILITY'] = $arFields['PROPERTY_ACCESSIBILITY'];
121 }
122 if (!empty($arFields['PROPERTY_IMPORTANCE']))
123 {
124 $arNewFields['IMPORTANCE'] = $arFields['PROPERTY_IMPORTANCE'];
125 }
126 if (!empty($arFields['PROPERTY_LOCATION']))
127 {
128 $arNewFields['LOCATION'] = Bitrix\Calendar\Rooms\Util::unParseTextLocation($arFields['PROPERTY_LOCATION']);
129 }
130 if (!empty($arFields['DETAIL_TEXT']))
131 {
132 if (empty($arFields['MEETING']['LANGUAGE_ID']))
133 {
134 $arNewFields['MEETING']['LANGUAGE_ID'] = CCalendar::getUserLanguageId((int)$arNewFields['OWNER_ID']);
135 }
136 $arNewFields['DESCRIPTION'] = self::CutAttendeesFromDescription(
137 $arFields['DETAIL_TEXT'],
138 self::getAttendeesCodesForCut($currentEvent['ATTENDEES_CODES'] ?? null),
139 $arNewFields['MEETING']['LANGUAGE_ID']
140 );
141 }
142
143 $arNewFields['DESCRIPTION'] = CCalendar::ClearExchangeHtml($arNewFields['DESCRIPTION']);
144
145 if (isset($arFields['PROPERTY_PERIOD_TYPE']) && in_array($arFields['PROPERTY_PERIOD_TYPE'], ["DAILY", "WEEKLY", "MONTHLY", "YEARLY"]))
146 {
147 $arNewFields['RRULE']['FREQ'] = $arFields["PROPERTY_PERIOD_TYPE"];
148 $arNewFields['RRULE']['INTERVAL'] = $arFields["PROPERTY_PERIOD_COUNT"];
149
150 if (!isset($arNewFields['DT_LENGTH']) && !empty($arFields['PROPERTY_EVENT_LENGTH']))
151 {
152 $arNewFields['DT_LENGTH'] = (int)$arFields['PROPERTY_EVENT_LENGTH'];
153 }
154 else if (isset($arFields['DT_TO_TS'], $arFields['DT_FROM_TS']))
155 {
156 $arNewFields['DT_LENGTH'] = $arFields['DT_TO_TS'] - $arFields['DT_FROM_TS'];
157 }
158 else
159 {
160 $arNewFields['DT_LENGTH'] = null;
161 }
162
163 if ($arNewFields['RRULE']['FREQ'] === "WEEKLY" && !empty($arFields['PROPERTY_PERIOD_ADDITIONAL']))
164 {
165 $arNewFields['RRULE']['BYDAY'] = [];
166 $bydays = explode(',',$arFields['PROPERTY_PERIOD_ADDITIONAL']);
167 foreach($bydays as $day)
168 {
169 $day = CCalendar::WeekDayByInd($day, false);
170 if ($day !== false)
171 {
172 $arNewFields['RRULE']['BYDAY'][] = $day;
173 }
174 }
175
176 $arNewFields['RRULE']['BYDAY'] = implode(',',$arNewFields['RRULE']['BYDAY']);
177 }
178
179 if (isset($arFields['PROPERTY_RRULE_COUNT']))
180 {
181 $arNewFields['RRULE']['COUNT'] = $arFields['PROPERTY_RRULE_COUNT'];
182 }
183 elseif (isset($arFields['PROPERTY_PERIOD_UNTIL']))
184 {
185 $arNewFields['RRULE']['UNTIL'] = $arFields['PROPERTY_PERIOD_UNTIL'];
186 }
187 else
188 {
189 $arNewFields['RRULE']['UNTIL'] = $arFields['DT_TO_TS'] ?? null;
190 }
191
192 if (isset($arFields['EXDATE']))
193 {
194 $arNewFields['EXDATE'] = $arFields["EXDATE"];
195 }
196 }
197
198 if (
199 isset($arFields['IS_MEETING'])
200 && $arFields['IS_MEETING']
201 && (($bExchange && self::isExchangeMeetingEnabled()) || $params['handleMeetingParams'])
202 )
203 {
204 $arNewFields['IS_MEETING'] = $arFields['IS_MEETING'];
205 $arNewFields['MEETING_HOST'] = $arFields['MEETING_HOST'];
206 $arNewFields['MEETING'] = $arFields['MEETING'];
207 $arNewFields['ATTENDEES_CODES'] = $arFields['ATTENDEES_CODES'];
208 }
209
210 $eventId = CCalendar::SaveEvent([
211 'arFields' => $arNewFields,
212 'userId' => $userId,
213 'bAffectToDav' => false, // Used to prevent synchro with calDav again
214 'bSilentAccessMeeting' => true,
215 'autoDetectSection' => false,
216 'sendInvitations' => ($params['sendInvitations'] ?? null) !== false,
217 'syncCaldav' => $params['caldav'] ?? null,
218 ]);
219
220 if ($eventId)
221 {
222 // Event actually is editing, but when it changes calendar category and
223 // comes from the external device it looks like its new event.
224 // But here we're trying to find original event and
225 // if it was in DB - we delete it to avoid duplication
226 if (
227 $currentEvent
228 && $currentEvent['ID']
229 && (int)$sectionId !== (int)$currentEvent['SECTION_ID']
230 && !$currentEvent['RECURRENCE_ID']
231 && $arNewFields['OWNER_ID'] === $currentEvent['OWNER_ID']
232 )
233 {
234 CCalendar::DeleteEvent($currentEvent['ID']);
235 }
236 }
237 else
238 {
239 CCalendarSect::UpdateModificationLabel($sectionId);
240 }
241
242 if (
243 $eventId
244 && ($arFields['IS_MEETING'] ?? null)
245 && ($arFields['ATTENDEES_RESPONSE'] ?? null)
246 && $bExchange
247 && self::isExchangeMeetingEnabled()
248 )
249 {
250 foreach($arFields['ATTENDEES_RESPONSE'] as $attendeeId => $status)
251 {
252 CCalendarEvent::SetMeetingStatus([
253 'userId' => $attendeeId,
254 'eventId' => $eventId,
255 'status' => $status,
256 'personalNotification' => false,
257 'hostNotification' => false,
258 'affectRecRelatedEvents' => false,
259 'updateDescription' => false,
260 'doSendMail' => false,
261 ]);
262 }
263 }
264 }
265
266 CCalendar::SetSilentErrorMode(false);
267
268 return $eventId;
269 }
270
271 public static function ModifyReccurentInstances($params = array())
272 {
273 CCalendar::SetSilentErrorMode();
274 $parentEvent = CCalendarEvent::GetById($params['parentId']);
275
276 if ($parentEvent && CCalendarEvent::CheckRecurcion($parentEvent))
277 {
278 $excludeDates = CCalendarEvent::GetExDate($parentEvent['EXDATE']);
279
280 foreach ($params['events'] as $arFields)
281 {
282 if (isset($parentEvent['IS_MEETING']) && $parentEvent['IS_MEETING'])
283 {
284 $arFields['IS_MEETING'] = $parentEvent['IS_MEETING'];
285 $arFields['MEETING_HOST'] = $parentEvent['MEETING_HOST'];
286 $arFields['MEETING'] = $parentEvent['MEETING'];
287 $arFields['ATTENDEES_CODES'] = $parentEvent['ATTENDEES_CODES'];
288 }
289
290 $arFields['RECURRENCE_ID'] = $parentEvent['ID'];
292 $params['calendarId'],
293 $arFields,
294 [
295 'handleMeetingParams' => $parentEvent['IS_MEETING'],
296 'sendInvitations' => false,
297 ]);
298
299 if ($arFields['RECURRENCE_ID_DATE'])
300 {
301 $excludeDates[] = CCalendar::Date(CCalendar::Timestamp($arFields['RECURRENCE_ID_DATE']), false);
302 }
303 }
304
305 $res = CCalendar::SaveEventEx(array(
306 'arFields' => array(
307 'ID' => $parentEvent['ID'],
308 'EXDATE' => CCalendarEvent::SetExDate($excludeDates)
309 ),
310 'bSilentAccessMeeting' => true,
311 'recursionEditMode' => 'skip',
312 'silentErrorMode' => true,
313 'sendInvitations' => false,
314 'bAffectToDav' => false,
315 'sendEditNotification' => false
316 ));
317 }
318
319 CCalendar::SetSilentErrorMode(false);
320 }
321
322 public static function DoSaveToDav(&$arFields, $params = [], $event = false)
323 {
324 $sectionId = $params['sectionId'];
325 $modeSync = $params['modeSync'];
326 $parameters['editInstance'] = $params['editInstance'];
327 $bExchange = $params['bExchange'];
328 $bCalDav = $params['bCalDav'];
329 $parameters['syncCaldav'] = $params['syncCaldav'];
330
331 if (isset($event['DAV_XML_ID']))
332 {
333 $arFields['DAV_XML_ID'] = $event['DAV_XML_ID'];
334 }
335 if (isset($event['DAV_EXCH_LABEL']))
336 {
337 $arFields['DAV_EXCH_LABEL'] = $event['DAV_EXCH_LABEL'];
338 }
339 if (isset($event['CAL_DAV_LABEL']))
340 {
341 $arFields['CAL_DAV_LABEL'] = $event['CAL_DAV_LABEL'];
342 }
343 if (!isset($arFields['DATE_CREATE']) && isset($event['DATE_CREATE']))
344 {
345 $arFields['DATE_CREATE'] = $event['DATE_CREATE'];
346 }
347 if (!isset($arFields['G_EVENT_ID']) && isset($event['G_EVENT_ID']))
348 {
349 $arFields['G_EVENT_ID'] = $event['G_EVENT_ID'];
350 }
351
352 $section = CCalendarSect::GetById($sectionId, false);
353
354 if ($event && (int)$event['SECT_ID'] !== (int)$sectionId)
355 {
356 $bCalDavCur = CCalendar::IsCalDAVEnabled() && $event['CAL_TYPE'] === 'user' && $event['CAL_DAV_LABEL'] <> '';
357 $bExchangeEnabledCur = CCalendar::IsExchangeEnabled() && $event['CAL_TYPE'] === 'user';
358
359 if ($bExchangeEnabledCur || $bCalDavCur)
360 {
362 'bCalDav' => $bCalDavCur,
363 'bExchangeEnabled' => $bExchangeEnabledCur,
364 'sectionId' => $event['SECT_ID']
365 ), $event);
366
367 if ($event['DAV_EXCH_LABEL'])
368 {
369 $event['DAV_EXCH_LABEL'] = '';
370 }
371
372 if ($res !== true)
373 {
374 return CCalendar::ThrowError($res);
375 }
376
377 //to save as a new event, not update an existing one
378 $newSection = CCalendarSect::GetById($event['SECT_ID'], false);
379
380 if ($section['CAL_DAV_CON'] === $newSection['CAL_DAV_CON']
381 && $section['ID'] !== $newSection['ID'])
382 {
383 unset($arFields['DAV_XML_ID']);
384 }
385 }
386 }
387
388 $arDavFields = $arFields;
389 CCalendarEvent::CheckFields($arDavFields);
390
391 if ($arDavFields['RRULE'] != '')
392 {
393 $arDavFields['RRULE'] = $arFields['RRULE'];
394 }
395
396 if ($arDavFields['LOCATION']['NEW'] !== '')
397 {
398 $arDavFields['LOCATION']['NEW'] = CCalendar::GetTextLocation($arDavFields['LOCATION']['NEW']);
399 }
400 $arDavFields['PROPERTY_IMPORTANCE'] = $arDavFields['IMPORTANCE'];
401 $arDavFields['PROPERTY_LOCATION'] = $arDavFields['LOCATION']['NEW'];
402
403 $arDavFields['PROPERTY_REMIND_SETTINGS'] = '';
404 if (!empty($arFields['REMIND'][0]) && is_array($arFields['REMIND'][0]))
405 {
406 $arDavFields['PROPERTY_REMIND_SETTINGS'] = floatVal($arFields['REMIND'][0]['count'] ?? null)
407 . '_' . $arFields['REMIND'][0]['type'];
408 }
409
410 if (isset($arDavFields['RRULE']['BYDAY']) && is_array($arDavFields['RRULE']['BYDAY']))
411 {
412 $arDavFields['RRULE']['BYDAY'] = implode(',',$arDavFields['RRULE']['BYDAY']);
413 }
414
415 // **** Synchronize with CalDav ****
416 if ($bCalDav && ($section['CAL_DAV_CON'] ?? null) > 0 && empty($parameters['syncCaldav']))
417 {
418 // New event or move existent event to DAV calendar
419 if ((int)($arFields['ID'] ?? null) <= 0 || ($event && empty($event['CAL_DAV_LABEL'])))
420 {
421 $DAVRes = CDavGroupdavClientCalendar::DoAddItem(
422 $section['CAL_DAV_CON'],
423 $section['CAL_DAV_CAL'] ?? null,
424 $arDavFields
425 );
426 }
427 else // Edit existent event
428 {
429 $DAVRes = CDavGroupdavClientCalendar::DoUpdateItem(
430 $section['CAL_DAV_CON'],
431 $section['CAL_DAV_CAL'] ?? null,
432 $event['DAV_XML_ID'] ?? null,
433 $event['CAL_DAV_LABEL'] ?? null,
434 $arDavFields
435 );
436 }
437
438 if (!is_array($DAVRes) || !isset($DAVRes['XML_ID']))
439 {
440 return CCalendar::CollectCalDAVErros($DAVRes);
441 }
442
443 // // It's ok, we successfuly save event to caldav calendar - and save it to DB
444 $arFields['DAV_XML_ID'] = $DAVRes['XML_ID'];
445 $arFields['CAL_DAV_LABEL'] = $DAVRes['MODIFICATION_LABEL'];
446 }
447 // **** Synchronize with Exchange ****
448 elseif ($bExchange && $section['IS_EXCHANGE'] && $section['DAV_EXCH_CAL'] <> '' && $section['DAV_EXCH_CAL'] !== 0 && $modeSync)
449 {
450 $ownerId = $arFields['OWNER_ID'] ?? null;
451
452 // Here we check if parent event was created in exchange calendar and if it is meeting
453 // If yes, we expect that it was already created in MS Exchange server
454 // and we don't need to dublicate this entry.
455 if (
456 self::isExchangeMeetingEnabled()
457 && ($arFields['IS_MEETING'] ?? null)
458 && ($arFields['MEETING_HOST'] ?? null) != $ownerId
459 && CCalendar::IsExchangeEnabled($arFields['MEETING_HOST'] ?? null)
460 )
461 {
462 $parentEvent = CCalendarEvent::GetById($arFields['PARENT_ID']);
463 if ($parentEvent['DAV_EXCH_LABEL'])
464 {
465 $parentSection = CCalendarSect::GetById($parentEvent['SECT_ID'], false);
466 if (
467 $parentSection['IS_EXCHANGE']
468 && $parentSection['DAV_EXCH_CAL'] <> ''
469 && $parentSection['DAV_EXCH_CAL'] !== 0)
470 {
471 return;
472 }
473 }
474 }
475
476 if (
477 self::isExchangeMeetingEnabled()
478 && $arFields['IS_MEETING']
479 && (int)$arFields['MEETING_HOST'] === (int)$ownerId
480 && !empty($arFields['ATTENDEES'])
481 )
482 {
483 $arDavFields['REQUIRED_ATTENDEES'] = self::GetExchangeEmailForUser($arFields['ATTENDEES']);
484 if (empty($arDavFields['REQUIRED_ATTENDEES']))
485 {
486 unset($arDavFields['REQUIRED_ATTENDEES']);
487 }
488 }
489
490 $fromTo = CCalendarEvent::GetEventFromToForUser($arDavFields, $ownerId);
491 $arDavFields["DATE_FROM"] = $fromTo['DATE_FROM'];
492 $arDavFields["DATE_TO"] = $fromTo['DATE_TO'];
493
494 // Convert BBcode to HTML for exchange
495 $arDavFields["DESCRIPTION"] = CCalendarEvent::ParseText($arDavFields['DESCRIPTION']);
496 $updateEvent = !($params['editInstance']);
497
498 if ($params['editParentEvents'] && !empty($arDavFields['RRULE']['UNTIL']))
499 {
500 $until = Type\Date::createFromTimestamp($arDavFields['DATE_TO_TS_UTC']);
501 $arDavFields['DATE_TO_TS_UTC'] = $until->add('-1 day')->getTimestamp();
502 }
503
504 // New event or move existent event to Exchange calendar
505 if (
506 (int)($arFields['ID'] ?? null) === 0
507 || ($event && !$event['DAV_EXCH_LABEL'] && $updateEvent)
508 )
509 {
510 $exchRes = CDavExchangeCalendar::DoAddItem($ownerId, $section['DAV_EXCH_CAL'], $arDavFields);
511 }
512 else
513 {
514 $exchRes = CDavExchangeCalendar::DoUpdateItem($ownerId, $event['DAV_XML_ID'], $event['DAV_EXCH_LABEL'], $arDavFields, $params);
515 }
516
517 if (!is_array($exchRes) || !array_key_exists("XML_ID", $exchRes))
518 {
519 return CCalendar::CollectExchangeErrors($exchRes);
520 }
521
522 // It's ok, we successfuly save event to exchange calendar - and save it to DB
523 $arFields['DAV_XML_ID'] = $exchRes['XML_ID'];
524 $arFields['DAV_EXCH_LABEL'] = $exchRes['MODIFICATION_LABEL'];
525 }
526
527 return true;
528 }
529
530 public static function DoDeleteToDav($params, $event)
531 {
532 $sectionId = $params['sectionId'];
533 $section = CCalendarSect::GetById($sectionId, false);
534
535 $bExchangeEnabled = $params['bExchangeEnabled'];
536 $bCalDav = $params['bCalDav'];
537
538 // Google and other caldav
539 if ($bCalDav && $section['CAL_DAV_CON'] > 0 && $event['CAL_DAV_LABEL'])
540 {
541 $DAVRes = CDavGroupdavClientCalendar::DoDeleteItem($section['CAL_DAV_CON'], $section['CAL_DAV_CAL'], $event['DAV_XML_ID']);$service = new \Bitrix\Calendar\Sync\Icloud\VendorSyncService();
542 if ($DAVRes !== true)
543 {
544 return CCalendar::CollectCalDAVErros($DAVRes);
545 }
546 }
547 // Exchange
548 if ($bExchangeEnabled && $section['IS_EXCHANGE'])
549 {
550 $exchRes = CDavExchangeCalendar::DoDeleteItem($event['OWNER_ID'], $event['DAV_XML_ID']);
551 if ($exchRes !== true)
552 return CCalendar::CollectExchangeErrors($exchRes);
553 }
554
555 return true;
556 }
557
558 public static function SyncCalendarSections($connectionType, $arCalendars, $entityType, $entityId, $connectionId = null): array
559 {
560 //Array(
561 // [0] => Array(
562 // [XML_ID] => calendar
563 // [NAME] => calendar
564 // )
565 // [1] => Array(
566 // [XML_ID] => AQATAGFud...
567 // [NAME] => geewgvwe 1
568 // [DESCRIPTION] => gewgvewgvw
569 // [COLOR] => #FF0000
570 // [MODIFICATION_LABEL] => af720e7c7b6a
571 // )
572 //)
573
574 $result = [];
575 if (
576 $connectionType === Bitrix\Calendar\Sync\Caldav\Helper::EXCHANGE_TYPE
577 || $connectionType === Bitrix\Calendar\Sync\Caldav\Helper::CALDAV_TYPE
578 )
579 {
580 CCalendar::SetSilentErrorMode();
581 $entityType = mb_strtolower($entityType);
582 $entityId = (int)$entityId;
583
584 $tempUser = CCalendar::TempUser(false, true);
585 $calendarNames = [];
586 foreach ($arCalendars as $value)
587 {
588 $calendarNames[$value["XML_ID"]] = $value;
589 }
590
591 if ($connectionType === Bitrix\Calendar\Sync\Caldav\Helper::CALDAV_TYPE)
592 {
593 $arFilter = [
594 'CAL_TYPE' => $entityType,
595 'OWNER_ID' => $entityId,
596 '!CAL_DAV_CAL' => false,
597 'CAL_DAV_CON' => $connectionId
598 ];
599 $xmlIdField = "CAL_DAV_CAL";
600 $xmlIdModLabel = "CAL_DAV_MOD";
601 }
602 else // Exchange
603 {
604 $arFilter = [
605 'CAL_TYPE' => $entityType,
606 'OWNER_ID' => $entityId,
607 '!DAV_EXCH_CAL' => false,
608 'IS_EXCHANGE' => 1
609 ];
610 $xmlIdField = "DAV_EXCH_CAL";
611 $xmlIdModLabel = "DAV_EXCH_MOD";
612 }
613
614 $res = CCalendarSect::GetList([
615 'arFilter' => $arFilter,
616 'checkPermissions' => false,
617 'getPermissions' => false
618 ]);
619
620 foreach($res as $section)
621 {
622 $xmlId = $section[$xmlIdField];
623 $modificationLabel = $section[$xmlIdModLabel];
624
625 if (
626 empty($xmlId)
627 || ($connectionType === Bitrix\Calendar\Sync\Caldav\Helper::CALDAV_TYPE && $section['DAV_EXCH_CAL'])
628 )
629 {
630 continue;
631 }
632
633 if (!array_key_exists($xmlId, $calendarNames))
634 {
635 CCalendarSect::Delete($section["ID"]);
636 }
637 else
638 {
639 if ($modificationLabel !== $calendarNames[$xmlId]["MODIFICATION_LABEL"])
640 {
641 CCalendarSect::Edit([
642 'arFields' => [
643 "ID" => $section["ID"],
644 "NAME" => $calendarNames[$xmlId]["NAME"],
645 "OWNER_ID" => $entityType === 'user' ? $entityId : 0,
646 "CREATED_BY" => $entityType === 'user' ? $entityId : 0,
647 "DESCRIPTION" => $calendarNames[$xmlId]["DESCRIPTION"],
648 "COLOR" => $calendarNames[$xmlId]["COLOR"],
649 $xmlIdModLabel => $calendarNames[$xmlId]["MODIFICATION_LABEL"],
650 ]
651 ]);
652 }
653
654 if (empty($modificationLabel) || ($modificationLabel !== $calendarNames[$xmlId]["MODIFICATION_LABEL"]))
655 {
656 $result[] = [
657 "XML_ID" => $xmlId,
658 "CALENDAR_ID" => [$section["ID"], $entityType, $entityId]
659 ];
660 }
661
662 unset($calendarNames[$xmlId]);
663 }
664 }
665
666 foreach($calendarNames as $key => $value)
667 {
668 $arFields = [
669 'CAL_TYPE' => $entityType,
670 'OWNER_ID' => $entityId,
671 'NAME' => $value["NAME"],
672 'DESCRIPTION' => $value["DESCRIPTION"] ?? null,
673 'COLOR' => $value["COLOR"] ?? null,
674 'EXPORT' => ['ALLOW' => false],
675 'CREATED_BY' => $entityType === 'user' ? $entityId : 0,
676 'ACCESS' => [],
677 'EXTERNAL_TYPE' => $connectionType,
678 $xmlIdField => $key,
679 $xmlIdModLabel => $value["MODIFICATION_LABEL"] ?? null
680 ];
681
682 if ($connectionType === Bitrix\Calendar\Sync\Caldav\Helper::CALDAV_TYPE)
683 {
684 $arFields["CAL_DAV_CON"] = $connectionId;
685 }
686 if ($entityType === 'user')
687 {
688 $arFields["CREATED_BY"] = $entityId;
689 }
690 if ($connectionType === Bitrix\Calendar\Sync\Caldav\Helper::EXCHANGE_TYPE)
691 {
692 $arFields["IS_EXCHANGE"] = 1;
693 }
694
695 $id = (int)CCalendar::SaveSection(['arFields' => $arFields, 'bAffectToDav' => false]);
696 if ($id)
697 {
698 $result[] =
699 [
700 "XML_ID" => $key,
701 "CALENDAR_ID" => [
702 $id,
703 $entityType,
705 ]
706 ];
707 }
708 }
709
710 CCalendar::TempUser($tempUser, false);
711 CCalendar::SetSilentErrorMode(false);
712 }
713
714 return $result;
715 }
716
717 public static function GetExchangeEmailForUser($idList = [])
718 {
719 global $DB;
720
721 $users = [];
722
723 if (CCalendar::IsSocNet())
724 {
725 if(is_array($idList))
726 {
727 $idList = array_unique($idList);
728 }
729 else
730 {
731 $idList = array($idList);
732 }
733
734 $strIdList = "";
735 foreach($idList as $id)
736 {
737 if((int)$id > 0)
738 {
739 $strIdList .= ','.(int)$id;
740 }
741 }
742 $strIdList = trim($strIdList, ', ');
743
744 if($strIdList != '')
745 {
746 $exchangeMailbox = COption::GetOptionString("dav", "exchange_mailbox", "");
747 $exchangeUseLogin = COption::GetOptionString("dav", "exchange_use_login", "Y");
748
749 $strSql = "SELECT U.ID, U.LOGIN, U.EMAIL, BUF.UF_BXDAVEX_MAILBOX
750 FROM b_user U
751 LEFT JOIN b_uts_user BUF ON (BUF.VALUE_ID = U.ID)
752 WHERE
753 U.ACTIVE = 'Y' AND
754 U.ID in (".$strIdList.")";
755
756 $res = $DB->Query($strSql);
757 while($entry = $res->Fetch())
758 {
759 $users[$entry['ID']] = (($exchangeUseLogin === "Y")
760 ? $entry["LOGIN"].$exchangeMailbox
761 : $entry["UF_BXDAVEX_MAILBOX"])
762 ;
763 if (empty($users[$entry['ID']]))
764 {
765 $users[$entry['ID']] = $entry['EMAIL'];
766 }
767 }
768 }
769 }
770
771 return $users;
772 }
773
774 public static function isExchangeMeetingEnabled()
775 {
776 if (!isset(self::$handleExchangeMeeting))
777 {
778 self::$handleExchangeMeeting = COption::GetOptionString('calendar', 'sync_exchange_meeting', false);
779 }
780 return self::$handleExchangeMeeting;
781 }
782
783 public static function isTaskListSyncEnabled()
784 {
785 $userSettings = UserSettings::get();
786 return $userSettings['showTasks'] === 'Y' && $userSettings['syncTasks'] === 'Y';
787 }
788
798 public static function CutAttendeesFromDescription(
799 ?string $description,
800 ?array $attendeesCodes,
801 ?string $languageId
802 ): ?string
803 {
804 if (empty($attendeesCodes))
805 {
806 return $description;
807 }
808
809 IncludeModuleLangFile($_SERVER["DOCUMENT_ROOT"].BX_ROOT."/modules/calendar/lib/sync/googleapisync.php");
810
811 $deleteParts = Util::getAttendees($attendeesCodes, "%");
812 $countSeparators = count($attendeesCodes) - 1;
813 $deleteParts[] = '%' . \Bitrix\Main\Localization\Loc::getMessage('ATTENDEES_EVENT', null, $languageId) . ':%';
814 $description = preg_replace($deleteParts, '', $description, 1);
815
816 return trim(preg_replace("%,%", "", $description, $countSeparators));
817 }
818
819
824 public static function getAttendeesCodesForCut($attendeesCodes): ?array
825 {
826 if (is_array($attendeesCodes))
827 {
828 return $attendeesCodes;
829 }
830
831 if (is_string($attendeesCodes) && $res = explode(',', $attendeesCodes))
832 {
833 return $res;
834 }
835
836 return null;
837 }
838
839 public static function getTimestampWithUserOffset($userId): Closure
840 {
841 $offset = \CTimeZone::GetOffset($userId, true);
842 return static function($date) use ($offset) {
843 return $date
844 ? \CCalendar::Timestamp($date, false, true) - $offset
845 : null;
846 };
847 }
848
849 public static function GetSyncInfo($params = [])
850 {
851 $userId = \CCalendar::getCurUserId();
852 $macSyncInfo = self::GetSyncInfoItem($userId, 'mac');
853 $iphoneSyncInfo = self::GetSyncInfoItem($userId, 'iphone');
854 $androidSyncInfo = self::GetSyncInfoItem($userId, 'android');
855 $outlookSyncInfo = self::GetMultipleSyncInfoItem($userId, 'outlook');
856 $exchangeSyncInfo = self::GetSyncInfoItem($userId, 'exchange');
857
859 $bExchangeConnected = false;
860 $bExchange = false;
861 if (Loader::includeModule('dav'))
862 {
863 $bExchange = \CCalendar::IsExchangeEnabled() && $params['type'] === 'user';
864 $bExchangeConnected = $bExchange && \CDavExchangeCalendar::IsExchangeEnabledForUser($userId);
865 }
866
867 $calculateTimestamp = self::getTimestampWithUserOffset($userId);
868
869 $syncInfo = [
870 'mac' => [
871 'type' => 'mac',
872 'active' => true,
873 'connected' => $macSyncInfo['connected'],
874 'status' => $macSyncInfo['status'],
875 'syncOffset' => time() - $calculateTimestamp($macSyncInfo['date']),
876 ],
877 'iphone' => [
878 'type' => 'iphone',
879 'active' => true,
880 'connected' => $iphoneSyncInfo['connected'],
881 'status' => $iphoneSyncInfo['status'],
882 'syncOffset' => time() - $calculateTimestamp($iphoneSyncInfo['date']),
883 ],
884 'android' => [
885 'type' => 'android',
886 'active' => true,
887 'connected' => $androidSyncInfo['connected'],
888 'status' => $androidSyncInfo['status'],
889 'syncOffset' => time() - $calculateTimestamp($androidSyncInfo['date']),
890 ],
891 ];
892
893
894 if (!(!Loader::includeModule('webservice') && $connection->getType() === 'pgsql'))
895 {
896 $syncInfo['outlook'] = [
897 'type' => 'outlook',
898 'active' => true,
899 'connected' => $outlookSyncInfo['connected'],
900 'status' => $outlookSyncInfo['status'],
901 'infoBySections' => ($outlookSyncInfo['infoBySections'] ?? ''),
902 'syncOffset' => time() - $calculateTimestamp($outlookSyncInfo['date'] ?? false),
903 ];
904 }
905
906 if (!Loader::includeModule('bitrix24'))
907 {
908 $syncInfo['exchange'] = [
909 'type' => 'exchange',
910 'active' => $bExchange,
911 'connected' => $bExchangeConnected,
912 'status' => $exchangeSyncInfo['status'],
913 'syncOffset' => time() - $calculateTimestamp($exchangeSyncInfo['date']),
914 ];
915 }
916
917 $caldavConnections = self::GetCaldavItemsInfo($userId, $params['type'], $calculateTimestamp);
918 if (is_array($caldavConnections))
919 {
920 $syncInfo = array_merge($syncInfo, $caldavConnections);
921 }
922
923 $newSyncConnections = self::getNewSyncItemsInfo($userId, $calculateTimestamp);
924 if (!empty($newSyncConnections))
925 {
926 $syncInfo = array_merge($syncInfo, $newSyncConnections);
927 }
928
929 $syncInfo['counters']['sync_errors'] = Internals\Counter::getInstance($userId)->get(
931 );
932
933 return $syncInfo;
934 }
935
941 public static function GetSyncInfoItem($userId, $syncType): array
942 {
943 $activeSyncPeriod = self::SYNC_TIME;
944 $syncTypes = array('iphone', 'android', 'mac', 'exchange');
945 $result = [
946 'connected' => false,
947 'status' => false,
948 ];
949
950 if (in_array($syncType, $syncTypes, true))
951 {
952 $result['date'] = CUserOptions::GetOption("calendar", "last_sync_".$syncType, false, $userId);
953 }
954
955 if ($result['date'])
956 {
957 $result['date'] = CCalendar::Date(CCalendar::Timestamp($result['date']) + CCalendar::GetOffset($userId), true, true, true);
958 $period = time() - CCalendar::Timestamp($result['date']);
959
960 if ($period <= $activeSyncPeriod)
961 {
962 $result['connected'] = true;
963 $result['status'] = true;
964 }
965 }
966
967 return $result;
968 }
969
975 public static function GetMultipleSyncInfoItem($userId, $syncType): array
976 {
977 $activeSyncPeriod = 604800; // 3600 * 24 * 7 - one week
978 $syncTypes = ['outlook'];
979 $lastSync = null;
980 $result = [
981 'connected' => false,
982 'status' => false,
983 'syncOffset' => $activeSyncPeriod
984 ];
985
986 if (in_array($syncType, $syncTypes, true))
987 {
988 $options = CUserOptions::GetOption("calendar", "last_sync_".$syncType, false, $userId);
989 }
990
991 if ($options !== false)
992 {
993 if (is_array($options))
994 {
995 foreach ($options as $key => &$date)
996 {
997 $dateTs = \CCalendar::Timestamp($date, false);
998 $period = time() - $dateTs;
999
1000 if ($dateTs > $lastSync)
1001 {
1002 $lastSync = $dateTs;
1003 }
1004
1005 if ($period <= $activeSyncPeriod)
1006 {
1007 $result['connected'] = true;
1008 $result['status'] = true;
1009 $result['syncOffset'] = $period;
1010 }
1011 }
1012
1013 $result['infoBySections'] = $options;
1014 }
1015 else
1016 {
1017 $lastSync = \CCalendar::Timestamp($options, false);
1018 $period = time() - $lastSync;
1019 if ($period <= $activeSyncPeriod)
1020 {
1021 $result['connected'] = true;
1022 $result['status'] = true;
1023 $result['syncOffset'] = $period;
1024 }
1025 }
1026 }
1027
1028 return $result;
1029 }
1030
1039 public static function GetCaldavItemsInfo($userId, $type, $calculateTimestamp): ?array
1040 {
1041 $connections = [];
1042 $bCalDAV = CCalendar::IsCalDAVEnabled() && $type === 'user';
1043 $bGoogleApi = CCalendar::isGoogleApiEnabled() && $type === 'user';
1044
1045 if ($bCalDAV || $bGoogleApi)
1046 {
1047 $res = CDavConnection::GetList(
1048 ['ID' => 'DESC'],
1049 [
1050 'ENTITY_TYPE' => 'user',
1051 'ENTITY_ID' => $userId,
1052 'ACCOUNT_TYPE' =>
1053 [
1054 Bitrix\Calendar\Sync\Caldav\Helper::CALDAV_TYPE,
1055 ],
1056 'IS_DELETED' => 'N'
1057 ]
1058 );
1059 $isRussian = Util::checkRuZone();
1061 $googleHelper = ServiceLocator::getInstance()->get('calendar.service.google.helper');
1063 $caldavHelper = ServiceLocator::getInstance()->get('calendar.service.caldav.helper');
1064
1065 while ($connection = $res->Fetch())
1066 {
1067 if ($connection['ACCOUNT_TYPE'] === Bitrix\Calendar\Sync\Caldav\Helper::CALDAV_TYPE)
1068 {
1069 if ($caldavHelper->isYandex($connection['SERVER_HOST']) && $isRussian)
1070 {
1072 'id' => $connection['ID'],
1073 'active' => true,
1074 'connected' => true,
1075 'userName' => $connection['SERVER_USERNAME'],
1076 'connectionName' => $connection['NAME'],
1078 'status' => self::isConnectionSuccess($connection['LAST_RESULT']),
1079 'server' => $connection['SERVER'],
1080 'syncOffset' => time() - $calculateTimestamp($connection['SYNCHRONIZED']),
1081 ];
1082 }
1083 else
1084 {
1085 $connections[Bitrix\Calendar\Sync\Caldav\Helper::CALDAV_TYPE . $connection['ID']] = [
1086 'id' => $connection['ID'],
1087 'active' => true,
1088 'connected' => true,
1089 'userName' => $connection['SERVER_USERNAME'],
1090 'connectionName' => $connection['NAME'],
1091 'type' => Bitrix\Calendar\Sync\Caldav\Helper::CALDAV_TYPE,
1092 'status' => self::isConnectionSuccess($connection['LAST_RESULT']),
1093 'server' => $connection['SERVER'],
1094 'syncOffset' => time() - $calculateTimestamp($connection['SYNCHRONIZED']),
1095 ];
1096 }
1097 }
1098 }
1099
1100 return $connections;
1101 }
1102
1103 return null;
1104 }
1105
1106 public static function getNewSyncItemsInfo($userId, $calculateTimestamp): array
1107 {
1108 $result = [];
1109
1110 if (!Loader::includeModule('dav'))
1111 {
1112 return $result;
1113 }
1114
1115 $connections = CDavConnection::GetList(
1116 ['ID' => 'DESC'],
1117 [
1118 'ENTITY_TYPE' => 'user',
1119 'ENTITY_ID' => $userId,
1120 'ACCOUNT_TYPE' => Sync\Dictionary::NEW_SYNC_PROVIDERS_TYPE,
1121 'IS_DELETED' => 'N'
1122 ]
1123 );
1124
1126 $googleHelper = ServiceLocator::getInstance()->get('calendar.service.google.helper');
1128 $iCloudHelper = ServiceLocator::getInstance()->get('calendar.service.icloud.helper');
1130 $office365Helper = ServiceLocator::getInstance()->get('calendar.service.office365.helper');
1131
1132 while ($connection = $connections->Fetch())
1133 {
1134 if (
1135 $iCloudHelper->isVendorConnection($connection['ACCOUNT_TYPE'])
1136 || $office365Helper->isVendorConnection($connection['ACCOUNT_TYPE'])
1137 )
1138 {
1139 $result[$connection['ACCOUNT_TYPE']] = [
1140 'id' => $connection['ID'],
1141 'active' => true,
1142 'connected' => true,
1143 'userName' => $connection['SERVER_USERNAME'],
1144 'connectionName' => $connection['NAME'],
1145 'type' => $connection['ACCOUNT_TYPE'],
1146 'status' => self::isConnectionSuccess($connection['LAST_RESULT']),
1147 'server' => $connection['SERVER'],
1148 'syncOffset' => time() - $calculateTimestamp($connection['SYNCHRONIZED']),
1149 ];
1150 }
1151 else if ($googleHelper->isGoogleConnection($connection['ACCOUNT_TYPE']))
1152 {
1153 $result[$googleHelper::CONNECTION_NAME] = [
1154 'type' => $googleHelper::CONNECTION_NAME,
1155 'id' => $connection['ID'],
1156 'active' => true,
1157 'connected' => true,
1158 'userName' => $connection['SERVER_USERNAME'] ?? null,
1159 'connectionName' => $connection['NAME'],
1160 'status' => self::isConnectionSuccess($connection['LAST_RESULT']),
1161 'syncOffset' => time() - $calculateTimestamp($connection['SYNCHRONIZED']),
1162 ];
1163
1164 }
1165 }
1166
1167 return $result;
1168 }
1169
1170 public static function getSyncLinks(): array
1171 {
1172 $googleService = Bitrix\Calendar\Core\Oauth\Factory::getInstance()->getByName('google');
1173 $office365Service = Bitrix\Calendar\Core\Oauth\Factory::getInstance()->getByName('office365');
1174
1175 return [
1176 'google' => $googleService ? $googleService->getUrl() : '',
1177 'office365' => $office365Service ? $office365Service->getUrl() : '',
1178 ];
1179 }
1180
1185 public static function SetSectionStatus(?int $userId = 0, ?array $sectionsStatus = []): void
1186 {
1187 if (is_array($sectionsStatus))
1188 {
1189 foreach ($sectionsStatus as $id => $status)
1190 {
1191 $section = CCalendarSect::GetById($id);
1192
1193 if ((int)$section['OWNER_ID'] === $userId)
1194 {
1195 $sectionStatus = [
1196 'ID' => $id,
1197 'ACTIVE' => $status
1198 ? 'Y'
1199 : 'N',
1200 ];
1201
1202 $params['arFields'] = $sectionStatus;
1203 $params['userId'] = $userId;
1204 \CCalendarSect::Edit($params);
1205 }
1206 }
1207 }
1208 }
1209
1214 public static function UpdateUserConnections(): bool
1215 {
1216 $userId = \CCalendar::getCurUserId();
1217 if (Loader::includeModule('dav'))
1218 {
1219 \CDavGroupdavClientCalendar::DataSync("user", $userId);
1220
1222
1223 if (\CCalendar::isGoogleApiEnabled() || \CCalendar::isOffice365ApiEnabled())
1224 {
1226 FactoriesCollection::createByUserId(
1227 $userId,
1228 [
1231 ]
1232 )
1233 );
1234 $manager->import();
1235 }
1236
1237 if (CCalendar::IsExchangeEnabled($userId))
1238 {
1239 $error = "";
1240 \CDavExchangeCalendar::DoDataSync($userId, $error);
1241 echo $error;
1242 }
1243
1245 Internals\Counter\Event\EventDictionary::SYNC_CHANGED,
1246 [
1247 'user_ids' => [$userId],
1248 ]
1249 );
1250 }
1251
1252 return true;
1253 }
1254
1259 public static function isConnectionSuccess(string $lastResult = null): bool
1260 {
1261 return (!is_null($lastResult) && preg_match("/^\[(2\d\d|0)\][a-z0-9 _]*/i", $lastResult));
1262 }
1263
1264 public static function deactivateConnection(int $connectionId)
1265 {
1267 $mapperFactory = ServiceLocator::getInstance()->get('calendar.service.mappers.factory');
1268 $connection = $mapperFactory->getConnection()->getMap([
1269 '=ID' => $connectionId,
1270 '=ENTITY_TYPE' => 'user',
1271 '=ENTITY_ID' => \CCalendar::getCurUserId(),
1272 '=IS_DELETED' => 'N'
1273 ])->fetch();
1274
1275 if ($connection)
1276 {
1277 return (new Sync\Managers\ConnectionManager())->deactivateConnection($connection)->isSuccess();
1278 }
1279
1280 return false;
1281 }
1282
1290 private static function prepareRemind($ar, array $arNewFields): array
1291 {
1292 if (count($ar) === 2 && $ar[1] === 'date')
1293 {
1294 $arNewFields["REMIND"][] = [
1295 'type' => $ar[1],
1296 'value' => new DateTime($ar[0], 'Ymd\\THis\\Z'),
1297 ];
1298 }
1299 else if (count($ar) === 2)
1300 {
1301 $arNewFields["REMIND"][] =
1302 [
1303 'type' => $ar[1],
1304 'count' => floatVal($ar[0])
1305 ];
1306 }
1307
1308 return $arNewFields;
1309 }
1310}
$connection
Определения actionsdefinitions.php:38
$type
Определения options.php:106
const BX_ROOT
Определения bx_root.php:3
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static addEvent(string $type, array $data)
Определения counterservice.php:40
const YANDEX_TYPE
Определения helper.php:8
static get($userId=null)
Определения usersettings.php:86
Определения util.php:21
static getAttendees(array $codeAttendees=null, string $stringWrapper='')
Определения util.php:272
static getInstance()
Определения application.php:98
Определения loader.php:13
static includeModule($moduleName)
Определения loader.php:67
static getMessage($code, $replace=null, $language=null)
Определения loc.php:30
static createFromTimestamp($timestamp)
Определения date.php:402
Определения calendar_sync.php:19
static getTimestampWithUserOffset($userId)
Определения calendar_sync.php:839
static getAttendeesCodesForCut($attendeesCodes)
Определения calendar_sync.php:824
static $attendeeList
Определения calendar_sync.php:21
static DoDeleteToDav($params, $event)
Определения calendar_sync.php:530
static UpdateUserConnections()
Определения calendar_sync.php:1214
static ModifyReccurentInstances($params=array())
Определения calendar_sync.php:271
static isTaskListSyncEnabled()
Определения calendar_sync.php:783
const SYNC_TIME
Определения calendar_sync.php:20
static ModifyEvent($calendarId, $arFields, $params=[])
Определения calendar_sync.php:35
static GetSyncInfo($params=[])
Определения calendar_sync.php:849
static GetMultipleSyncInfoItem($userId, $syncType)
Определения calendar_sync.php:975
static isConnectionSuccess(string $lastResult=null)
Определения calendar_sync.php:1259
static $handleExchangeMeeting
Определения calendar_sync.php:22
static SetSectionStatus(?int $userId=0, ?array $sectionsStatus=[])
Определения calendar_sync.php:1185
static isExchangeMeetingEnabled()
Определения calendar_sync.php:774
static SyncCalendarSections($connectionType, $arCalendars, $entityType, $entityId, $connectionId=null)
Определения calendar_sync.php:558
static getSyncLinks()
Определения calendar_sync.php:1170
static $doNotSendToGoogle
Определения calendar_sync.php:23
static GetSyncInfoItem($userId, $syncType)
Определения calendar_sync.php:941
static CutAttendeesFromDescription(?string $description, ?array $attendeesCodes, ?string $languageId)
Определения calendar_sync.php:798
static GetExchangeEmailForUser($idList=[])
Определения calendar_sync.php:717
static DoSaveToDav(&$arFields, $params=[], $event=false)
Определения calendar_sync.php:322
$options
Определения commerceml2.php:49
$arFields
Определения dblapprove.php:5
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
if(Loader::includeModule( 'bitrix24')) elseif(Loader::includeModule('intranet') &&CIntranetUtils::getPortalZone() !=='ru') $description
Определения .description.php:24
$_SERVER["DOCUMENT_ROOT"]
Определения cron_frame.php:9
global $DB
Определения cron_frame.php:29
$status
Определения session.php:10
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
Определения tools.php:3778
GetMessage($name, $aReplace=null)
Определения tools.php:3397
Определения collection.php:2
$manager
Определения office365push.php:39
$service
Определения payment.php:18
$entityId
Определения payment.php:4
$event
Определения prolog_after.php:141
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$ar
Определения options.php:199
if(empty($signedUserToken)) $key
Определения quickway.php:257
</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
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$error
Определения subscription_card_product.php:20
$arFilter
Определения user_search.php:106