public function editEntryAction()
{
$response = [];
$request = $this->getRequest();
$id = (int)$request['id'];
$sectionId = (int)$request['section'];
$requestUid = (int)$request['requestUid'];
$userId = CCalendar::getCurUserId();
$isPlannerFeatureEnabled = Bitrix24Manager::isPlannerFeatureEnabled();
$checkCurrentUsersAccessibility = !$id || $request->getPost('checkCurrentUsersAccessibility') !== 'N';
if ($id)
{
$eventModel = CCalendarEvent::getEventModelForPermissionCheck($id, [], $userId);
}
else
{
$section = CCalendarSect::GetById($sectionId, false);
$eventModel =
EventModel::createNew()
->setOwnerId((int)($section['OWNER_ID'] ?? 0))
->setSectionId($sectionId)
->setSectionType($section['CAL_TYPE'] ?? '')
;
}
$accessController = new EventAccessController($userId);
if (
(!$id && !$accessController->check(ActionDictionary::ACTION_EVENT_ADD, $eventModel))
|| ($id && !$accessController->check(ActionDictionary::ACTION_EVENT_EDIT, $eventModel))
)
{
$this->addError(new Error(Loc::getMessage('EC_ACCESS_DENIED'), 'edit_entry_access_denied'));
}
if (!empty($this->getErrors()))
{
return $response;
}
$sectionList = InternalsSectionTable::getList([
'filter' => [
'=ACTIVE' => 'Y',
'=ID' => $sectionId
],
'select' => [
'ID',
'CAL_TYPE',
'OWNER_ID',
'NAME'
]
]
);
if (!($section = $sectionList->fetch()))
{
$this->addError(new Error(Loc::getMessage('EC_SECTION_NOT_FOUND'), 'edit_entry_section_not_found'));
}
if (
$section['CAL_TYPE'] !== 'group'
&& Loader::includeModule('intranet') && !IntranetUtil::isIntranetUser($userId)
)
{
$this->addError(new Error(Loc::getMessage('EC_ACCESS_DENIED'), 'edit_entry_extranet_access_denied'));
}
if (!empty($this->getErrors()))
{
return $response;
}
// Default name for events
$name = trim($request['name']);
if (empty($name))
{
$name = Loc::getMessage('EC_DEFAULT_EVENT_NAME_V2');
}
$reminderList = CCalendarReminder::prepareReminder($request['reminder']);
$rrule = $this->prepareRecurringRule($request['EVENT_RRULE'], $request['rrule_endson']);
// Date & Time
$dateFrom = $request['date_from'];
$dateTo = $request['date_to'];
$skipTime = isset($request['skip_time']) && $request['skip_time'] === 'Y';
if (!$skipTime)
{
$dateFrom .= ' '.$request['time_from'];
$dateTo .= ' '.$request['time_to'];
}
$dateFrom = trim($dateFrom);
$dateTo = trim($dateTo);
// Timezone
$tzFrom = $request['tz_from'];
$tzTo = $request['tz_to'];
if (!$tzFrom && isset($request['default_tz']))
{
$tzFrom = $request['default_tz'];
}
if (!$tzTo && isset($request['default_tz']))
{
$tzTo = $request['default_tz'];
}
if (isset($request['default_tz']) && (string)$request['default_tz'] !== '')
{
CCalendar::SaveUserTimezoneName(CCalendar::GetUserId(), $request['default_tz']);
}
$entryFields = [
'ID' => $id,
'DATE_FROM' => $dateFrom,
'DATE_TO' => $dateTo,
'SKIP_TIME' => $skipTime,
'TZ_FROM' => $tzFrom,
'TZ_TO' => $tzTo,
'NAME' => $name,
'DESCRIPTION' => trim($request['desc']),
'SECTIONS' => [$sectionId],
'COLOR' => $request['color'],
'ACCESSIBILITY' => $request['accessibility'],
'IMPORTANCE' => $request['importance'] ?? 'normal',
'PRIVATE_EVENT' => $request['private_event'] === 'Y',
'RRULE' => $rrule,
'LOCATION' => $request['location'],
'REMIND' => $reminderList,
'SECTION_CAL_TYPE' => $section['CAL_TYPE'],
'SECTION_OWNER_ID' => $section['OWNER_ID']
];
$codes = [];
if (isset($request['attendeesEntityList']) && is_array($request['attendeesEntityList']))
{
$codes = Util::convertEntitiesToCodes($request['attendeesEntityList']);
}
$accessCodes = CCalendarEvent::handleAccessCodes($codes, ['userId' => $userId]);
$entryFields['IS_MEETING'] =
$accessCodes !== ['U'.$userId] || in_array($entryFields['SECTION_CAL_TYPE'], ['group', 'company_calendar'], true)
;
$entryFields['ATTENDEES_CODES'] = $accessCodes;
$entryFields['ATTENDEES'] = CCalendar::GetDestinationUsers($accessCodes);
$response['reload'] = true;
if ($request['exclude_users'] && !empty($entryFields['ATTENDEES']))
{
$excludeUsers = explode(',', $request['exclude_users']);
$entryFields['ATTENDEES_CODES'] = [];
if (!empty($excludeUsers))
{
$entryFields['ATTENDEES'] = array_diff($entryFields['ATTENDEES'], $excludeUsers);
foreach($entryFields['ATTENDEES'] as $attendee)
{
$entryFields['ATTENDEES_CODES'][] = 'U'. (int)$attendee;
}
}
}
else
{
$excludeUsers = [];
}
$meetingHost = (int)$request['meeting_host'];
$chatId = (int)$request['chat_id'];
if ($meetingHost)
{
$entryFields['MEETING_HOST'] = $meetingHost;
}
else
{
$entryFields['MEETING_HOST'] = CCalendar::GetUserId();
}
$entryFields['MEETING'] = [
'HOST_NAME' => CCalendar::GetUserName($entryFields['MEETING_HOST']),
'NOTIFY' => $request['meeting_notify'] === 'Y',
'REINVITE' => $request['meeting_reinvite'] === 'Y',
'ALLOW_INVITE' => $request['allow_invite'] === 'Y',
'MEETING_CREATOR' => $entryFields['MEETING_HOST'],
'HIDE_GUESTS' => $request['hide_guests'] === 'Y'
];
$recurrenceEventMode = !empty($request['rec_edit_mode']) ? $request['rec_edit_mode'] : null;
$currentEventDate = !empty($request['current_date_from'])
? CCalendar::Date(CCalendar::Timestamp($request['current_date_from']), false)
: null
;
if ($chatId)
{
$entryFields['MEETING']['CHAT_ID'] = $chatId;
}
if (!RoomsAccessibilityManager::checkAccessibility($entryFields['LOCATION'], ['fields' => $entryFields]))
{
$this->addError(new Error(Loc::getMessage('EC_LOCATION_BUSY'), 'edit_entry_location_busy'));
}
if ($entryFields['IS_MEETING'] && $isPlannerFeatureEnabled)
{
$attendees = [];
if ($checkCurrentUsersAccessibility)
{
$attendees = $entryFields['ATTENDEES'];
}
else if (is_array($request['newAttendeesList']))
{
$attendees = array_diff($request['newAttendeesList'], $excludeUsers);
}
$timezoneName = CCalendar::GetUserTimezoneName(CCalendar::GetUserId());
$timezoneOffset = Util::getTimezoneOffsetUTC($timezoneName);
$timestampFrom = CCalendar::TimestampUTC($dateFrom) - $timezoneOffset;
$timestampTo = CCalendar::TimestampUTC($dateTo) - $timezoneOffset;
$busyUsers = $this->getBusyUsersIds($attendees, $id, $timestampFrom, $timestampTo);
if (!empty($busyUsers))
{
$response['busyUsersList'] = CCalendarEvent::getUsersDetails($busyUsers);
$busyUserName = current($response['busyUsersList'])['DISPLAY_NAME'];
$this->addError(new Error(Loc::getMessage('EC_USER_BUSY', ['#USER#' => $busyUserName]), 'edit_entry_user_busy'));
}
}
// Userfields for event
$arUFFields = [];
foreach($request as $field => $value)
{
if (mb_strpos($field, 'UF_') === 0)
{
$arUFFields[$field] = $value;
}
}
if (!empty($this->getErrors()))
{
return $response;
}
$newId = false;
try
{
$newId = CCalendar::SaveEvent([
'arFields' => $entryFields,
'UF' => $arUFFields,
'silentErrorMode' => false,
'recursionEditMode' => $recurrenceEventMode,
'currentEventDateFrom' => $currentEventDate,
'sendInvitesToDeclined' => $request['sendInvitesAgain'] === 'Y',
'requestUid' => $requestUid,
'checkLocationOccupancy' => ($request['doCheckOccupancy'] ?? 'N') === 'Y',
]);
}
catch (RoomsOccupancyCheckerException $e)
{
$this->addError(new Error(Loc::getMessage('EC_LOCATION_BUSY_RECURRENCE'), 'edit_entry_location_busy_recurrence'));
$this->addError(new Error($e->getMessage(), 'edit_entry_location_repeat_busy'));
}
$errors = CCalendar::GetErrors();
$eventList = [];
$eventIdList = [$newId];
if ($newId && empty($errors))
{
$response['entryId'] = $newId;
$filter = [
'ID' => $newId,
'FROM_LIMIT' => CCalendar::Date(
CCalendar::Timestamp($entryFields['DATE_FROM']) -
CCalendar::DAY_LENGTH * 10, false
),
'TO_LIMIT' => CCalendar::Date(
CCalendar::Timestamp($entryFields['DATE_TO']) +
CCalendar::DAY_LENGTH * 90, false
)
];
$eventList = CCalendarEvent::GetList(
[
'arFilter' => $filter,
'parseRecursion' => true,
'fetchAttendees' => true,
'userId' => CCalendar::GetUserId(),
]
);
if ($entryFields['IS_MEETING'])
{
BitrixMainFinderDestTable::merge(
[
'CONTEXT' => Util::getUserSelectorContext(),
'CODE' => BitrixMainFinderDestTable::convertRights(
$accessCodes,
['U'. CCalendar::GetUserId()]
)
]
);
}
if (isset($_REQUEST['rec_edit_mode']) && in_array($_REQUEST['rec_edit_mode'], ['this', 'next']))
{
unset($filter['ID']);
$filter['RECURRENCE_ID'] = ($eventList && $eventList[0] && $eventList[0]['RECURRENCE_ID']) ? $eventList[0]['RECURRENCE_ID'] : $newId;
$resRelatedEvents = CCalendarEvent::GetList(
[
'arFilter' => $filter,
'parseRecursion' => true,
'fetchAttendees' => true,
'userId' => CCalendar::GetUserId()
]
);
foreach($resRelatedEvents as $ev)
{
$eventIdList[] = $ev['ID'];
}
$eventList = array_merge($eventList, $resRelatedEvents);
}
else if ($id && $eventList && $eventList[0] && CCalendarEvent::CheckRecurcion($eventList[0]))
{
$recId = $eventList[0]['RECURRENCE_ID'] ?? $eventList[0]['ID'];
if ($eventList[0]['RECURRENCE_ID'] && $eventList[0]['RECURRENCE_ID'] !== $eventList[0]['ID'])
{
unset($filter['RECURRENCE_ID']);
$filter['ID'] = $eventList[0]['RECURRENCE_ID'];
$resRelatedEvents = CCalendarEvent::GetList(
[
'arFilter' => $filter,
'parseRecursion' => true,
'fetchAttendees' => true,
'userId' => CCalendar::GetUserId(),
]
);
$eventIdList[] = $eventList[0]['RECURRENCE_ID'];
$eventList = array_merge($eventList, $resRelatedEvents);
}
if ($recId)
{
unset($filter['ID']);
$filter['RECURRENCE_ID'] = $recId;
$resRelatedEvents = CCalendarEvent::GetList(
[
'arFilter' => $filter,
'parseRecursion' => true,
'fetchAttendees' => true,
'userId' => CCalendar::GetUserId(),
]
);
foreach($resRelatedEvents as $ev)
{
$eventIdList[] = $ev['ID'];
}
$eventList = array_merge($eventList, $resRelatedEvents);
}
}
}
else if (is_iterable($errors))
{
foreach ($errors as $error)
{
if (is_string($error))
{
$this->addError(new Error($error, 'send_invite_failed'));
}
}
}
$pathToCalendar = CCalendar::GetPathForCalendarEx($userId);
foreach($eventList as $ind => $event)
{
$eventList[$ind]['~URL'] = CHTTP::urlAddParams($pathToCalendar, ['EVENT_ID' => $event['ID']]);
}
$response['eventList'] = $eventList;
$response['eventIdList'] = $eventIdList;
$response['countEventWithEmailGuestAmount'] = Bitrix24Manager::getCountEventWithEmailGuestAmount();
$userSettings = UserSettings::get($userId);
$userSettings['defaultReminders'][$skipTime ? 'fullDay' : 'withTime'] = $reminderList;
UserSettings::set($userSettings, $userId);
return $response;
}