Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
sharingeventmanager.php
1<?php
2
4
13use Bitrix\Crm;
22use CUser;
23
25{
26 public const SHARED_EVENT_TYPE = Dictionary::EVENT_TYPE['shared'];
27 public const SHARED_EVENT_CRM_TYPE = Dictionary::EVENT_TYPE['shared_crm'];
29 private Event $event;
31 private ?int $hostId;
33 private ?int $ownerId;
35 private ?Sharing\Link\Link $link;
36
43 public function __construct(Event $event, ?int $hostId = null, ?int $ownerId = null, ?Sharing\Link\Link $link = null)
44 {
45 $this->event = $event;
46 $this->hostId = $hostId;
47 $this->ownerId = $ownerId;
48 $this->link = $link;
49 }
50
55 public function setEvent(Event $event): self
56 {
57 $this->event = $event;
58
59 return $this;
60 }
61
68 public function createEvent(bool $sendInvitations = true, string $externalUserName = ''): Result
69 {
70 $result = new Result();
71
72 if (!$this->doesEventHasCorrectTime())
73 {
74 $result->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_USER_BUSY')));
75
76 return $result;
77 }
78
79 if (!$this->doesEventSatisfyRule())
80 {
81 $result->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_USER_BUSY')));
82
83 return $result;
84 }
85
86 $members = $this->link->getMembers();
87 $users = array_merge([$this->link->getOwnerId()], array_map(static function ($member){
88 return $member->getId();
89 }, $members));
90
91 if (!$this->checkUserAccessibility($users))
92 {
93 $result->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_USER_BUSY')));
94
95 return $result;
96 }
97
98 $eventId = (new Mappers\Event())->create($this->event, [
99 'sendInvitations' => $sendInvitations
100 ])->getId();
101
102 $this->event->setId($eventId);
103
104 if (!$eventId)
105 {
106 $result->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_EVENT_SAVE_ERROR')));
107
108 return $result;
109 }
110
111 $eventLinkParams = [
112 'eventId' => $eventId,
113 'ownerId' => $this->ownerId,
114 'hostId' => $this->hostId,
115 'parentLinkHash' => $this->link->getHash(),
117 DateTime::createFromTimestamp($this->event->getEnd()->getTimestamp()),
118 Sharing\Link\Helper::EVENT_SHARING_TYPE
119 ),
120 'externalUserName' => $externalUserName,
121 ];
122
123 $eventLink = (new Sharing\Link\Factory())->createEventLink($eventLinkParams);
124
125 $result->setData([
126 'eventLink' => $eventLink,
127 'event' => $this->event,
128 ]);
129
130 return $result;
131 }
132
137 public function deleteEvent(): Result
138 {
139 $result = new Result();
140
141 (new Mappers\Event())->delete($this->event);
142 $this->notifyEventDeleted();
143
144 return $result;
145 }
146
151 public function deactivateEventLink(Sharing\Link\EventLink $eventLink): self
152 {
153 $eventLink
154 ->setCanceledTimestamp(time())
155 ->setActive(false)
156 ;
157
158 (new Sharing\Link\EventLinkMapper())->update($eventLink);
159
160 return $this;
161 }
162
167 public static function validateContactData(string $userContact): bool
168 {
169 return self::isEmailCorrect($userContact)
170 || self::isPhoneNumberCorrect($userContact)
171 ;
172 }
173
178 public static function validateContactName(string $userName): bool
179 {
180 return self::isUserNameCorrect($userName);
181 }
182
183 private static function isUserNameCorrect(string $userName): bool
184 {
185 return $userName !== '';
186 }
187
188 public static function isEmailCorrect(string $userContact): bool
189 {
190 return check_email($userContact);
191 }
192
193 public static function isPhoneNumberCorrect(string $userContact): bool
194 {
196 && PhoneNumber\Parser::getInstance()->parse($userContact)->isValid()
197 ;
198 }
199
205 public static function prepareEventForSave($data, $userId, Sharing\Link\Joint\JointLink $link): Event
206 {
207 $ownerId = (int)($data['ownerId'] ?? null);
208 $sectionId = self::getSectionId($userId);
209
210 $attendeesCodes = ['U' . $userId, 'U' . $ownerId];
211 $members = $link->getMembers();
212 foreach ($members as $member)
213 {
214 $attendeesCodes[] = 'U' . $member->getId();
215 }
216
217 $meeting = [
218 'HOST_NAME' => \CCalendar::GetUserName($userId),
219 'NOTIFY' => true,
220 'REINVITE' => false,
221 'ALLOW_INVITE' => true,
222 'MEETING_CREATOR' => $userId,
223 'HIDE_GUESTS' => false,
224 ];
225
226 $eventData = [
227 'OWNER_ID' => $userId,
228 'NAME' => (string)($data['eventName'] ?? ''),
229 'DATE_FROM' => (string)($data['dateFrom'] ?? ''),
230 'DATE_TO' => (string)($data['dateTo'] ?? ''),
231 'TZ_FROM' => (string)($data['timezone'] ?? ''),
232 'TZ_TO' => (string)($data['timezone'] ?? ''),
233 'SKIP_TIME' => 'N',
234 'SECTIONS' => [$sectionId],
235 'EVENT_TYPE' => $data['eventType'],
236 'ACCESSIBILITY' => 'busy',
237 'IMPORTANCE' => 'normal',
238 'ATTENDEES_CODES' => $attendeesCodes,
239 'MEETING_HOST' => $userId,
240 'IS_MEETING' => true,
241 'MEETING' => $meeting,
242 'DESCRIPTION' => (string)($data['description'] ?? ''),
243 ];
244
245 return (new EventBuilderFromArray($eventData))->build();
246 }
247
248 public static function getEventDataFromRequest($request): array
249 {
250 return [
251 'ownerId' => (int)($request['ownerId'] ?? 0),
252 'dateFrom' => (string)($request['dateFrom'] ?? ''),
253 'dateTo' => (string)($request['dateTo'] ?? ''),
254 'timezone' => (string)($request['timezone'] ?? ''),
255 'description' => (string)($request['description'] ?? ''),
256 'eventType' => Dictionary::EVENT_TYPE['shared'],
257 ];
258 }
259
260 public static function getSharingEventNameByUserId(int $userId): string
261 {
262 $user = CUser::GetByID($userId)->Fetch();
263 $userName = ($user['NAME'] ?? '') . ' ' . ($user['LAST_NAME'] ?? '');
264
265 return self::getSharingEventNameByUserName($userName);
266 }
267
268 public static function getSharingEventNameByUserName(?string $userName): string
269 {
270 if (!empty($userName))
271 {
272 $result = Loc::getMessage('CALENDAR_SHARING_EVENT_MANAGER_EVENT_NAME', [
273 '#GUEST_NAME#' => trim($userName),
274 ]);
275 }
276 else
277 {
278 $result = Loc::getMessage('CALENDAR_SHARING_EVENT_MANAGER_EVENT_NAME_WITHOUT_GUEST');
279 }
280
281 return $result;
282 }
283
288 public static function getCrmEventDataFromRequest($request): array
289 {
290 return [
291 'ownerId' =>(int)($request['ownerId'] ?? 0),
292 'dateFrom' => (string)($request['dateFrom'] ?? ''),
293 'dateTo' => (string)($request['dateTo'] ?? ''),
294 'timezone' => (string)($request['timezone'] ?? ''),
295 'description' => (string)($request['description'] ?? ''),
296 'eventType' => Dictionary::EVENT_TYPE['shared_crm'],
297 ];
298 }
299
303 public static function getSharingEventTypes(): array
304 {
305 return [
308 ];
309 }
310
318 public static function onSharingEventEdit(array $fields): void
319 {
320 $eventId = $fields['ID'];
321 $eventLink = (new Sharing\Link\Factory())->getEventLinkByEventId($eventId);
322 if ($eventLink instanceof Sharing\Link\EventLink)
323 {
324 self::updateEventSharingLink($eventLink, $fields);
325 }
326 }
327
335 public static function setCanceledTimeOnSharedLink(int $eventId): void
336 {
337 $eventLink = (new Sharing\Link\Factory())->getEventLinkByEventId($eventId);
338 if ($eventLink instanceof Sharing\Link\EventLink)
339 {
340 $eventLink->setCanceledTimestamp(time());
341 (new Sharing\Link\EventLinkMapper())->update($eventLink);
342 }
343 }
344
355 public static function onSharingEventMeetingStatusChange(
356 int $userId,
357 string $currentMeetingStatus,
358 array $userEventBeforeChange,
359 bool $isAutoAccept = false
360 )
361 {
363 $eventLink = (new Sharing\Link\Factory())->getEventLinkByEventId((int)$userEventBeforeChange['PARENT_ID']);
364
365 if (!$eventLink)
366 {
367 return;
368 }
369
370 $ownerId = $eventLink->getOwnerId();
371 //if not the link owner's event has changed, send notification to link owner
372 if ($ownerId !== $userId && !$isAutoAccept)
373 {
374 self::onSharingEventGuestStatusChange($currentMeetingStatus, $userEventBeforeChange, $eventLink, $userId);
375 }
376 else if ($userEventBeforeChange['EVENT_TYPE'] === Dictionary::EVENT_TYPE['shared'])
377 {
378 self::onSharingCommonEventMeetingStatusChange($eventLink);
379 }
380 else if ($userEventBeforeChange['EVENT_TYPE'] === Dictionary::EVENT_TYPE['shared_crm'])
381 {
382 self::onSharingCrmEventStatusChange($currentMeetingStatus, $userEventBeforeChange, $userId, $ownerId);
383 }
384 }
385
386 private static function onSharingEventGuestStatusChange(
387 string $currentMeetingStatus,
388 array $event,
389 Sharing\Link\EventLink $eventLink,
390 int $userId
391 ): void
392 {
393 \CCalendarNotify::Send([
394 'mode' => $currentMeetingStatus === "Y" ? 'accept' : 'decline',
395 'name' => $event['NAME'],
396 'from' => $event["DATE_FROM"],
397 'to' => $event["DATE_TO"],
398 'location' => \CCalendar::GetTextLocation($userEvent["LOCATION"] ?? null),
399 'guestId' => $userId,
400 'eventId' => $event['PARENT_ID'],
401 'userId' => $eventLink->getOwnerId(),
402 'fields' => $event
403 ]);
404 }
405
406 private static function onSharingCommonEventMeetingStatusChange(Sharing\Link\EventLink $eventLink): void
407 {
409 $event = (new Mappers\Event())->getById($eventLink->getEventId());
410
411 $host = CUser::GetByID($eventLink->getHostId())->Fetch();
412 $email = $host['PERSONAL_MAILBOX'] ?? null;
413 $phone = $host['PERSONAL_PHONE'] ?? null;
414 $userContact = !empty($email) ? $email : $phone;
415
416 $notificationService = null;
417 if ($userContact && self::isEmailCorrect($userContact))
418 {
419 $notificationService = (new Sharing\Notification\Mail())
420 ->setEventLink($eventLink)
421 ->setEvent($event)
422 ;
423 }
424
425 $notificationService?->notifyAboutMeetingStatus($userContact);
426 }
427
428 private static function onSharingCrmEventStatusChange(
429 string $currentMeetingStatus,
430 array $userEventBeforeChange,
431 int $userId,
432 int $ownerId
433 ): void
434 {
435 if (!Loader::includeModule('crm'))
436 {
437 return;
438 }
439
440 $previousMeetingStatus = $userEventBeforeChange['MEETING_STATUS'] ?? null;
441
442 if (
443 $currentMeetingStatus === Dictionary::MEETING_STATUS['Yes']
444 && $previousMeetingStatus === Dictionary::MEETING_STATUS['Question']
445 && $userId === $ownerId
446 )
447 {
448 self::onSharingCrmEventConfirmed(
449 (int)$userEventBeforeChange['PARENT_ID'],
450 $userEventBeforeChange['DATE_FROM'] ?? null,
451 $userEventBeforeChange['TZ_FROM'] ?? null,
452 );
453 }
454
455 if (
456 $currentMeetingStatus === Dictionary::MEETING_STATUS['No']
457 && (
458 $previousMeetingStatus === Dictionary::MEETING_STATUS['Question']
459 || $previousMeetingStatus === Dictionary::MEETING_STATUS['Yes']
460 )
461 )
462 {
463 self::onSharingCrmEventDeclined((int)$userEventBeforeChange['PARENT_ID']);
464 }
465 }
466
474 private static function onSharingCrmEventConfirmed(int $eventId, ?string $dateFrom, ?string $timezone): void
475 {
476 $crmDealLink = self::getCrmDealLink($eventId);
477
478 $activity = \CCrmActivity::GetByCalendarEventId($eventId, false);
479
480 if ($crmDealLink && $activity)
481 {
482 (new Sharing\Crm\NotifyManager($crmDealLink, Sharing\Crm\NotifyManager::NOTIFY_TYPE_EVENT_CONFIRMED))
483 ->sendSharedCrmActionsEvent(
484 Util::getDateTimestamp($dateFrom, $timezone),
485 $activity['ID'],
486 \CCrmOwnerType::Activity,
487 )
488 ;
489 }
490 }
491
492 private static function onSharingCrmEventDeclined(int $eventId): void
493 {
494 $sharingFactory = new Sharing\Link\Factory();
495
497 $eventLink = $sharingFactory->getEventLinkByEventId($eventId);
498
500 $crmDealLink = $sharingFactory->getLinkByHash($eventLink->getParentLinkHash());
501
503 $event = (new Mappers\Event())->getById($eventId);
504
505 $completeActivityStatus = Sharing\Crm\ActivityManager::STATUS_CANCELED_BY_MANAGER;
506
507 $userId = \CCalendar::GetUserId();
508 if ($userId === 0 || $userId === $event->getEventHost()->getId())
509 {
510 $completeActivityStatus = Sharing\Crm\ActivityManager::STATUS_CANCELED_BY_CLIENT;
511 }
512
513 (new Sharing\Crm\ActivityManager($eventId))
514 ->completeSharedCrmActivity($completeActivityStatus)
515 ;
517 if ($crmDealLink->getContactId() > 0)
518 {
519 Crm\Integration\Calendar\Notification\Manager::getSenderInstance($crmDealLink)
520 ->setCrmDealLink($crmDealLink)
521 ->setEventLink($eventLink)
522 ->setEvent($event)
523 ->sendCrmSharingCancelled()
524 ;
525 }
526 else
527 {
528 $email = CUser::GetByID($eventLink->getHostId())->Fetch()['PERSONAL_MAILBOX'] ?? null;
529 if (!is_string($email))
530 {
531 return;
532 }
533
534 $eventLink->setCanceledTimestamp(time());
535 (new Sharing\Notification\Mail())
536 ->setEventLink($eventLink)
537 ->setEvent($event)
538 ->notifyAboutMeetingCancelled($email)
539 ;
540 }
541
543 }
544
545 public static function onSharingEventEdited(int $eventId, array $previousFields): void
546 {
548 $event = (new Mappers\Event())->getById($eventId);
549 if ($event instanceof Event)
550 {
551 $oldEvent = Event::fromBuilder(new EventBuilderFromArray($previousFields));
552 if ($event->getSpecialLabel() === Dictionary::EVENT_TYPE['shared'])
553 {
554 self::onSharingCommonEventEdited($event, $oldEvent);
555 }
556 else if ($event->getSpecialLabel() === Dictionary::EVENT_TYPE['shared_crm'])
557 {
558 self::onSharingCrmEventEdited($event, $oldEvent);
559 }
560 }
561 }
562
563 private static function onSharingCommonEventEdited(Event $event, Event $oldEvent): void
564 {
565 $sharingFactory = new Sharing\Link\Factory();
566
568 $eventLink = $sharingFactory->getEventLinkByEventId($event->getId());
569
570 //TODO remove if not needed
571// /** @var Sharing\Link\UserLink $crmDealLink */
572// $userLink = $sharingFactory->getLinkByHash($eventLink->getParentLinkHash());
573
574 $host = CUser::GetByID($eventLink->getHostId())->Fetch();
575 $email = $host['PERSONAL_MAILBOX'] ?? null;
576 $phone = $host['PERSONAL_PHONE'] ?? null;
577 $userContact = !empty($email) ? $email : $phone;
578
579 $notificationService = null;
580 if ($userContact && self::isEmailCorrect($userContact))
581 {
582 $notificationService = (new Sharing\Notification\Mail())
583 ->setEventLink($eventLink)
584 ->setEvent($event)
585 ->setOldEvent($oldEvent)
586 ;
587 }
588
589 if ($notificationService !== null)
590 {
591 $notificationService->notifyAboutSharingEventEdit($userContact);
592 }
593 }
594
595 private static function onSharingCrmEventEdited(Event $event, Event $oldEvent): void
596 {
597 if (!Loader::includeModule('crm'))
598 {
599 return;
600 }
601
602 (new Sharing\Crm\ActivityManager($event->getId()))
603 ->editActivityDeadline(DateTime::createFromUserTime($event->getStart()->toString()))
604 ;
605
606 $sharingFactory = new Sharing\Link\Factory();
607
609 $eventLink = $sharingFactory->getEventLinkByEventId($event->getId());
610 if (!$eventLink instanceof Sharing\Link\EventLink)
611 {
612 return;
613 }
614
616 $crmDealLink = $sharingFactory->getLinkByHash($eventLink->getParentLinkHash());
617 if (!$crmDealLink instanceof Sharing\Link\CrmDealLink)
618 {
619 return;
620 }
621
622 if ($crmDealLink->getContactId() > 0)
623 {
624 Crm\Integration\Calendar\Notification\Manager::getSenderInstance($crmDealLink)
625 ->setCrmDealLink($crmDealLink)
626 ->setEventLink($eventLink)
627 ->setEvent($event)
628 ->setOldEvent($oldEvent)
629 ->sendCrmSharingEdited()
630 ;
631 }
632 else
633 {
634 $email = CUser::GetByID($eventLink->getHostId())->Fetch()['PERSONAL_MAILBOX'] ?? null;
635 if (!is_string($email))
636 {
637 return;
638 }
639
640 (new Sharing\Notification\Mail())
641 ->setEventLink($eventLink)
642 ->setEvent($event)
643 ->setOldEvent($oldEvent)
644 ->notifyAboutSharingEventEdit($email)
645 ;
646 }
647 }
648
649 public static function onSharingEventDeleted(int $eventId, string $eventType): void
650 {
652 $eventLink = (new Sharing\Link\Factory())->getEventLinkByEventId($eventId);
653 if ($eventLink)
654 {
656
657 if ($eventType === Dictionary::EVENT_TYPE['shared'])
658 {
659 self::onSharingCommonEventDeclined($eventLink);
660 }
661 else if ($eventType === Dictionary::EVENT_TYPE['shared_crm'])
662 {
663 self::onSharingCrmEventDeclined($eventId);
664 }
665
666 }
667 }
668
669 public static function onSharingCommonEventDeclined(Sharing\Link\EventLink $eventLink)
670 {
671 self::setCanceledTimeOnSharedLink($eventLink->getEventId());
673 $event = (new Mappers\Event())->getById($eventLink->getEventId());
674
675 $host = CUser::GetByID($eventLink->getHostId())->Fetch();
676 $email = $host['PERSONAL_MAILBOX'] ?? null;
677 $phone = $host['PERSONAL_PHONE'] ?? null;
678 $userContact = !empty($email) ? $email : $phone;
679
680 $notificationService = null;
681 if ($userContact && self::isEmailCorrect($userContact))
682 {
683 $notificationService = (new Sharing\Notification\Mail())
684 ->setEventLink($eventLink)
685 ->setEvent($event)
686 ;
687 }
688
689 if ($notificationService !== null)
690 {
691 $notificationService->notifyAboutMeetingCancelled($userContact);
692 }
693 }
694
695 public static function setDeclinedStatusOnLinkOwnerEvent(Sharing\Link\EventLink $eventLink)
696 {
697 $userId = \CCalendar::GetUserId();
698 if ($userId !== 0 && $userId !== $eventLink->getHostId())
699 {
700 $ownerId = $eventLink->getOwnerId();
701 $event = EventTable::query()
702 ->setSelect(['ID'])
703 ->where('PARENT_ID', $eventLink->getEventId())
704 ->whereIn('EVENT_TYPE', self::getSharingEventTypes())
705 ->where('OWNER_ID', $ownerId)
706 ->exec()
707 ->fetch()
708 ;
709 if ($event['ID'] ?? false)
710 {
711 EventTable::update((int)$event['ID'], ['MEETING_STATUS' => Dictionary::MEETING_STATUS['No']]);
712 }
713 }
714 }
715
721 private static function updateEventSharingLink(Sharing\Link\EventLink $eventLink, array $fields): void
722 {
723 if (!empty($fields['DATE_TO']))
724 {
726 DateTime::createFromText($fields['DATE_TO']),
727 Sharing\Link\Helper::EVENT_SHARING_TYPE
728 );
729 $eventLink->setDateExpire($expireDate);
730 }
731
732 (new Sharing\Link\EventLinkMapper())->update($eventLink);
733 }
734
739 private static function getCrmDealLink(int $eventId): ?Link\CrmDealLink
740 {
741 $sharingLinkFactory = new Sharing\Link\Factory();
743 $eventLink = $sharingLinkFactory->getEventLinkByEventId($eventId);
744 if ($eventLink instanceof Sharing\Link\EventLink)
745 {
747 $crmDealLink = $sharingLinkFactory->getLinkByHash($eventLink->getParentLinkHash());
748 if ($crmDealLink instanceof Sharing\Link\CrmDealLink)
749 {
750 return $crmDealLink;
751 }
752 }
753
754 return null;
755 }
756
757 private function doesEventHasCorrectTime(): bool
758 {
759 $start = new DateTime($this->event->getStart()->toString());
760 $end = new DateTime($this->event->getEnd()->toString());
761
762 $offset = Util::getTimezoneOffsetUTC(\CCalendar::GetUserTimezoneName($this->ownerId));
763 $fromTs = Util::getDateTimestampUtc($start, $this->event->getStartTimeZone());
764 $toTs = Util::getDateTimestampUtc($end, $this->event->getEndTimeZone());
765
766 if ($fromTs < time())
767 {
768 return false;
769 }
770
771 $ownerDate = new \DateTime('now', new \DateTimeZone('UTC'));
772
773 $holidays = $this->getYearHolidays();
774 $intersectedHolidays = array_filter($holidays, static fn($holiday) => in_array($holiday, [
775 $ownerDate->setTimestamp($fromTs + $offset)->format('j.m'),
776 $ownerDate->setTimestamp($toTs + $offset)->format('j.m'),
777 ], true));
778
779 if (!empty($intersectedHolidays))
780 {
781 return false;
782 }
783
784 return true;
785 }
786
787 private function getYearHolidays(): array
788 {
789 return explode(',', \COption::GetOptionString('calendar', 'year_holidays', Loc::getMessage('EC_YEAR_HOLIDAYS_DEFAULT')));
790 }
791
792 private function doesEventSatisfyRule(): bool
793 {
794 $start = new DateTime($this->event->getStart()->toString());
795 $end = new DateTime($this->event->getEnd()->toString());
796 $fromTs = Util::getDateTimestampUtc($start, $this->event->getStartTimeZone());
797 $toTs = Util::getDateTimestampUtc($end, $this->event->getEndTimeZone());
798
799 $rule = $this->link->getSharingRule();
800 $eventDurationMinutes = ($toTs - $fromTs) / 60;
801 if ($eventDurationMinutes !== $rule->getSlotSize())
802 {
803 return false;
804 }
805
806 $availableTime = [];
807 foreach ($rule->getRanges() as $range)
808 {
809 foreach ($range->getWeekdays() as $weekday)
810 {
811 $availableTime[$weekday] ??= [];
812 $availableTime[$weekday][] = [
813 'from' => $range->getFrom(),
814 'to' => $range->getTo(),
815 ];
816
817 [$intersected, $notIntersected] = $this->separate(fn($interval) => Util::doIntervalsIntersect(
818 $interval['from'],
819 $interval['to'],
820 $range->getFrom(),
821 $range->getTo(),
822 ), $availableTime[$weekday]);
823
824 if (!empty($intersected))
825 {
826 $from = min(array_column($intersected, 'from'));
827 $to = max(array_column($intersected, 'to'));
828
829 $availableTime[$weekday] = [...$notIntersected, [
830 'from' => $from,
831 'to' => $to,
832 ]];
833 }
834 }
835 }
836
837 $offset = Util::getTimezoneOffsetUTC(\CCalendar::GetUserTimezoneName($this->ownerId)) / 60;
838 $minutesFrom = ($fromTs % 86400) / 60;
839 $minutesTo = ($toTs % 86400) / 60;
840 $weekday = (int)gmdate('N', $fromTs) % 7;
841 foreach ($availableTime[$weekday] as $range)
842 {
843 if ($minutesFrom >= $range['from'] - $offset && $minutesTo <= $range['to'] - $offset)
844 {
845 return true;
846 }
847 }
848
849 return false;
850 }
851
852 private function separate($take, $array): array
853 {
854 return array_reduce($array, fn($s, $e) => $take($e) ? [[...$s[0], $e], $s[1]] : [$s[0], [...$s[1], $e]], [[], []]);
855 }
856
860 private function checkUserAccessibility(array $userIds): bool
861 {
862 $start = new DateTime($this->event->getStart()->toString());
863 $end = new DateTime($this->event->getEnd()->toString());
864 $fromTs = Util::getDateTimestampUtc($start, $this->event->getStartTimeZone());
865 $toTs = Util::getDateTimestampUtc($end, $this->event->getEndTimeZone());
866
867 return (new SharingAccessibilityManager([
868 'userIds' => $userIds,
869 'timestampFrom' => $fromTs,
870 'timestampTo' => $toTs,
871 ]))->checkUsersAccessibility();
872 }
873
878 private static function getSectionId($userId)
879 {
880 $result = \CCalendarSect::GetList([
881 'arFilter' => [
882 'OWNER_ID' => $userId,
883 'CAL_TYPE' => 'user',
884 'ACTIVE' => 'Y'
885 ]
886 ]);
887
888 if (!$result)
889 {
890 $createdSection = \CCalendarSect::CreateDefault([
891 'type' => 'user',
892 'ownerId' => $userId,
893 ]);
894 $result[] = $createdSection;
895 }
896
897 return $result[0]['ID'];
898 }
899
903 private function notifyEventDeleted()
904 {
905 return \CCalendarNotify::Send([
906 'mode' => 'cancel_sharing',
907 'userId' => $this->hostId,
908 'guestId' => $this->ownerId,
909 'eventId' => $this->event->getId(),
910 'from' => $this->event->getStart()->toString(),
911 'to' => $this->event->getEnd()->toString(),
912 'name' => $this->event->getName(),
913 'isSharing' => true,
914 ]);
915 }
916
918 {
919 $event = (new Mappers\Event)->getById($eventLink->getEventId());
920 if ($event)
921 {
922 $event = \CCalendarEvent::GetList([
923 'arFilter' => [
924 'ID' => $event->getId(),
925 ],
926 'fetchAttendees' => true,
927 'checkPermissions' => false,
928 'parseRecursion' => false,
929 'setDefaultLimit' => false,
930 'limit' => null,
931 ]);
932
933 $event = $event[0] ?? null;
934 if ($event)
935 {
936 $event['ATTENDEES'] = [$eventLink->getOwnerId(), $eventLink->getHostId()];
937 \CCalendar::SaveEvent([
938 'arFields' => $event,
939 'userId' => $eventLink->getOwnerId(),
940 'checkPermission' => false,
941 'sendInvitations' => true
942 ]);
943 }
944 }
945 }
946}
static createSharingLinkExpireDate(?DateTime $dateTime, string $linkType)
Definition helper.php:344
deactivateEventLink(Sharing\Link\EventLink $eventLink)
createEvent(bool $sendInvitations=true, string $externalUserName='')
static reSaveEventWithoutAttendeesExceptHostAndSharingLinkOwner(Sharing\Link\EventLink $eventLink)
static prepareEventForSave($data, $userId, Sharing\Link\Joint\JointLink $link)
static setDeclinedStatusOnLinkOwnerEvent(Sharing\Link\EventLink $eventLink)
__construct(Event $event, ?int $hostId=null, ?int $ownerId=null, ?Sharing\Link\Link $link=null)
static getTimezoneOffsetUTC(string $timezoneName)
Definition util.php:733
static doIntervalsIntersect($from1, $to1, $from2, $to2)
Definition util.php:805
static getDateTimestamp(?string $dateFrom, ?string $timezone)
Definition util.php:690
static getDateTimestampUtc(DateTime $date, ?string $eventTimezone=null)
Definition util.php:740
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
static createFromText($text)
Definition date.php:414
static createFromTimestamp($timestamp)
Definition datetime.php:246
static createFromUserTime($timeString)
Definition datetime.php:180