1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
vendordataexchangemanager.php
См. документацию.
1<?php
2
3namespace Bitrix\Calendar\Sync\Managers;
4
5use Bitrix\Calendar\Core;
6use Bitrix\Calendar\Core\Base\BaseException;
7use Bitrix\Calendar\Core\Event\Event;
8use Bitrix\Calendar\Core\Handlers\UpdateMasterExdateHandler;
9use Bitrix\Calendar\Core\Managers\Compare\EventCompareManager;
10use Bitrix\Calendar\Integration\Pull\PushCommand;
11use Bitrix\Calendar\Sync\Util\FlagRegistry;
12use Bitrix\Calendar\Sync\Util\HandleStatusTrait;
13use Bitrix\Calendar\Sync;
14use Bitrix\Calendar\Sync\Connection\Connection;
15use Bitrix\Calendar\Sync\Entities\SyncEvent;
16use Bitrix\Calendar\Sync\Exceptions\AuthException;
17use Bitrix\Calendar\Sync\Exceptions\RemoteAccountException;
18use Bitrix\Calendar\Sync\Handlers\MasterPushHandler;
19use Bitrix\Calendar\Sync\Handlers\SyncEventMergeHandler;
20use Bitrix\Calendar\UserField\ResourceBooking;
21use Bitrix\Calendar\Util;
22use Bitrix\Main\ArgumentException;
23use Bitrix\Main\DI\ServiceLocator;
24use Bitrix\Main\Loader;
25use Bitrix\Main\LoaderException;
26use Bitrix\Main\ObjectException;
27use Bitrix\Main\ObjectNotFoundException;
28use Bitrix\Main\ObjectPropertyException;
29use Bitrix\Main\SystemException;
30use Bitrix\Main\Web\Uri;
31use CCalendar;
32use CCalendarSect;
33use Exception;
34
36{
37 use HandleStatusTrait;
38
39 private static array $outgoingManagersCache = [];
40
48 protected bool $isFullSync = false;
49
50 private Sync\Factories\SyncEventFactory $syncEventFactory;
51 private Core\Mappers\EventConnection $eventConnectionMapper;
52 private Core\Mappers\Event $eventMapper;
53 private Core\Mappers\Section $sectionMapper;
54 private Core\Mappers\SectionConnection $sectionConnectionMapper;
58
63 {
64 $this->factory = $factory;
65 $this->syncSectionMap = $syncSectionMap;
66 $this->isFullSync = !$this->factory->getConnection()->getToken();
67
69 $mapperHelper = ServiceLocator::getInstance()->get('calendar.service.mappers.factory');
70 $this->sectionConnectionMapper = $mapperHelper->getSectionConnection();
71 $this->sectionMapper = $mapperHelper->getSection();
72 $this->eventConnectionMapper = $mapperHelper->getEventConnection();
73 $this->eventMapper = $mapperHelper->getEvent();
74 $this->syncEventFactory = new Sync\Factories\SyncEventFactory();
75
76
77 $handlerMergeClass = Core\Handlers\HandlersMap::getHandler('syncEventMergeHandler');
78 $this->handlerMerge = new $handlerMergeClass();
79 }
80
89 public function exchange(): self
90 {
91 $pushManager = new PushManager();
92 $push = $pushManager->getPush(PushManager::TYPE_CONNECTION, $this->factory->getConnection()->getId());
93 // TODO: what could to do, if push is blocked ?
94 $pushManager->setBlockPush($push);
95 try
96 {
97 $this->exchangeSections();
98
99 $this->sendResult(MasterPushHandler::MASTER_STAGE[1]);
100
101 $this->blockSectionPush($this->syncSectionMap);
102 try
103 {
104 $this->exchangeEvents();
105 }
106 catch(BaseException $e)
107 {}
108 finally
109 {
110 $this->unblockSectionPush($this->syncSectionMap);
111 }
112
113 $this->sendResult(MasterPushHandler::MASTER_STAGE[2]);
114 $this->sendResult(MasterPushHandler::MASTER_STAGE[3]);
115
116 $this
117 ->updateConnection($this->factory->getConnection())
118 ->clearCache() // Clear legacy cache after whole sync
119 ;
120 }
121 catch(BaseException $e)
122 {
123 }
124 finally
125 {
126 $pushManager->setUnblockPush($push);
127 }
128
129 return $this;
130 }
131
132 private function sendResult(string $stage): void
133 {
134 $this->sendStatus([
135 'vendorName' => $this->factory->getConnection()->getVendor()->getCode(),
136 'accountName' => $this->factory->getConnection()->getName(),
137 'stage' => $stage,
138 ]);
139 }
140
141 public function clearCache(): void
142 {
143 CCalendar::ClearCache();
144 }
145
157 public function importEvents(): self
158 {
159 $importEventManager = (new ImportEventManager($this->factory, $this->syncSectionMap));
160
161 $syncEventMap = $importEventManager->import()->getEvents();
162
163 $this->prepareLocalSyncEventMapWithVendorEventId($syncEventMap);
164 $this->handleEventsToLocalStorage($syncEventMap);
165 $this->handleSectionsToLocalStorage($this->syncSectionMap);
166
167 return $this;
168 }
169
179 public function importSections(): self
180 {
181 //sections
182 $sectionImporter = (new ImportSectionManager($this->factory))->import();
183
184 $this->handleImportedSections($sectionImporter->getSyncSectionMap());
185
186 return $this;
187 }
188
195 {
196 $connection->setLastSyncTime(new Core\Base\Date());
197 (new Core\Mappers\Connection())->update($connection);
198
199 $accountType = $connection->getAccountType() === Sync\Google\Helper::GOOGLE_ACCOUNT_TYPE_API
200 ? 'google'
201 : $connection->getAccountType()
202 ;
203
205 PushCommand::RefreshSyncStatus,
206 $connection->getOwner()->getId(),
207 [
208 'syncInfo' => [
209 $accountType => [
210 'status' => $this->getSyncStatus($connection->getStatus()),
211 'type' => $accountType,
212 'connected' => true,
213 'id' => $connection->getId(),
214 'syncOffset' => 0,
215 ],
216 ],
217 'requestUid' => Util::getRequestUid(),
218 ]
219 );
220
221 return $this;
222 }
223
224 private function getSyncStatus(?string $status): bool
225 {
226 return $status && preg_match("/^\[(2\d\d|0)\][a-z0-9 _]*/i", $status);
227 }
228
237 public function handleImportedSections(Sync\Entities\SyncSectionMap $externalSyncSectionMap): void
238 {
239 $this->mergeSyncedSyncSectionsWithSavedSections($externalSyncSectionMap);
240 $this->handleSectionsToLocalStorage($externalSyncSectionMap);
241 $this->removeDeletedExternalSections($externalSyncSectionMap);
242 }
243
254 public function handleSyncEvent(
255 Sync\Entities\SyncEvent $syncEvent,
256 ?string $key = null,
257 ?Sync\Entities\SyncEvent $masterSyncEvent = null
258 ): void
259 {
260 if ($syncEvent->getEventConnection() === null)
261 {
262 return;
263 }
264
265 if ($masterSyncEvent !== null)
266 {
267 $syncEvent->getEvent()->setRecurrenceId($masterSyncEvent->getId());
268 }
269
270 $this->mergeExternalEventWithLocalParams($syncEvent);
271
272 if ($syncEvent->getAction() === Sync\Dictionary::SYNC_EVENT_ACTION['delete'])
273 {
274 //if we drag out an old event that has not been saved in our system
275 if ($syncEvent->getEvent()->getId() === null)
276 {
277 if ($syncEvent->isInstance())
278 {
279 if ($masterSyncEvent === null)
280 {
281 $masterSyncEvent = $this->getMasterSyncEvent($syncEvent);
282 }
283 if (!$masterSyncEvent)
284 {
285 return;
286 }
287
288 if ($masterSyncEvent->getAction() === Sync\Dictionary::SYNC_EVENT_ACTION['delete'])
289 {
290 return;
291 }
292
293 if ($masterSyncEvent->getId() === null)
294 {
295 $this->handleSyncEvent($masterSyncEvent);
296
297 return;
298 }
299
300 $this->updateMasterExdate($this->addExdateToMasterEvent($masterSyncEvent, $syncEvent));
301 }
302
303 return;
304 }
305
306 $this->deleteEvent($syncEvent);
307
308 return;
309 }
310
311 $this->saveEvent($syncEvent);
312
313 if (
314 $masterSyncEvent
315 && $masterSyncEvent->getId()
316 && $syncEvent->isInstance()
317 )
318 {
319 $this->updateMasterExdate($this->addExdateToMasterEvent($masterSyncEvent, $syncEvent));
320 }
321 }
322
328 public function filterUnchangedSections(
329 Sync\Entities\SyncSectionMap $externalSyncSectionMap,
330 Sync\Entities\SyncSection $syncSection
331 ): bool
332 {
334 if (
335 ($externalSyncSection = $externalSyncSectionMap->getItem($syncSection->getSectionConnection()
336 ->getVendorSectionId()))
337 && $syncSection->getSectionConnection()->getVersionId() !== $externalSyncSection->getSectionConnection()
338 ->getVersionId()
339 )
340 {
341 $syncSection->getSectionConnection()->setVersionId($externalSyncSection->getSectionConnection()->getVersionId());
342
343 return true;
344 }
345
346 return false;
347 }
348
357 public function handleDeleteInstance(Sync\Entities\SyncEvent $syncEvent): void
358 {
359 $masterSyncEvent = $this->getMasterSyncEvent($syncEvent);
360 if (!$masterSyncEvent)
361 {
362 return;
363 }
364
365 $this->prepareExcludedDatesMasterEvent(
366 $masterSyncEvent,
367 $syncEvent->getEvent()->getOriginalDateFrom()
368 );
369
370 if ($masterSyncEvent->getId() === null)
371 {
372 return;
373 }
374
375 $this->updateMasterExdate($masterSyncEvent->getEvent());
376 $masterSyncEvent->setEvent($masterSyncEvent->getEvent());
377
378 $this->syncEventMap->updateItem($masterSyncEvent, $masterSyncEvent->getVendorEventId());
379 }
380
385 public function getMeetingDescriptionForNewEvent(Core\Role\Role $owner): Core\Event\Properties\MeetingDescription
386 {
387 return (new Core\Event\Properties\MeetingDescription())
388 ->setHostName($owner->getFullName())
389 ->setMeetingCreator($owner->getId())
390 ->setReInvite(false)
391 ->setLanguageId(($owner->getRoleEntity() instanceof Core\Role\User)
392 ? $owner->getRoleEntity()->getLanguageId()
393 : LANGUAGE_ID
394 )
395 ->setIsNotify(true)
396 ->setAllowInvite(true)
397 ;
398 }
399
408 public function deleteEvent(Sync\Entities\SyncEvent $syncEvent): Event
409 {
410 $event = $syncEvent->getEvent();
411
412 // todo handle meeting status
413 if ($event->isInstance())
414 {
415 $this->handleDeleteInstance($syncEvent);
416 }
417
418 if ($event->isRecurrence())
419 {
420 $this->handleDeleteRecurrenceEvent($syncEvent);
421 }
422
423 if ($event->isSingle())
424 {
425 $this->handleDeleteSingleEvent($syncEvent);
426 }
427
428 $this->eventMapper->delete($event, [
429 'softDelete' => true,
430 'originalFrom' => $syncEvent->getEventConnection()->getConnection()->getVendor()->getCode(),
431 ]);
432
433 $this->eventConnectionMapper->delete($syncEvent->getEventConnection());
434
435 return $event;
436 }
437
444 public function saveEvent(Sync\Entities\SyncEvent $syncEvent): void
445 {
446 $event = $syncEvent->getEvent();
447 $event = $event->isNew()
448 ? $this->eventMapper->create($event, [
449 'originalFrom' => $this->factory->getServiceName(),
450 ])
451 : $this->eventMapper->update($event, [
452 'originalFrom' => $this->factory->getServiceName(),
453 ])
454 ;
455
456 if ($event)
457 {
458 $syncEvent->setEvent($event);
459 $eventConnection = $syncEvent->getEventConnection();
460 if ($eventConnection)
461 {
462 $eventConnection
463 ->setEvent($event)
464 ->setVersion($event->getVersion())
465 ;
466
467 $eventConnection->getId()
468 ? $this->eventConnectionMapper->update($eventConnection)
469 : $this->eventConnectionMapper->create($eventConnection)
470 ;
471 }
472 }
473 }
474
485 public function handleImportedEvents(Sync\Entities\SyncEventMap $externalEventMap): void
486 {
487 $this->prepareLocalSyncEventMapWithVendorEventId($externalEventMap);
488 $this->handleEventsToLocalStorage($externalEventMap);
489 }
490
495 public function savePermissions(Sync\Entities\SyncSection $syncSection): void
496 {
497 CCalendarSect::SavePermissions(
498 $syncSection->getSection()->getId(),
499 CCalendarSect::GetDefaultAccess(
500 $syncSection->getSection()->getType(),
501 $syncSection->getSection()->getOwner()->getId()
502 )
503 );
504 }
505
513 private function exchangeSections(): void
514 {
515 //sections
516 $sectionImporter = (new ImportSectionManager($this->factory))->import();
517
518 $sectionExporter = (new OutgoingSectionManager(
519 $this->factory,
520 $this->prepareSyncSectionBeforeExport(
521 $this->getFilteredSectionMapForExport($sectionImporter->getSyncSectionMap())
522 )
523 ))->export();
524
525 $this->handleImportedSections($sectionImporter->getSyncSectionMap());
526 $this->handleExportedSections($sectionExporter->getSyncSectionMap());
527
528 $this->filterBrokenSyncSections();
529 }
530
537 private function handleExportedSections(Sync\Entities\SyncSectionMap $syncSectionMap): void
538 {
539 $this->handleSectionsToLocalStorage($syncSectionMap);
540 }
541
552 private function exchangeEvents(): void
553 {
554 $eventImporter = (new ImportEventManager($this->factory, $this->syncSectionMap))->import();
555 $this->handleImportedEvents($eventImporter->getEvents());
556
557 $savedSyncEventMap = $this->getLocalEventsForExport();
558
559 if ($savedSyncEventMap)
560 {
561 (new ExportEventManager($this->factory, $this->syncSectionMap))->export($savedSyncEventMap);
562 $this->updateExportedEvents($savedSyncEventMap);
563 }
564
565 $this->handleSectionsToLocalStorage($this->syncSectionMap);
566 }
567
574 private function handleExportedInstances(Sync\Entities\SyncEvent $syncEvent): void
575 {
577 foreach ($syncEvent->getInstanceMap() as $instance)
578 {
579 if ($instance->getAction() !== Sync\Dictionary::SYNC_EVENT_ACTION['success'])
580 {
581 $this->handleExportedFailedSyncEvent($syncEvent);
582 continue;
583 }
584
585 if ($instanceEventConnection = $instance->getEventConnection())
586 {
587 $instanceEventConnection
588 ->setEvent($instance->getEvent())
589 ->setConnection($syncEvent->getEventConnection()->getConnection())
590 ;
591
592 if ($instanceEventConnection->getId())
593 {
594 $this->eventConnectionMapper->update($instanceEventConnection);
595 }
596 else
597 {
598 $this->eventConnectionMapper->create($instanceEventConnection);
599 }
600 }
601 }
602 }
603
614 public function validateSyncEventChange(
615 Sync\Entities\SyncEvent $syncEvent,
616 Sync\Entities\SyncEvent $existsSyncEvent = null
617 ): bool
618 {
619 if (!$existsSyncEvent)
620 {
621 return true;
622 }
623
624 if (
625 $syncEvent->getEventConnection() !== null
626 && (
627 ($syncEvent->getEventConnection()->getVendorVersionId() === $existsSyncEvent->getEventConnection()->getVendorVersionId())
628 || ($syncEvent->getEventConnection()->getEntityTag() === $existsSyncEvent->getEventConnection()->getEntityTag())
629 )
630 )
631 {
632 if (
633 (
634 $syncEvent->getEventConnection()->getConnection()->getVendor()->getCode()
635 !== Sync\Google\Helper::GOOGLE_ACCOUNT_TYPE_API
636 )
637 || !$this->hasDifferentEventFields($syncEvent, $existsSyncEvent))
638 {
639 return false;
640 }
641 }
642
643 // Changing an event for an invitee
644 // TODO: move it check to core.
645 if ($existsSyncEvent->getEventId() !== $existsSyncEvent->getParentId())
646 {
647 // temporary this functionality is turned off
648 // if (!$existsSyncEvent->getEvent()->isDeleted() && $this->hasDifferentEventFields($syncEvent, $existsSyncEvent))
649 // {
650 // $this->rollbackEvent(
651 // $existsSyncEvent,
652 // $syncEvent,
653 // 'CALENDAR_IMPORT_BLOCK_FROM_ATTENDEE'
654 // );
655 // }
656
657 return false;
658 }
659
660 // Prevent changing events with booking
661 if ($existsSyncEvent->getEvent()->getSpecialLabel() === ResourceBooking::EVENT_LABEL)
662 {
663 // temporary this functionality is turned off
664 // if ($this->hasDifferentEventFields($syncEvent, $existsSyncEvent))
665 // {
666 //
667 // $this->rollbackEvent(
668 // $existsSyncEvent,
669 // $syncEvent,
670 // 'CALENDAR_IMPORT_BLOCK_RESOURCE_BOOKING'
671 // );
672 // }
673
674 return false;
675 }
676
677 // temporary this functionality is turned off
678
679 // if ($syncEvent->getAction() !== Sync\Dictionary::SYNC_EVENT_ACTION['delete']
680 // && !$this->checkAttendeesAccessibility($existsSyncEvent->getEvent(), $syncEvent->getEvent()))
681 // {
682 // if ($this->hasDifferentEventFields($syncEvent, $existsSyncEvent))
683 // {
684 // $this->rollbackEvent(
685 // $existsSyncEvent,
686 // $syncEvent,
687 // 'CALENDAR_IMPORT_BLOCK_ATTENDEE_ACCESSIBILITY'
688 // );
689 // }
690 //
691 // return false;
692 // }
693
694 if ($syncEvent->isSingle() && $syncEvent->getEntityTag() !== $existsSyncEvent->getEntityTag())
695 {
696 return true;
697 }
698
699 if ($syncEvent->isRecurrence())
700 {
701 if ($syncEvent->getEntityTag() !== $existsSyncEvent->getEntityTag())
702 {
703 return true;
704 }
705
706 if ($syncEvent->hasInstances())
707 {
709 foreach ($syncEvent->getInstanceMap() as $key => $instance)
710 {
711 $existsInstanceMap = $existsSyncEvent->getInstanceMap();
712
713 if (!$existsInstanceMap)
714 {
715 return true;
716 }
717
719 $existsInstance = $existsInstanceMap->getItem($key);
720
721 if (!$existsInstance)
722 {
723 return true;
724 }
725
726 if ($existsInstance->getEntityTag() !== $instance->getEntityTag())
727 {
728 return true;
729 }
730 }
731 }
732 }
733
734 if ($syncEvent->isInstance())
735 {
736 return true;
737 }
738
739 return false;
740 }
741
742 private function hasDifferentEventFields(
743 Sync\Entities\SyncEvent $syncEvent,
744 Sync\Entities\SyncEvent $existSyncEvent
745 ): bool
746 {
747 if (!$syncEvent->getEvent() && !$existSyncEvent->getEvent())
748 {
749 return false;
750 }
751
752 if ($syncEvent->getAction() === Sync\Dictionary::SYNC_EVENT_ACTION['delete']
753 && !$existSyncEvent->getEvent()->isDeleted()
754 )
755 {
756 return true;
757 }
758
759 $comparator = new EventCompareManager($syncEvent->getEvent(), $existSyncEvent->getEvent());
760
761 $diff = $comparator->getDiff();
762 $significantFields = [
766 EventCompareManager::COMPARE_FIELDS['recurringRule'] => true,
767 EventCompareManager::COMPARE_FIELDS['description'] => true,
768 'excludedDates' => true,
769 ];
770 $significantDiff = array_intersect_key($diff, $significantFields);
771
772 return !empty($significantDiff);
773 }
774
781 {
782 $masterEvent = $masterSyncEvent->getEvent();
783 $exdateCollection = $masterEvent->getExcludedDateCollection();
784 if ($exdateCollection === null)
785 {
786 $exdateCollection = new Core\Event\Properties\ExcludedDatesCollection();
787 $masterEvent->setExcludedDateCollection($exdateCollection);
788 }
789
790 if ($instance->getEvent()->getOriginalDateFrom() instanceof Core\Base\Date)
791 {
792 $exdateCollection->add(
793 (clone $instance->getEvent()->getOriginalDateFrom())
794 ->setDateTimeFormat(Core\Event\Properties\ExcludedDatesCollection::EXCLUDED_DATE_FORMAT)
795 );
796 }
797
798 return $masterEvent;
799 }
800
811 private function rollbackEvent(
812 Sync\Entities\SyncEvent $existsExternalSyncEvent,
813 Sync\Entities\SyncEvent $syncEvent,
814 string $messageCode
815 ): void
816 {
817 $muteNotice = $this->isNoticesMuted();
818 if ($existsExternalSyncEvent->getEvent()->isDeleted())
819 {
820 $muteNotice = true;
821 $syncStatus = Sync\Dictionary::SYNC_EVENT_ACTION['delete'];
822 }
823 else
824 {
825 $syncStatus = ($existsExternalSyncEvent->getEvent()->isRecurrence() || $syncEvent->getEvent()->isRecurrence())
828 ;
829 }
830 $existsExternalSyncEvent->getEventConnection()
831 ->setLastSyncStatus($syncStatus)
832 ->setVersion($existsExternalSyncEvent->getEvent()->getVersion() - 1);
833 $this->eventConnectionMapper->update($existsExternalSyncEvent->getEventConnection());
834
835 if (!$muteNotice)
836 {
837 $this->noticeUser($existsExternalSyncEvent, $messageCode);
838 }
839 }
840
844 private function isNoticesMuted(): bool
845 {
846 return FlagRegistry::getInstance()->isFlag(Sync\Dictionary::FIRST_SYNC_FLAG_NAME);
847 }
848
852 private function createPusher(): Sync\Handlers\MasterPushHandler
853 {
854 return new Sync\Handlers\MasterPushHandler(
855 $this->factory->getConnection()->getOwner(),
856 'google',
857 $this->factory->getConnection()->getName()
858 );
859 }
860
865 private function mergeSyncedSyncSectionsWithSavedSections(Sync\Entities\SyncSectionMap $externalSyncSectionMap): void
866 {
868 foreach ($externalSyncSectionMap as $key => $externalSyncSection)
869 {
870 if ($externalSyncSection->getSectionConnection() === null)
871 {
872 $externalSyncSectionMap->remove($key);
873
874 continue;
875 }
876
878 if ($savedSyncSection = $this->syncSectionMap->has(
879 $externalSyncSection->getSectionConnection()->getVendorSectionId()
880 ))
881 {
882 $savedSyncSection = $this->syncSectionMap->getItem(
883 $externalSyncSection->getSectionConnection()->getVendorSectionId()
884 );
885 $externalSyncSection
886 ->getSectionConnection()
887 ->setId($savedSyncSection->getSectionConnection()->getId())
888 ->setSyncToken($savedSyncSection->getSectionConnection()->getSyncToken())
889 ->setPageToken($savedSyncSection->getSectionConnection()->getPageToken())
890 ;
891
892 $savedSection = $savedSyncSection->getSection();
893 $externalSyncSection
894 ->getSection()
895 ->setId($savedSection->getId())
896 ->setXmlId($savedSection->getXmlId())
897 ->setCreator($savedSection->getCreator())
898 ->setExternalType($savedSection->getExternalType())
899 ->setIsActive($savedSection->isActive())
900 ->setType($savedSection->getType())
901 ;
902 if (empty($externalSyncSection->getSection()->getColor()))
903 {
904 $externalSyncSection->getSection()->setColor(
905 $savedSection->getColor()
906 ?: Core\Property\ColorHelper::getOurColorRandom()
907 );
908 }
909 if ($savedSection->isLocal())
910 {
911 $externalSyncSection->getSection()->setName($savedSection->getName());
912 }
913 }
914 }
915 }
916
921 private function handleSectionsToLocalStorage(Sync\Entities\SyncSectionMap $syncSectionMap): void
922 {
924 foreach ($syncSectionMap as $key => $syncSection)
925 {
926 if (!$this->validateSyncSectionBeforeSave($syncSection))
927 {
928 $this->updateFailedSyncSection($syncSection);
929
930 continue;
931 }
932
933 if ($syncSection->getAction() === Sync\Dictionary::SYNC_STATUS['delete'])
934 {
935 if ($syncSection->getSection()->isLocal())
936 {
937 $this->createLocalDeletedSection($syncSection);
938 }
939 else
940 {
941 $this->deleteSyncSectionFromLocalStorage($syncSection);
942 continue;
943 }
944 }
945
946 if ($syncSection->getSection()->isNew())
947 {
949 // TODO: change later to saveManager
950 $this->sectionMapper->create($syncSection->getSection());
951 $this->savePermissions($syncSection);
952
953 $this->sectionConnectionMapper->create(
954 $syncSection->getSectionConnection()->setSection($syncSection->getSection())
955 );
956 }
957 else
958 {
959 $this->sectionMapper->update($syncSection->getSection());
960 $sectionConnection = $syncSection->getSectionConnection();
961 $sectionConnection->setSection($syncSection->getSection());
962
963 $sectionConnection->isNew()
964 ? $this->sectionConnectionMapper->create($sectionConnection)
965 : $this->sectionConnectionMapper->update($sectionConnection)
966 ;
967 }
968
969 $syncSection->setAction(Sync\Dictionary::SYNC_SECTION_ACTION['success']);
970
971 $this->syncSectionMap->add($syncSection, $key);
972 }
973 }
974
979 private function removeDeletedExternalSections(Sync\Entities\SyncSectionMap $externalSectionMap): void
980 {
981 if (!$this->isFullSync)
982 {
983 return;
984 }
985
986 $deleteCandidates = (new Sync\Entities\SyncSectionMap(
987 array_diff_key($this->syncSectionMap->getCollection(), $externalSectionMap->getCollection()),
988 ))->getNonLocalSections();
989
991 foreach ($deleteCandidates as $syncSection)
992 {
993 if (
994 ($syncSection->getSection() === null)
995 || ($syncSection->getSectionConnection() === null)
996 )
997 {
998 continue;
999 }
1000 $this->deleteSyncSectionFromLocalStorage($syncSection);
1001 }
1002 }
1003
1004 private function createLocalDeletedSection(Sync\Entities\SyncSection $syncSection)
1005 {
1006
1007 }
1008
1013 private function deleteSyncSectionFromLocalStorage(Sync\Entities\SyncSection $syncSection): void
1014 {
1015 if ($syncSection->getSectionConnection()->getId() !== null)
1016 {
1017 $this->sectionConnectionMapper->delete($syncSection->getSectionConnection());
1018 $this->syncSectionMap->remove($syncSection->getSectionConnection()->getVendorSectionId());
1019 }
1020
1021 if ($syncSection->getSection()->getId() !== null)
1022 {
1023 $this->sectionMapper->delete($syncSection->getSection(), ['softDelete' => false]);
1024 $this->syncSectionMap->remove($syncSection->getSection()->getId());
1025 }
1026 }
1027
1032 private function getFilteredSectionMapForExport(
1033 Sync\Entities\SyncSectionMap $externalSectionMap
1034 ): Sync\Entities\SyncSectionMap
1035 {
1036 return (new Sync\Entities\SyncSectionMap(
1037 array_diff_key(
1038 $this->isFullSync
1039 ? $this->syncSectionMap->getCollection()
1040 : $this->syncSectionMap
1041 ->getItemsByKeys(array_keys($externalSectionMap->getCollection()))
1042 ->getCollection(),
1043 $externalSectionMap->getCollection()
1044 ),
1045 ))->getLocalSections();
1046 }
1047
1055 {
1056 $syncSectionList = $this->isFullSync
1057 ? $this->syncSectionMap->getCollection()
1058 : $this->syncSectionMap
1059 ->getItemsByKeys(array_keys($syncSectionMap->getCollection()))
1060 ->getCollection();
1061
1063 array_diff_key($syncSectionList, $syncSectionMap->getCollection()),
1064 );
1065 }
1066
1073 private function getLocalEventsForExport(): ?Sync\Entities\SyncEventMap
1074 {
1075 $sectionIdCollection = [];
1077 foreach ($this->syncSectionMap as $syncSection)
1078 {
1079 $sectionIdCollection[] = $syncSection->getSection()->getId();
1080 }
1081
1082 // foreach ($this->importedLocalEventUidList as $eventUid)
1083 // {
1084 // $candidatesForExport->remove($eventUid);
1085 // }
1086
1087 return $this->syncEventFactory->getSyncEventMapBySyncSectionIdCollectionForExport(
1088 $sectionIdCollection,
1089 $this->factory->getConnection()->getOwner()->getId(),
1090 $this->factory->getConnection()->getId()
1092 }
1093
1102 private function handleEventsToLocalStorage(Sync\Entities\SyncEventMap $externalSyncEventMap): void
1103 {
1105 foreach ($externalSyncEventMap as $key => $syncEvent)
1106 {
1108 $existsExternalSyncEvent = $this->syncEventMap->getItem($key);
1109
1110 if (!$this->validateSyncEventChange($syncEvent, $existsExternalSyncEvent))
1111 {
1112 continue;
1113 }
1114
1115 $masterSyncEvent = $this->getMasterSyncEvent($syncEvent);
1116 if (
1117 $masterSyncEvent
1118 && ($syncEvent->isInstance() || $syncEvent->getVendorRecurrenceId())
1119 && $masterSyncEvent->getId() !== $masterSyncEvent->getParentId()
1120 )
1121 {
1122 continue;
1123 }
1124
1125 $this->handleSyncEvent($syncEvent, $syncEvent->getVendorEventId(), $masterSyncEvent);
1126
1127 if (
1128 $existsExternalSyncEvent
1129 && (
1130 $syncEvent->isRecurrence()
1131 || ($syncEvent->getAction() === Sync\Dictionary::SYNC_EVENT_ACTION['delete'])
1132 )
1133 )
1134 {
1135 $this->removeDeprecatedInstances($existsExternalSyncEvent, $syncEvent);
1136 }
1137
1138 if ($syncEvent->hasInstances())
1139 {
1140 $collection = $syncEvent->getInstanceMap()->getCollection();
1141 array_walk($collection, [$this, 'handleSyncEvent'], $syncEvent);
1142 }
1143
1144 $this->syncEventMap->updateItem($syncEvent, $syncEvent->getVendorEventId());
1145 }
1146 }
1147
1156 private function getMasterSyncEvent(Sync\Entities\SyncEvent $syncEvent): ?Sync\Entities\SyncEvent
1157 {
1158 $recurrenceId = [];
1159 $eventConnection = $syncEvent->getEventConnection();
1160
1161 if ($eventConnection === null)
1162 {
1163 throw new BaseException('you should set EventConnection in SyncEvent');
1164 }
1165
1166 if ($masterSyncEvent = $this->syncEventMap->getItem($eventConnection->getRecurrenceId()))
1167 {
1168 return $masterSyncEvent;
1169 }
1170
1171 if ($eventConnection->getRecurrenceId())
1172 {
1173 $recurrenceId[] = $eventConnection->getRecurrenceId();
1174 }
1175
1176 return $this->syncEventFactory->getSyncEventCollectionByVendorIdList(
1177 $recurrenceId,
1178 $this->factory->getConnection()->getId()
1179 )->fetch();
1180 }
1181
1187 private function prepareExcludedDatesMasterEvent(Sync\Entities\SyncEvent $masterSyncEvent, Core\Base\Date $excludedDate): void
1188 {
1189 $masterEvent = $masterSyncEvent->getEvent();
1190
1191 $date = clone $excludedDate;
1192 $date->format(Core\Event\Properties\ExcludedDatesCollection::EXCLUDED_DATE_FORMAT);
1193
1194 if ($masterEvent->getExcludedDateCollection())
1195 {
1196 $masterEvent->getExcludedDateCollection()->add($date);
1197 }
1198 else
1199 {
1200 $masterEvent->setExcludedDateCollection(new Core\Event\Properties\ExcludedDatesCollection([$date]));
1201 }
1202 }
1203
1212 private function prepareNewEvent(Event $event, Sync\Entities\SyncSection $syncSection): void
1213 {
1214 $section = $syncSection->getSection();
1215 $owner = $section->getOwner();
1216 if ($owner === null)
1217 {
1218 throw new BaseException('section has not owner');
1219 }
1220
1221 $event
1222 ->setSection($syncSection->getSection())
1223 ->setOwner($owner)
1224 ->setCreator($owner)
1225 ->setEventHost($owner)
1226 ->setMeetingDescription($this->getMeetingDescriptionForNewEvent($owner))
1227 ->setIsActive(true)
1228 ->setIsDeleted(false)
1229 ->setCalendarType($owner->getType())
1230 ;
1231 }
1232
1244 public function handleMerge(
1245 Sync\Entities\SyncEventMap $localEventCollection,
1246 string $vendorId,
1247 SyncEventMergeHandler $handlerMerge,
1248 Sync\Entities\SyncEvent $syncEvent,
1249 ?Sync\Connection\EventConnection $eventConnection,
1250 Core\Event\Event $event,
1251 Sync\Entities\SyncSection $syncSection
1252 ): Core\Event\Event
1253 {
1254 $mergedSyncEvent = null;
1255 if ($localEventCollection->has($vendorId))
1256 {
1257 $mergedSyncEvent = $handlerMerge(
1258 $localEventCollection->getItem($vendorId),
1259 $syncEvent,
1260 $localEventCollection->getItem($vendorId)->getEvent()->getId()
1261 );
1262 $eventConnection->setId($localEventCollection->getItem($vendorId)->getEventConnection()->getId());
1263 }
1264 elseif (
1265 $syncEvent->getEventConnection()
1266 && $localEventCollection->has($syncEvent->getEventConnection()
1267 ->getRecurrenceId())
1268 )
1269 {
1271 $masterSyncEvent = $localEventCollection->getItem($syncEvent->getEventConnection()->getRecurrenceId());
1272 // merge with master event
1273 $mergedSyncEvent = $handlerMerge(
1274 $masterSyncEvent,
1275 $syncEvent
1276 );
1277 $mergedSyncEvent->getEvent()->setRecurrenceId($masterSyncEvent->getEvent()->getId())
1278 ;
1279 }
1280 if ($mergedSyncEvent !== null)
1281 {
1282 $event = $mergedSyncEvent->getEvent();
1283 }
1284 else
1285 {
1286 $this->prepareNewEvent($event, $syncSection);
1287 }
1288 return $event;
1289 }
1290
1296 private function mergeExternalEventWithLocalParams(Sync\Entities\SyncEvent $syncEvent): void
1297 {
1299 if ($existsSyncEvent = $this->syncEventMap->getItem($syncEvent->getEventConnection()->getVendorEventId()))
1300 {
1301 $this->mergeSyncEvent(
1302 $existsSyncEvent,
1303 $syncEvent,
1304 $existsSyncEvent->getEventId(),
1305 $existsSyncEvent->getEventConnection()->getId()
1306 );
1307
1308 if (
1309 $syncEvent->isRecurrence()
1310 && $syncEvent->hasInstances()
1311 )
1312 {
1313 foreach ($syncEvent->getInstanceMap() as $instanceSyncEvent)
1314 {
1315 if (
1316 $existsSyncEvent->hasInstances()
1317 && $instanceSyncEvent->getEvent()->getOriginalDateFrom()
1318 && $existsInstanceSyncEvent = $existsSyncEvent->getInstanceMap()->getItem(
1319 Sync\Entities\InstanceMap::getKeyByDate(
1320 $instanceSyncEvent->getEvent()->getOriginalDateFrom()
1321 )
1322 )
1323 )
1324 {
1325 $this->mergeSyncEvent(
1326 $existsInstanceSyncEvent,
1327 $instanceSyncEvent,
1328 $existsInstanceSyncEvent->getEventId(),
1329 $existsInstanceSyncEvent->getEventConnection()->getId()
1330 );
1331 }
1332 else
1333 {
1334 $this->prepareNewSyncEvent($syncEvent);
1335 }
1336 }
1337 }
1338
1339 return;
1340 }
1341
1343 if ($existsMasterSyncEvent = $this->syncEventMap->getItem($syncEvent->getEventConnection()->getRecurrenceId()))
1344 {
1345 if (
1346 $existsMasterSyncEvent->hasInstances()
1347 && $syncEvent->getEvent()->getOriginalDateFrom()
1348 && $existsInstanceSyncEvent = $existsMasterSyncEvent->getInstanceMap()->getItem(
1349 Sync\Entities\InstanceMap::getKeyByDate(
1350 $syncEvent->getEvent()->getOriginalDateFrom()
1351 )
1352 )
1353 )
1354 {
1355 $this->mergeSyncEvent(
1356 $existsInstanceSyncEvent,
1357 $syncEvent,
1358 $existsInstanceSyncEvent->getEventId(),
1359 $existsInstanceSyncEvent->getEventConnection()->getId()
1360 );
1361
1362 return;
1363 }
1364
1365 $this->mergeSyncEvent($existsMasterSyncEvent, $syncEvent);
1366
1367 return;
1368 }
1369
1370 if ($syncEvent->getAction() !== Sync\Dictionary::SYNC_EVENT_ACTION['delete'])
1371 {
1372 $this->prepareNewSyncEvent($syncEvent);
1373 }
1374 }
1375
1384 private function mergeSyncEvent(
1385 Sync\Entities\SyncEvent $existsSyncEvent,
1386 Sync\Entities\SyncEvent $externalSyncEvent,
1387 int $id = null,
1388 int $eventConnectionId = null
1389 ): void
1390 {
1391 $handler = new SyncEventMergeHandler();
1392 $handler($existsSyncEvent, $externalSyncEvent, $id, $eventConnectionId);
1393 }
1394
1399 private function prepareLocalSyncEventMapWithVendorEventId(Sync\Entities\SyncEventMap $externalSyncEventMap): void
1400 {
1401 $vendorEventIdList = [];
1403 foreach ($externalSyncEventMap->getCollection() as $item)
1404 {
1405 $vendorEventIdList[] = $item->getVendorEventId();
1406 if ($item->isInstance())
1407 {
1408 $vendorEventIdList[] = $item->getVendorRecurrenceId();
1409 }
1410 $this->importedLocalEventUidList[] = $item->getUid();
1411 }
1412
1413 $this->syncEventMap = $this->syncEventFactory->getSyncEventCollectionByVendorIdList(
1414 array_unique($vendorEventIdList),
1415 $this->factory->getConnection()->getId()
1416 );
1417 }
1418
1423 private function prepareNewSyncEvent(Sync\Entities\SyncEvent $syncEvent): void
1424 {
1425
1426 }
1427
1432 private function updateExportedEvents(Sync\Entities\SyncEventMap $localEventMap): void
1433 {
1435 foreach ($localEventMap as $syncEvent)
1436 {
1437 if ($syncEvent->getAction() !== Sync\Dictionary::SYNC_EVENT_ACTION['success'])
1438 {
1439 $this->handleExportedFailedSyncEvent($syncEvent);
1440 continue;
1441 }
1442
1443 if ($eventConnection = $syncEvent->getEventConnection())
1444 {
1445 if ($eventConnection->getId())
1446 {
1447 $this->eventConnectionMapper->update($eventConnection);
1448 }
1449 else
1450 {
1451 $this->eventConnectionMapper->create($eventConnection);
1452 }
1453
1454 if ($syncEvent->hasInstances())
1455 {
1456 $this->handleExportedInstances($syncEvent);
1457 }
1458 }
1459 }
1460 }
1461
1466 private function updateMasterExdate(Event $masterEvent): void
1467 {
1468 $handler = new UpdateMasterExdateHandler();
1469 $handler($masterEvent);
1470 }
1471
1476 private function validateSyncSectionBeforeSave(Sync\Entities\SyncSection $syncSection): bool
1477 {
1478 return $syncSection->getSection() && $syncSection->getSectionConnection();
1479 }
1480
1485 private function updateFailedSyncSection(Sync\Entities\SyncSection $syncSection): void
1486 {
1487
1488 }
1489
1493 private function filterBrokenSyncSections(): void
1494 {
1499 foreach ($this->syncSectionMap as $key => $item)
1500 {
1501 if ($item->getSectionConnection() === null)
1502 {
1503 $this->syncSectionMap->remove($key);
1504 }
1505 }
1506 }
1507
1511 private function handleDeleteRecurrenceEvent(SyncEvent $syncEvent)
1512 {
1513
1514 }
1515
1519 private function handleDeleteSingleEvent(SyncEvent $syncEvent)
1520 {
1521
1522 }
1523
1531 private function handleExportedFailedSyncEvent(Sync\Entities\SyncEvent $syncEvent): void
1532 {
1533 if (
1534 ($syncEvent->getEventConnection() === null)
1535 || ($syncEvent->getEventConnection()->getId() === null)
1536 )
1537 {
1538 return;
1539 }
1540
1541 $eventConnection = $syncEvent->getEventConnection();
1542
1543 switch ($syncEvent->getAction())
1544 {
1545 case Sync\Dictionary::SYNC_EVENT_ACTION['delete']:
1546 $eventConnection->setLastSyncStatus(Sync\Dictionary::SYNC_STATUS['delete']);
1547 break;
1548 default:
1549 $eventConnection->setLastSyncStatus(Sync\Dictionary::SYNC_STATUS['update']);
1550 break;
1551 }
1552
1553 $this->eventConnectionMapper->update($eventConnection);
1554 }
1555
1566 private function blockSectionPush(Sync\Entities\SyncSectionMap $syncSectionMap): void
1567 {
1568 $pushManager = new PushManager();
1570 foreach ($syncSectionMap as $syncSection)
1571 {
1572 $pushManager->setBlockPush(
1573 $pushManager->getPush(PushManager::TYPE_SECTION, $syncSection->getSection()->getId())
1574 );
1575
1576 if (
1577 ($syncSection->getSectionConnection() !== null)
1578 && ($syncSection->getSectionConnection()->getId() !== null)
1579 )
1580 {
1581 $pushManager->setBlockPush(
1582 $pushManager->getPush(
1584 $syncSection->getSectionConnection()->getId()
1585 )
1586 );
1587 }
1588 }
1589 }
1590
1603 private function unblockSectionPush(Sync\Entities\SyncSectionMap $syncSectionMap): void
1604 {
1605 $pushManager = new PushManager();
1607 foreach ($syncSectionMap as $syncSection)
1608 {
1609 $pushManager->setUnblockPush(
1610 $pushManager->getPush(PushManager::TYPE_SECTION, $syncSection->getSection()->getId())
1611 );
1612
1613 if ($syncSection->getSectionConnection() !== null
1614 && $syncSection->getSectionConnection()->getId() !== null
1615 )
1616 {
1617 $pushManager->setUnblockPush(
1618 $pushManager->getPush(
1620 $syncSection->getSectionConnection()->getId()
1621 )
1622 );
1623 }
1624 }
1625 }
1626
1633 private function removeDeprecatedInstances(
1634 Sync\Entities\SyncEvent $existsExternalSyncEvent,
1635 Sync\Entities\SyncEvent $syncEvent
1636 ): void
1637 {
1638 if ($existsExternalSyncEvent->hasInstances())
1639 {
1641 foreach ($existsExternalSyncEvent->getInstanceMap() as $key => $oldInstance)
1642 {
1643 if (!$syncEvent->hasInstances() || empty($syncEvent->getInstanceMap()->getItem($key)))
1644 {
1645 $this->eventConnectionMapper->delete($oldInstance->getEventConnection(), ['softDelete' => false]);
1646 $this->eventMapper->delete($oldInstance->getEvent(), [
1647 'softDelete' => false,
1648 'originalFrom' => $syncEvent->getEventConnection()?->getConnection()->getVendor()->getCode(),
1649 'recursionMode' => 'this',
1650 ]);
1651 }
1652 }
1653 }
1654 }
1655
1664 private function prepareSyncSectionBeforeExport(Sync\Entities\SyncSectionMap $syncSectionMap): Sync\Entities\SyncSectionMap
1665 {
1666 $syncSectionKeyIdList = [];
1668 foreach ($syncSectionMap as $key => $syncSection)
1669 {
1670 if ($syncSection->getSectionConnection() === null)
1671 {
1672 continue;
1673 }
1674
1675 if (in_array($syncSection->getSection()->getId(), $syncSectionKeyIdList, true))
1676 {
1677 $syncSectionMap->remove($key);
1678 }
1679 else
1680 {
1681 $syncSectionKeyIdList[$syncSection->getSectionConnection()->getVendorSectionId()] = $syncSection->getSection()->getId();
1682 }
1683
1684 $this->sectionConnectionMapper->delete($syncSection->getSectionConnection(), ['softDelete' => false]);
1685 $this->syncSectionMap->remove($key);
1686 $syncSection->setSectionConnection(null);
1687 }
1688
1689 // todo optimize this process after update mappers
1690 if ($syncSectionKeyIdList)
1691 {
1692 $syncEventMap = $this->syncEventFactory->getSyncEventMapBySyncSectionIdCollectionForExport(
1693 $syncSectionKeyIdList,
1694 $this->factory->getConnection()->getOwner()->getId(),
1695 $this->factory->getConnection()->getId()
1696 );
1697 if ($syncEventMap->count())
1698 {
1700 foreach ($syncEventMap as $syncEvent)
1701 {
1702 if ($syncEvent->getEventConnection() === null)
1703 {
1704 continue;
1705 }
1706
1707 $this->eventConnectionMapper->delete($syncEvent->getEventConnection(), ['softDelete' => false]);
1708 }
1709 }
1710 }
1711
1712 return $syncSectionMap;
1713 }
1714
1723 private function noticeUser(Sync\Entities\SyncEvent $syncEvent, string $messageCode = '')
1724 {
1725 if (Loader::includeModule('im') && Loader::includeModule('pull'))
1726 {
1728 $syncEvent->getEvent()->getOwner()->getType(),
1729 $syncEvent->getEvent()->getOwner()->getId(),
1730 true);
1731 $uri = (new Uri($path))
1732 ->deleteParams(["action", "sessid", "bx_event_calendar_request", "EVENT_ID", "EVENT_DATE"])
1733 ->addParams([
1734 'EVENT_ID' => $syncEvent->getEvent()->getId()])
1735 ;
1736
1738 $syncEvent->getEventConnection()->getConnection()->getOwner()->getId(),
1739 $messageCode,
1740 [
1741 '#EVENT_URL#' => $uri->getUri(),
1742 '#EVENT_TITLE#' => $syncEvent->getEvent()->getName(),
1743 'EVENT_ID' => $syncEvent->getEvent()->getId(),
1744 ]
1745 );
1746 }
1747 }
1748
1760 {
1761 $mapperFactory = ServiceLocator::getInstance()->get('calendar.service.mappers.factory');
1762 $links = $mapperFactory->getSectionConnection()->getMap([
1763 '=CONNECTION_ID' => $connection->getId(),
1764 '=ACTIVE' => 'Y'
1765 ]);
1766
1767 $manager = $this->getOutgoingManager($connection);
1768 foreach ($links as $link)
1769 {
1770 $manager->subscribeSection($link);
1771 }
1772
1773 $manager->subscribeConnection();
1774 }
1775
1783 private function getOutgoingManager(Connection $connection)
1784 {
1785 if (empty(static::$outgoingManagersCache[$connection->getId()]))
1786 {
1787 static::$outgoingManagersCache[$connection->getId()] = new OutgoingManager($connection);
1788 }
1789
1790 return static::$outgoingManagersCache[$connection->getId()];
1791 }
1792}
$path
Определения access_edit.php:21
$connection
Определения actionsdefinitions.php:38
getItemsByKeys(array $keys)
Определения map.php:86
static getHandler(string $handlerName)
Определения handlersmap.php:13
const SYNC_SECTION_ACTION
Определения dictionary.php:40
const SYNC_EVENT_ACTION
Определения dictionary.php:47
const SYNC_STATUS
Определения dictionary.php:16
const FIRST_SYNC_FLAG_NAME
Определения dictionary.php:62
const GOOGLE_ACCOUNT_TYPE_API
Определения helper.php:16
static sendBlockChangeNotification(int $userId, $messageCode, $vars)
Определения notificationmanager.php:131
savePermissions(Sync\Entities\SyncSection $syncSection)
Определения vendordataexchangemanager.php:495
getSyncSectionMapBySyncSectionMap(Sync\Entities\SyncSectionMap $syncSectionMap)
Определения vendordataexchangemanager.php:1052
handleSyncEvent(Sync\Entities\SyncEvent $syncEvent, ?string $key=null, ?Sync\Entities\SyncEvent $masterSyncEvent=null)
Определения vendordataexchangemanager.php:254
handleDeleteInstance(Sync\Entities\SyncEvent $syncEvent)
Определения vendordataexchangemanager.php:357
addExdateToMasterEvent(Sync\Entities\SyncEvent $masterSyncEvent, Sync\Entities\SyncEvent $instance)
Определения vendordataexchangemanager.php:780
saveEvent(Sync\Entities\SyncEvent $syncEvent)
Определения vendordataexchangemanager.php:444
handleImportedSections(Sync\Entities\SyncSectionMap $externalSyncSectionMap)
Определения vendordataexchangemanager.php:237
handleImportedEvents(Sync\Entities\SyncEventMap $externalEventMap)
Определения vendordataexchangemanager.php:485
deleteEvent(Sync\Entities\SyncEvent $syncEvent)
Определения vendordataexchangemanager.php:408
static addPullEvent(PushCommand $command, int $userId, array $params=[])
Определения util.php:385
static getRequestUid()
Определения util.php:537
Определения date.php:9
static GetPath($type='', $ownerId='', $hard=false)
Определения calendar.php:5035
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
if(file_exists($_SERVER['DOCUMENT_ROOT'] . "/urlrewrite.php")) $uri
Определения urlrewrite.php:61
$status
Определения session.php:10
$manager
Определения office365push.php:39
$event
Определения prolog_after.php:141
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$instance
Определения ps_b24_final.php:14
if(empty($signedUserToken)) $key
Определения quickway.php:257