64 $monthFrom = (int)
$request->getPost(
'month_from');
65 $yearFrom = (int)
$request->getPost(
'year_from');
66 $monthTo = (int)
$request->getPost(
'month_to');
67 $yearTo = (int)
$request->getPost(
'year_to');
68 $ownerId = (int)
$request->getPost(
'ownerId');
69 $calendarType =
$request->getPost(
'type');
71 $direction =
$request->getPost(
'direction');
72 if (!in_array($direction, [self::DIRECTION_PREVIOUS, self::DIRECTION_NEXT, self::DIRECTION_BOTH],
true))
77 $activeSectionIds = is_array(
$request->getPost(
'active_sect'))
80 $additionalSectionIds = is_array(
$request->getPost(
'sup_sect'))
85 $limits = \CCalendarEvent::getLimitDates($yearFrom, $monthFrom, $yearTo, $monthTo);
91 foreach(array_unique(array_merge($activeSectionIds, $additionalSectionIds)) as $sectId)
93 if ($sectId ===
'tasks')
97 elseif ((
int)$sectId > 0)
99 $sectionIdList[] = (int)$sectId;
103 if (!empty($sectionIdList))
105 $sect = \CCalendarSect::GetList([
107 'ID' => $sectionIdList,
110 'checkPermissions' =>
true
112 foreach($sect as $section)
114 $sections[] = (int)$section[
'ID'];
118 $isBoundaryOfPastReached =
false;
119 $isBoundaryOfFutureReached =
false;
121 if (!empty($sections))
123 $entries = $this->
getEntries($sections, $limits);
126 $direction === self::DIRECTION_BOTH
130 $isBoundaryOfPastReached =
true;
131 $isBoundaryOfFutureReached =
true;
137 $entries = $this->
getEntries($sections, $limits);
139 if (!empty($entries))
142 $timestamp = strtotime($earliestEvent[
'DATE_FROM']);
143 if($timestamp < strtotime(
"01.$monthFrom.$yearFrom"))
145 $yearFrom = (int)date(
'Y', $timestamp);
146 $monthFrom = (int)date(
'm', $timestamp);
150 $timestamp = strtotime($latestEvent[
'DATE_FROM']);
151 if($timestamp > strtotime(
"01.$monthTo.$yearTo"))
153 $yearTo = (int)date(
'Y', $timestamp);
154 $monthTo = (int)date(
'm', $timestamp);
161 ($direction === self::DIRECTION_PREVIOUS)
167 $entries = $this->
getEntries($sections, \CCalendarEvent::getLimitDates($yearFrom, $monthFrom, $yearTo, $monthTo));
173 $limits = \CCalendarEvent::getLimitDates($yearFrom, $monthFrom, $yearTo, $monthTo);
174 $entries = $this->
getEntries($sections, $limits);
178 $isBoundaryOfPastReached =
true;
180 $limits[
'from'] =
false;
181 $entries = $this->
getEntries($sections, $limits);
183 if (!empty($entries))
186 $timestamp = strtotime($earliestEvent[
'DATE_FROM']);
187 $yearFrom = (int)date(
'Y', $timestamp);
188 $monthFrom = (int)date(
'm', $timestamp);
195 ($direction === self::DIRECTION_NEXT)
201 $entries = $this->
getEntries($sections, \CCalendarEvent::getLimitDates($yearFrom, $monthFrom, $yearTo, $monthTo));
207 $limits = \CCalendarEvent::getLimitDates($yearFrom, $monthFrom, $yearTo, $monthTo);
208 $entries = $this->
getEntries($sections, $limits);
212 $isBoundaryOfFutureReached =
true;
214 $limits[
'to'] =
false;
215 $entries = $this->
getEntries($sections, $limits);
217 if (!empty($entries))
220 $timestamp = strtotime($latestEvent[
'DATE_FROM']);
221 $yearTo = (int)date(
'Y', $timestamp);
222 $monthTo = (int)date(
'm', $timestamp);
230 $userId = \CCalendar::GetUserId();
232 foreach ($entries as $key => $entry)
234 $eventModel = EventModel::createFromArray($entry);
235 $canEditEventInParentSection = $accessController->check(ActionDictionary::ACTION_EVENT_EDIT, $eventModel);
236 $canEditEventInCurrentSection = $accessController->check(ActionDictionary::ACTION_EVENT_EDIT, $eventModel, [
237 'checkCurrentEvent' =>
'Y',
239 $entries[$key][
'permissions'] = [
240 'edit' => $canEditEventInParentSection && $canEditEventInCurrentSection,
247 $tasksEntries = \CCalendar::getTaskList(
249 'type' => $calendarType,
250 'ownerId' => $ownerId,
254 if (!empty($tasksEntries))
256 $entries = array_merge($entries, $tasksEntries);
261 'entries' => $entries,
262 'userIndex' => \CCalendarEvent::getUserIndex(),
263 'isBoundaryOfPastReached' => $isBoundaryOfPastReached,
264 'isBoundaryOfFutureReached' => $isBoundaryOfFutureReached,
266 if (is_array($connections))
268 $response[
'connections'] = $connections;
272 (
int)
$request->getPost(
'month_from') !== $monthFrom
273 || (
int)
$request->getPost(
'year_from') !== $yearFrom
276 $response[
'newYearFrom'] = $yearFrom;
277 $response[
'newMonthFrom'] = $monthFrom;
281 (
int)
$request->getPost(
'month_to') !== $monthTo
282 || (
int)
$request->getPost(
'year_to') !== $yearTo
285 $response[
'newYearTo'] = $yearTo;
286 $response[
'newMonthTo'] = $monthTo;
393 $userId = \CCalendar::getCurUserId();
395 $sectionId = (int)
$request->getPost(
'section');
399 $eventModel = \CCalendarEvent::getEventModelForPermissionCheck($id, [], $userId);
403 $section = \CCalendarSect::GetById($sectionId);
406 EventModel::createNew()
407 ->setOwnerId((
int)($section[
'OWNER_ID'] ?? 0))
408 ->setSectionId($sectionId ?? 0)
409 ->setSectionType($section[
'TYPE'] ??
'')
414 (!$id && !$accessController->check(ActionDictionary::ACTION_EVENT_ADD, $eventModel))
415 || ($id && !$accessController->check(ActionDictionary::ACTION_EVENT_EDIT, $eventModel))
421 $sectionList = Internals\SectionTable::getList([
435 if (!($section = $sectionList->fetch()))
441 $section[
'CAL_TYPE'] !==
'group'
442 && Loader::includeModule(
'intranet') && !Intranet\Util::isIntranetUser($userId)
451 $entry = Internals\EventTable::getList(
456 "=SECTION_ID" => $sectionId
458 "select" => [
"ID",
"CAL_TYPE"]
462 if (Loader::includeModule(
'intranet'))
464 if ($entry[
'CAL_TYPE'] !==
'group' && !Intranet\Util::isIntranetUser($userId))
471 $requestUid = (int)
$request->getPost(
'requestUid');
472 $reload =
$request->getPost(
'recursive') ===
'Y';
473 $sendInvitesToDeclined =
$request->getPost(
'sendInvitesAgain') ===
'Y';
474 $skipTime =
$request->getPost(
'skip_time') ===
'Y';
475 $dateFrom =
$request->getPost(
'date_from');
476 $dateTo =
$request->getPost(
'date_to');
477 $timezone =
$request->getPost(
'timezone');
478 $attendees =
$request->getPost(
'attendees');
479 $location = trim((
string)
$request->getPost(
'location'));
480 $isPlannerFeatureEnabled = Bitrix24Manager::isPlannerFeatureEnabled();
482 $locationBusyWarning =
false;
483 $busyWarning =
false;
489 "DATE_FROM" => \CCalendar::Date(\CCalendar::Timestamp($dateFrom), !$skipTime),
490 "SKIP_TIME" => $skipTime
495 $arFields[
"DATE_TO"] = \CCalendar::Date(\CCalendar::Timestamp($dateTo), !$skipTime);
498 if (!$skipTime &&
$request->getPost(
'set_timezone') ===
'Y' && $timezone)
500 $arFields[
"TZ_FROM"] = $timezone;
501 $arFields[
"TZ_TO"] = $timezone;
505 $isPlannerFeatureEnabled
510 $locationBusyWarning =
true;
515 $isPlannerFeatureEnabled
516 && is_array($attendees)
517 &&
$request->getPost(
'is_meeting') ===
'Y'
520 $timezoneName = \CCalendar::GetUserTimezoneName(\CCalendar::GetUserId());
522 $timestampFrom = \CCalendar::TimestampUTC($arFields[
"DATE_FROM"]) - $timezoneOffset;
523 $timestampTo = \CCalendar::TimestampUTC($arFields[
"DATE_TO"]) - $timezoneOffset;
524 if (!empty($this->getBusyUsersIds($attendees, $id, $timestampFrom, $timestampTo)))
531 if (!$busyWarning && !$locationBusyWarning)
533 if (
$request->getPost(
'recursive') ===
'Y')
535 \CCalendar::SaveEventEx(
537 'arFields' => $arFields,
538 'silentErrorMode' =>
false,
539 'recursionEditMode' =>
'this',
540 'currentEventDateFrom' => \CCalendar::Date(
541 \CCalendar::Timestamp(
$request->getPost(
'current_date_from')),
544 'sendInvitesToDeclined' => $sendInvitesToDeclined,
545 'requestUid' => $requestUid
551 $id = \CCalendar::SaveEvent(
553 'arFields' => $arFields,
554 'silentErrorMode' =>
false,
555 'sendInvitesToDeclined' => $sendInvitesToDeclined,
556 'requestUid' => $requestUid
566 'busy_warning' => $busyWarning,
567 'location_busy_warning' => $locationBusyWarning
577 $sectionId = (int)
$request[
'section'];
578 $requestUid = (int)
$request[
'requestUid'];
579 $userId = \CCalendar::getCurUserId();
580 $isPlannerFeatureEnabled = Bitrix24Manager::isPlannerFeatureEnabled();
581 $checkCurrentUsersAccessibility = !$id ||
$request->getPost(
'checkCurrentUsersAccessibility') !==
'N';
585 $eventModel = \CCalendarEvent::getEventModelForPermissionCheck($id, [], $userId);
589 $section = \CCalendarSect::GetById($sectionId,
false);
592 EventModel::createNew()
593 ->setOwnerId((
int)($section[
'OWNER_ID'] ?? 0))
594 ->setSectionId($sectionId)
595 ->setSectionType($section[
'CAL_TYPE'] ??
'')
600 (!$id && !$accessController->check(ActionDictionary::ACTION_EVENT_ADD, $eventModel))
601 || ($id && !$accessController->check(ActionDictionary::ACTION_EVENT_EDIT, $eventModel))
612 $sectionList = Internals\SectionTable::getList([
626 if (!($section = $sectionList->fetch()))
632 $section[
'CAL_TYPE'] !==
'group'
633 && Loader::includeModule(
'intranet') && !Intranet\Util::isIntranetUser($userId)
650 $reminderList = \CCalendarReminder::prepareReminder(
$request[
'reminder']);
652 $rrule = $this->prepareRecurringRule(
$request[
'EVENT_RRULE'],
$request[
'rrule_endson']);
660 $dateFrom .=
' '.$request[
'time_from'];
661 $dateTo .=
' '.$request[
'time_to'];
663 $dateFrom = trim($dateFrom);
664 $dateTo = trim($dateTo);
667 (
int)(
new \
DateTime())->setTimestamp(\CCalendar::Timestamp($dateFrom))->format(
'Y') > 9999
668 || (
int)(
new \
DateTime())->setTimestamp(\CCalendar::Timestamp($dateTo))->format(
'Y') > 9999
678 if (!$tzFrom && isset(
$request[
'default_tz']))
682 if (!$tzTo && isset(
$request[
'default_tz']))
689 \CCalendar::SaveUserTimezoneName(\CCalendar::GetUserId(),
$request[
'default_tz']);
694 'DATE_FROM' => $dateFrom,
695 'DATE_TO' => $dateTo,
696 'SKIP_TIME' => $skipTime,
697 'TZ_FROM' => $tzFrom,
700 'DESCRIPTION' => trim(
$request[
'desc']),
701 'SECTIONS' => [$sectionId],
703 'ACCESSIBILITY' =>
$request[
'accessibility'],
704 'IMPORTANCE' =>
$request[
'importance'] ??
'normal',
705 'PRIVATE_EVENT' =>
$request[
'private_event'] ===
'Y',
708 'REMIND' => $reminderList,
709 'SECTION_CAL_TYPE' => $section[
'CAL_TYPE'],
710 'SECTION_OWNER_ID' => $section[
'OWNER_ID']
714 if (isset(
$request[
'attendeesEntityList']) && is_array(
$request[
'attendeesEntityList']))
719 $accessCodes = \CCalendarEvent::handleAccessCodes($codes, [
'userId' => $userId]);
721 $entryFields[
'IS_MEETING'] =
722 $accessCodes !== [
'U'.$userId] || in_array($entryFields[
'SECTION_CAL_TYPE'], [
'group',
'company_calendar'],
true)
725 $entryFields[
'ATTENDEES_CODES'] = $accessCodes;
726 $entryFields[
'ATTENDEES'] = \CCalendar::GetDestinationUsers($accessCodes);
727 $response[
'reload'] =
true;
729 if (
$request[
'exclude_users'] && !empty($entryFields[
'ATTENDEES']))
731 $excludeUsers = explode(
',',
$request[
'exclude_users']);
732 $entryFields[
'ATTENDEES_CODES'] = [];
734 if (!empty($excludeUsers))
736 $entryFields[
'ATTENDEES'] = array_diff($entryFields[
'ATTENDEES'], $excludeUsers);
737 foreach($entryFields[
'ATTENDEES'] as $attendee)
739 $entryFields[
'ATTENDEES_CODES'][] =
'U'. (int)$attendee;
748 $meetingHost = (int)
$request[
'meeting_host'];
753 $entryFields[
'MEETING_HOST'] = $meetingHost;
757 $entryFields[
'MEETING_HOST'] = \CCalendar::GetUserId();
760 $entryFields[
'MEETING'] = [
761 'HOST_NAME' => \CCalendar::GetUserName($entryFields[
'MEETING_HOST']),
762 'NOTIFY' =>
$request[
'meeting_notify'] ===
'Y',
763 'REINVITE' =>
$request[
'meeting_reinvite'] ===
'Y',
764 'ALLOW_INVITE' =>
$request[
'allow_invite'] ===
'Y',
765 'MEETING_CREATOR' => $entryFields[
'MEETING_HOST'],
766 'HIDE_GUESTS' =>
$request[
'hide_guests'] ===
'Y'
769 $recurrenceEventMode = !empty(
$request[
'rec_edit_mode']) ?
$request[
'rec_edit_mode'] :
null;
770 $currentEventDate = !empty(
$request[
'current_date_from'])
771 ? \CCalendar::Date(\CCalendar::Timestamp(
$request[
'current_date_from']),
false)
778 $entryFields[
'MEETING'][
'CHAT_ID'] = $chatId;
786 if ($entryFields[
'IS_MEETING'] && $isPlannerFeatureEnabled)
789 if ($checkCurrentUsersAccessibility)
791 $attendees = $entryFields[
'ATTENDEES'];
793 else if (is_array(
$request[
'newAttendeesList']))
795 $attendees = array_diff(
$request[
'newAttendeesList'], $excludeUsers);
798 $timezoneFrom = !empty($tzFrom) ? $tzFrom : \CCalendar::GetUserTimezoneName(\CCalendar::GetUserId());
799 $timezoneTo = !empty($tzTo) ? $tzTo : $timezoneFrom;
802 $timestampFrom = \CCalendar::TimestampUTC($dateFrom) - $timezoneOffsetFrom;
803 $timestampTo = \CCalendar::TimestampUTC($dateTo) - $timezoneOffsetTo;
806 $timestampTo += \CCalendar::GetDayLen();
808 $busyUsers = $this->getBusyUsersIds($attendees, $id, $timestampFrom, $timestampTo);
809 if (!empty($busyUsers))
811 $response[
'busyUsersList'] = \CCalendarEvent::getUsersDetails($busyUsers);
812 $busyUserName = current($response[
'busyUsersList'])[
'DISPLAY_NAME'];
819 foreach(
$request as $field => $value)
821 if (mb_strpos($field,
'UF_') === 0)
823 $arUFFields[$field] = $value;
835 $newId = \CCalendar::SaveEvent([
836 'arFields' => $entryFields,
838 'silentErrorMode' =>
false,
839 'recursionEditMode' => $recurrenceEventMode,
840 'currentEventDateFrom' => $currentEventDate,
841 'sendInvitesToDeclined' =>
$request[
'sendInvitesAgain'] ===
'Y',
842 'requestUid' => $requestUid,
843 'checkLocationOccupancy' => (
$request[
'doCheckOccupancy'] ??
'N') ===
'Y',
849 $this->
addError(
new Error($e->getMessage(),
'edit_entry_location_repeat_busy'));
852 $errors = \CCalendar::GetErrors();
854 $eventIdList = [$newId];
856 if ($newId && empty($errors))
858 $response[
'entryId'] = $newId;
862 'FROM_LIMIT' => \CCalendar::Date(
863 \CCalendar::Timestamp($entryFields[
'DATE_FROM']) -
864 \CCalendar::DAY_LENGTH * 10,
false
866 'TO_LIMIT' => \CCalendar::Date(
867 \CCalendar::Timestamp($entryFields[
'DATE_TO']) +
868 \CCalendar::DAY_LENGTH * 90,
false
872 $eventList = \CCalendarEvent::GetList(
874 'arFilter' => $filter,
875 'parseRecursion' =>
true,
876 'fetchAttendees' =>
true,
877 'userId' => \CCalendar::GetUserId(),
881 if ($entryFields[
'IS_MEETING'])
883 \Bitrix\Main\FinderDestTable::merge(
888 [
'U'. \CCalendar::GetUserId()]
894 if (isset($_REQUEST[
'rec_edit_mode']) && in_array($_REQUEST[
'rec_edit_mode'], [
'this',
'next']))
896 unset($filter[
'ID']);
897 $filter[
'RECURRENCE_ID'] = ($eventList && $eventList[0] && $eventList[0][
'RECURRENCE_ID']) ? $eventList[0][
'RECURRENCE_ID'] : $newId;
899 $resRelatedEvents = \CCalendarEvent::GetList(
901 'arFilter' => $filter,
902 'parseRecursion' =>
true,
903 'fetchAttendees' =>
true,
904 'userId' => \CCalendar::GetUserId()
908 foreach($resRelatedEvents as $ev)
910 $eventIdList[] = $ev[
'ID'];
912 $eventList = array_merge($eventList, $resRelatedEvents);
914 else if ($id && $eventList && $eventList[0] && \CCalendarEvent::CheckRecurcion($eventList[0]))
916 $recId = $eventList[0][
'RECURRENCE_ID'] ?? $eventList[0][
'ID'];
918 if ($eventList[0][
'RECURRENCE_ID'] && $eventList[0][
'RECURRENCE_ID'] !== $eventList[0][
'ID'])
920 unset($filter[
'RECURRENCE_ID']);
921 $filter[
'ID'] = $eventList[0][
'RECURRENCE_ID'];
922 $resRelatedEvents = \CCalendarEvent::GetList(
924 'arFilter' => $filter,
925 'parseRecursion' =>
true,
926 'fetchAttendees' =>
true,
927 'userId' => \CCalendar::GetUserId(),
930 $eventIdList[] = $eventList[0][
'RECURRENCE_ID'];
931 $eventList = array_merge($eventList, $resRelatedEvents);
936 unset($filter[
'ID']);
937 $filter[
'RECURRENCE_ID'] = $recId;
938 $resRelatedEvents = \CCalendarEvent::GetList(
940 'arFilter' => $filter,
941 'parseRecursion' =>
true,
942 'fetchAttendees' =>
true,
943 'userId' => \CCalendar::GetUserId(),
947 foreach($resRelatedEvents as $ev)
949 $eventIdList[] = $ev[
'ID'];
951 $eventList = array_merge($eventList, $resRelatedEvents);
955 else if (is_iterable($errors))
957 foreach ($errors as $error)
959 if (is_string($error))
966 $pathToCalendar = \CCalendar::GetPathForCalendarEx($userId);
967 foreach($eventList as $ind => $event)
969 $eventList[$ind][
'~URL'] = \CHTTP::urlAddParams($pathToCalendar, [
'EVENT_ID' => $event[
'ID']]);
972 $response[
'eventList'] = $eventList;
973 $response[
'eventIdList'] = $eventIdList;
974 $response[
'countEventWithEmailGuestAmount'] = Bitrix24Manager::getCountEventWithEmailGuestAmount();
977 $userSettings[
'defaultReminders'][$skipTime ?
'fullDay' :
'withTime'] = $reminderList;