41 private array $subManagers = [];
58 $this->factories = $factories;
59 $this->mapperFactory = ServiceLocator::getInstance()->get(
'calendar.service.mappers.factory');
77 $slaveEvents = $this->getSlaveEvents($event);
78 $context->add(
'sync',
'slaveEvents', $slaveEvents);
79 $this->prepareEventExDates($event, $slaveEvents);
81 return $this->execActionEvent(
'createEvent', $event, $context);
98 $slaveEvents = $this->getSlaveEvents($event);
99 $context->add(
'sync',
'slaveEvents', $slaveEvents);
100 $this->prepareEventExDates($event, $slaveEvents);
102 return $this->execActionEvent(
'updateEvent', $event, $context);
117 return $this->execActionEvent(
'deleteEvent', $event, $context);
131 private function execActionEvent(
string $method,
Event $event,
Context $context):
Result
133 $mainResult =
new Result();
140 foreach ($this->factories as $factory)
142 if ($this->checkExclude($factory, $context, $method))
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();
349 !isset($context->diff[
'EXDATE'])
350 && !isset($context->sync[
'excludeDate'])
354 $mainResult->addError(
new Error(
'Not found info about exclude date'));
358 if (!isset($context->sync[
'excludeDate']))
360 $diff = is_array($context->diff[
'EXDATE'])
361 ? $context->diff[
'EXDATE']
362 : explode(
';', $context->diff[
'EXDATE']);
363 if (isset($context->sync[
'excludeDate']))
365 $excludeDate = $context->sync[
'excludeDate'];
369 $excludeDates = array_filter(
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)
410 if ($this->checkExclude($factory, $context, $method))
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());
505 public function upEventVersion(
Event $event,
Connection $connection,
string $version)
508 $link = $this->mapperFactory->getEventConnection()->getMap([
509 '=CONNECTION_ID' => $connection->getId(),
510 '=EVENT_ID' => $event->
getId(),
515 $link->setVersion((
int)$version);
516 EventConnectionTable::update($link->getId(), [
518 'VERSION' => $version,
531 private function getVendorSynchronization(FactoryInterface $factory): VendorSynchronization
533 $key = $factory->getConnection()->getVendor()->getCode();
534 if (empty($this->subManagers[$key]))
536 $this->subManagers[$key] =
new VendorSynchronization($factory);
539 return $this->subManagers[$key];
549 private function checkExclude(
550 FactoryInterface $factory,
555 if (isset($context->sync)
556 && !empty($context->sync[
'originalFrom'])
557 && $context->sync[
'originalFrom'] === $this->getVendorCode($factory)
571 private function getVendorCode(FactoryInterface $factory): string
573 return $factory->getConnection()->getVendor()->getCode();
587 private function prepareEventContext(Event $event, Context $context, FactoryInterface $factory): EventContext
589 $sectionLink = $context->sync[
'sectionLink'] ?? $this->getSectionConnection($event->getSection(), $factory);
590 $eventLink = $context->sync[
'eventLink'] ?? $this->getEventConnection($event, $factory);
592 return (
new EventContext())
594 ->setSectionConnection($sectionLink)
595 ->setEventConnection($eventLink)
610 private function prepareSectionContext(Section $section, Context $context, FactoryInterface $factory)
612 $sectionLink = $context->sync[
'sectionLink'] ?? $this->getSectionConnection($section, $factory);
614 return (
new SectionContext())
616 ->setSectionConnection($sectionLink)
630 private function getSectionConnection(Section $section, FactoryInterface $factory): ?SectionConnection
632 return $this->mapperFactory->getSectionConnection()->getMap([
633 '=SECTION_ID' => $section->getId(),
634 '=CONNECTION_ID' => $factory->getConnection()->getId(),
647 private function getEventConnection(Event $event, ?FactoryInterface $factory): ?EventConnection
653 $link = $this->mapperFactory->getEventConnection()->getMap([
654 '=EVENT_ID' => $event->getId(),
655 '=CONNECTION_ID' => $factory->getConnection()->getId(),
669 private function getSlaveEvents(Event $event): Core\Base\Map
671 $map = $this->getEventExceptionsMap($event);
673 return new Core\Event\EventMap(
674 array_reduce($map->getCollection(),
static function ($result, $value)
677 if ($value->getOriginalDateFrom())
679 $key = $value->getOriginalDateFrom()->format(
'Ymd');
680 $result[$key] = $value->getId();
694 private function prepareEventExDates(Event $event, Core\Base\Map $slaveEvents)
696 (
new ExcludeDatesHandler())->prepareEventExcludeDates($event, $slaveEvents);
708 private function getEventExceptionsMap(Event $event): Core\Base\Map
710 $mapClass = Core\Event\EventMap::class;
711 $result =
new $mapClass;
713 $queryResult = EventTable::query()
715 ->where(
'RECURRENCE_ID', $event->getParentId())
716 ->where(
'DELETED',
'N')
717 ->where(
'OWNER_ID', $event->getOwner()->getId())
718 ->where(Query::filter()
720 ->whereNot(
'MEETING_STATUS',
'N')
721 ->whereNull(
'MEETING_STATUS')
723 ->whereNotNull(
'ORIGINAL_DATE_FROM')
727 while ($row = $queryResult->fetchObject())
729 $eventEntity = $this->mapperFactory->getEvent()->getByEntityObject($row);
732 $result->add($eventEntity, $eventEntity->getId());
750 private function prepareRecurrenceEvent(
752 Core\Base\Map $eventExceptionsMap,
753 ?FactoryInterface $factory =
null
756 $masterLink = $this->getEventConnection($event, $factory);
757 $syncEvent = (
new SyncEvent())
760 ->setEventConnection($masterLink)
761 ->setInstanceMap(
new InstanceMap());
763 foreach ($eventExceptionsMap as $exceptionEvent)
765 $instance = (
new SyncEvent())
766 ->setEvent($exceptionEvent)
768 ->setEventConnection($this->getEventConnection($exceptionEvent, $factory));
769 $syncEvent->getInstanceMap()->add($instance);
771 (
new ExcludeDatesHandler())->prepareEventExcludeDates($event, $syncEvent->getInstanceMap());
783 private function cloneEventMap(Core\Event\EventMap $eventExceptionsMap): Core\Event\EventMap
785 $result =
new Core\Event\EventMap();
786 foreach ($eventExceptionsMap as $key => $event)
788 $result->add((
new Core\Builders\EventCloner($event))->build(), $key);