• Модуль: calendar
  • Путь к файлу: ~/bitrix/modules/calendar/lib/controller/calendarentryajax.php
  • Класс: BitrixCalendarControllerCalendarEntryAjax
  • Вызов: CalendarEntryAjax::editEntryAction
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;
}