41 private array $subManagers = [];
58 $this->factories = $factories;
59 $this->mapperFactory = ServiceLocator::getInstance()->get(
'calendar.service.mappers.factory');
75 if (
$event->getExcludedDateCollection() &&
$event->getExcludedDateCollection()->count())
77 $slaveEvents = $this->getSlaveEvents(
$event);
78 $context->add(
'sync',
'slaveEvents', $slaveEvents);
79 $this->prepareEventExDates(
$event, $slaveEvents);
96 if (
$event->getExcludedDateCollection()->count())
98 $slaveEvents = $this->getSlaveEvents(
$event);
99 $context->add(
'sync',
'slaveEvents', $slaveEvents);
100 $this->prepareEventExDates(
$event, $slaveEvents);
133 $mainResult =
new Result();
140 foreach ($this->factories as $factory)
150 $clonedEvent = $eventCloner->build();
151 $vendorSync = $this->getVendorSynchronization($factory);
152 $eventContext = $this->prepareEventContext($clonedEvent, clone
$context, $factory);
154 if ($eventContext->getSectionConnection()?->getId())
157 $pushManager->setBlockPush($push);
160 $vendorResult = $vendorSync->$method($clonedEvent, $eventContext);
162 $data[$this->getVendorCode($factory)] = $vendorResult;
163 if (!$vendorResult->isSuccess())
165 $mainResult->addErrors($vendorResult->getErrors());
168 catch (RemoteAccountException $e)
170 $mainResult->addError(
new Error($e->getMessage(), $e->getCode()));
174 $pushManager->setUnblockPush($push);
178 return $mainResult->setData(
$data);
194 public function reCreateRecurrence(Event $masterEvent, Context
$context): Result
196 $mainResult =
new Result();
197 $eventExceptionsMap = $this->getEventExceptionsMap($masterEvent);
199 $masterEvent->setVersion($masterEvent->getVersion() + 1);
200 $eventCloner =
new Core\Builders\EventCloner($masterEvent);
203 foreach ($this->factories as $factory)
205 if ($this->checkExclude($factory,
$context))
211 $safeEvent = $eventCloner->build();
212 $safeExceptionsMap = $this->cloneEventMap($eventExceptionsMap);
213 $vendorSyncManager = $this->getVendorSynchronization($factory);
214 $eventContext = $this->prepareEventContext($safeEvent, clone
$context, $factory);
216 if ($factory->getServiceName() === Sync\Icloud\Factory::SERVICE_NAME)
218 $syncEvent = $this->prepareRecurrenceEvent($safeEvent, $safeExceptionsMap, $factory);
219 $vendorResult = $vendorSyncManager->updateRecurrence($syncEvent, $eventContext);
223 $syncEvent = $this->prepareRecurrenceEvent($safeEvent, $safeExceptionsMap);
224 $deleteResult = $vendorSyncManager->deleteEvent($safeEvent, clone $eventContext);
225 if ($deleteResult->isSuccess() && $syncEvent->getEventConnection())
227 $this->mapperFactory->getEventConnection()->delete($syncEvent->getEventConnection());
229 $syncEvent->setEventConnection(
null);
230 $vendorResult = $vendorSyncManager->createRecurrence($syncEvent, $eventContext);
233 $data[$this->getVendorCode($factory)] = $vendorResult;
234 if (!$vendorResult->isSuccess())
236 $mainResult->addErrors($vendorResult->getErrors());
239 catch (RemoteAccountException $e)
241 $mainResult->addError(
new Error($e->getMessage(), $e->getCode()));
245 return $mainResult->setData(
$data);
261 public function createRecurrence(Event
$event, Context
$context): Result
268 $eventExceptionsMap = $this->getEventExceptionsMap(
$event);
269 $mainResult =
new Result();
271 $eventCloner =
new Core\Builders\EventCloner(
$event);
273 foreach ($this->factories as $factory)
275 if ($this->checkExclude($factory,
$context))
281 $safeEvent = $eventCloner->build();
282 $vendorSyncManager = $this->getVendorSynchronization($factory);
283 $eventContext = $this->prepareEventContext($safeEvent,
$context, $factory);
284 $syncEvent = $this->prepareRecurrenceEvent($safeEvent, $eventExceptionsMap);
286 $vendorResult = $vendorSyncManager->createRecurrence($syncEvent, $eventContext);
288 $data[$this->getVendorCode($factory)] = $vendorResult;
289 if (!$vendorResult->isSuccess())
291 $mainResult->addErrors($vendorResult->getErrors());
294 catch (RemoteAccountException $e)
296 $mainResult->addError(
new Error($e->getMessage(), $e->getCode()));
301 return $mainResult->setData(
$data);
316 return $this->execActionEvent(
'createInstance',
$event,
$context);
331 return $this->execActionEvent(
'updateInstance',
$event,
$context);
346 $mainResult =
new Result();
350 && !isset(
$context->sync[
'excludeDate'])
351 && !
$event->getExcludedDateCollection()->count()
354 $mainResult->addError(
new Error(
'Not found info about exclude date'));
358 if (!isset(
$context->sync[
'excludeDate']))
360 $diff = is_array(
$context->diff[
'EXDATE'])
362 : explode(
';',
$context->diff[
'EXDATE']);
363 if (isset(
$context->sync[
'excludeDate']))
365 $excludeDate =
$context->sync[
'excludeDate'];
369 $excludeDates = array_filter(
370 $event->getExcludedDateCollection()->getCollection(),
371 function($item) use ($diff)
373 return !in_array($item->format(CCalendar::DFormat(
false)), $diff);
375 $excludeDate = $excludeDates ? reset($excludeDates) : [];
378 $context->add(
'sync',
'excludeDate', $excludeDate);
381 return $this->execActionEvent(
'deleteInstance',
$event,
$context);
396 private function execActionSection(
402 $mainResult =
new Result();
408 foreach ($this->factories as $factory)
415 if ($factory->getConnection()->getId())
418 $pushManager->setBlockPush($push);
423 $vendorSync = $this->getVendorSynchronization($factory);
424 $sectionContext = $this->prepareSectionContext($section,
$context, $factory);
425 $vendorResult = $vendorSync->$method($section, $sectionContext);
426 $resultData[$this->getVendorCode($factory)] = $vendorResult;
427 if (!$vendorResult->isSuccess())
429 $mainResult->addErrors($vendorResult->getErrors());
432 catch (RemoteAccountException $e)
434 $mainResult->addError(
new Error($e->getMessage(), $e->getCode()));
438 $pushManager->setUnblockPush($push);
442 return $mainResult->setData($resultData);
457 return $this->execActionSection(
'createSection', $section,
$context);
472 return $this->execActionSection(
'updateSection', $section,
$context);
487 $result = $this->execActionSection(
'deleteSection', $section,
$context);
488 CCalendarSect::cleanLinkTables($section->getId());
508 $link = $this->mapperFactory->getEventConnection()->getMap([
510 '=EVENT_ID' =>
$event->getId(),
515 $link->setVersion((
int)$version);
516 EventConnectionTable::update($link->getId(), [
518 'VERSION' => $version,
524 public function deleteInstanceEventConnection(
Event $event)
526 $links = $this->mapperFactory->getEventConnection()->getMap([
527 '=EVENT_ID' =>
$event->getId(),
531 foreach ($links as $link)
533 EventConnectionTable::delete($link->getId());
544 private function getVendorSynchronization(FactoryInterface $factory): VendorSynchronization
546 $key = $factory->getConnection()->getVendor()->getCode();
547 if (empty($this->subManagers[
$key]))
549 $this->subManagers[
$key] =
new VendorSynchronization($factory);
552 return $this->subManagers[
$key];
562 private function checkExclude(
563 FactoryInterface $factory,
569 && !empty(
$context->sync[
'originalFrom'])
570 &&
$context->sync[
'originalFrom'] === $this->getVendorCode($factory)
584 private function getVendorCode(FactoryInterface $factory): string
586 return $factory->getConnection()->getVendor()->getCode();
600 private function prepareEventContext(Event
$event, Context
$context, FactoryInterface $factory): EventContext
602 $sectionLink =
$context->sync[
'sectionLink'] ?? $this->getSectionConnection(
$event->getSection(), $factory);
603 $eventLink =
$context->sync[
'eventLink'] ?? $this->getEventConnection(
$event, $factory);
605 return (
new EventContext())
607 ->setSectionConnection($sectionLink)
608 ->setEventConnection($eventLink)
623 private function prepareSectionContext(Section $section, Context
$context, FactoryInterface $factory)
625 $sectionLink =
$context->sync[
'sectionLink'] ?? $this->getSectionConnection($section, $factory);
627 return (
new SectionContext())
629 ->setSectionConnection($sectionLink)
643 private function getSectionConnection(Section $section, FactoryInterface $factory): ?SectionConnection
645 return $this->mapperFactory->getSectionConnection()->getMap([
646 '=SECTION_ID' => $section->getId(),
647 '=CONNECTION_ID' => $factory->getConnection()->getId(),
660 private function getEventConnection(Event
$event, ?FactoryInterface $factory): ?EventConnection
666 $link = $this->mapperFactory->getEventConnection()->getMap([
667 '=EVENT_ID' =>
$event->getId(),
668 '=CONNECTION_ID' => $factory->getConnection()->getId(),
682 private function getSlaveEvents(Event
$event): Core\Base\Map
686 return new Core\Event\EventMap(
687 array_reduce(
$map->getCollection(),
static function (
$result, $value)
690 if (
$value->getOriginalDateFrom())
692 $key =
$value->getOriginalDateFrom()->format(
'Ymd');
707 private function prepareEventExDates(Event
$event, Core\Base\Map $slaveEvents)
709 (
new ExcludeDatesHandler())->prepareEventExcludeDates(
$event, $slaveEvents);
721 private function getEventExceptionsMap(Event
$event): Core\Base\Map
723 $mapClass = Core\Event\EventMap::class;
726 $queryResult = EventTable::query()
728 ->where(
'RECURRENCE_ID',
$event->getParentId())
729 ->where(
'DELETED',
'N')
730 ->where(
'OWNER_ID',
$event->getOwner()->getId())
731 ->where(Query::filter()
733 ->whereNot(
'MEETING_STATUS',
'N')
734 ->whereNull(
'MEETING_STATUS')
736 ->whereNotNull(
'ORIGINAL_DATE_FROM')
740 while ($row = $queryResult->fetchObject())
742 $eventEntity = $this->mapperFactory->getEvent()->getByEntityObject($row);
745 $result->add($eventEntity, $eventEntity->getId());
763 private function prepareRecurrenceEvent(
765 Core\Base\Map $eventExceptionsMap,
766 ?FactoryInterface $factory =
null
769 $masterLink = $this->getEventConnection(
$event, $factory);
770 $syncEvent = (
new SyncEvent())
773 ->setEventConnection($masterLink)
774 ->setInstanceMap(
new InstanceMap());
776 foreach ($eventExceptionsMap as $exceptionEvent)
779 ->setEvent($exceptionEvent)
781 ->setEventConnection($this->getEventConnection($exceptionEvent, $factory));
782 $syncEvent->getInstanceMap()->add(
$instance);
784 (
new ExcludeDatesHandler())->prepareEventExcludeDates(
$event, $syncEvent->getInstanceMap());
796 private function cloneEventMap(Core\Event\EventMap $eventExceptionsMap): Core\Event\EventMap
798 $result =
new Core\Event\EventMap();
799 foreach ($eventExceptionsMap as
$key =>
$event)