• Модуль: calendar
  • Путь к файлу: ~/bitrix/modules/calendar/classes/general/calendar_sync.php
  • Класс: CCalendarSync
  • Вызов: CCalendarSync::SaveExternalEvents
static function SaveExternalEvents(array $externalEvents, array $localEvents, $localCalendar): void
{
	foreach ($externalEvents as $externalEvent)
	{
		$eventExists = !empty($localEvents[$externalEvent['G_EVENT_ID']]);
		// find parent event
		if (
			isset($externalEvent['recurringEventId'])
			&& $externalEvent['isRecurring'] === 'Y'
			&& !isset($localEvents[$externalEvent['recurringEventId']])
		)
		{
			$parentEvent = self::getLocalEventsList($localCalendar, [$externalEvent['recurringEventId']]);
			if (!empty($parentEvent))
			{
				$localEvents[$externalEvent['recurringEventId']] = $parentEvent[$externalEvent['recurringEventId']];
			}
		}

		// delete events
		if ($externalEvent['status'] === 'cancelled')
		{
			$originalEvent = $localEvents[$externalEvent['G_EVENT_ID']];

			// event exists
			if ($eventExists)
			{
				if (!empty($externalEvents[$externalEvent['recurringEventId']])
					&& $externalEvents[$externalEvent['recurringEventId']]['status'] === 'cancelled'
					&& !empty($localEvents[$externalEvent['recurringEventId']])
					&& (int)$originalEvent['ID'] === (int)$originalEvent['PARENT_ID']
				)
				{
					CCalendarEvent::Delete([
						'id' => $localEvents[$externalEvent['recurringEventId']]['ID'],
						'bMarkDeleted' => true,
						'Event' => $localEvents[$externalEvent['recurringEventId']],
						'userId' => $localCalendar['OWNER_ID'],
						'sendNotification' => false
					]);
				}

				if (!empty($localEvents[$externalEvent['G_EVENT_ID']]['IS_MEETING']) && $localEvents[$externalEvent['G_EVENT_ID']]['IS_MEETING'])
				{
					self::$doNotSendToGoogle = false;
				}

				//if host single event then delete instance and  change meeting status if invitation
				if ((int)$originalEvent['ID'] !== (int)$originalEvent['PARENT_ID'])
				{
					CCalendarEvent::SetMeetingStatus([
						'userId' => (int)$originalEvent['OWNER_ID'],
						'eventId' => (int)$originalEvent['ID'],
						'status' => 'N',
						'personalNotification' => true
					]);
				}
				else // delete event
				{
					CCalendarEvent::Delete([
						'id' => $originalEvent['ID'],
						'bMarkDeleted' => true,
						'Event' => $originalEvent,
						'userId' => $localCalendar['OWNER_ID'],
						'sendNotification' => false
					]);
				}

				if (!empty($originalEvent['IS_MEETING']) && $originalEvent['IS_MEETING'])
				{
					self::$doNotSendToGoogle = true;
				}

				// enumeration local instances and change status if invitation or delete if host instance
				foreach ($localEvents as $localEvent)
				{
					if (
						!empty($localEvent['RECURRENCE_ID'])
						&& $localEvent['RECURRENCE_ID'] === $originalEvent['ID']
					)
					{
						if ((int)$localEvent['ID'] !== (int)$localEvent['PARENT_ID'])
						{
							CCalendarEvent::SetMeetingStatus([
								'userId' => (int)$localEvent['OWNER_ID'],
								'eventId' => (int)$localEvent['ID'],
								'status' => 'N',
								'personalNotification' => true
							]);
						}
						else
						{
							CCalendarEvent::Delete([
								'id' => $localEvent['ID'],
								'bMarkDeleted' => true,
								'Event' => $localEvent,
								'userId' => $localCalendar['OWNER_ID'],
								'sendNotification' => false
							]);
						}
					}
				}
			}
			elseif (!empty($externalEvent['recurringEventId'])
				&& !empty($localEvents[$externalEvent['recurringEventId']])
				&& $externalEvent['isRecurring'] === 'Y'
			) // update parent event exdate
			{
				$excludeDates = CCalendarEvent::GetExDate($localEvents[$externalEvent['recurringEventId']]['EXDATE']);
				$excludeDates[] = $externalEvent['EXDATE'];
				$localEvents[$externalEvent['recurringEventId']]['EXDATE'] = implode(';', $excludeDates);

				$newParentData = [
					'arFields' => $localEvents[$externalEvent['recurringEventId']],
					'userId' => $localCalendar['OWNER_ID'],
					'fromWebservice' => true
				];

				$newParentData['arFields']['EXDATE'] = CCalendarEvent::SetExDate($excludeDates);
				$newParentData['arFields']['RRULE'] = CCalendarEvent::ParseRRULE($newParentData['arFields']['RRULE']);
				CCalendar::SaveEvent($newParentData);
			}
			continue;
		}

		// handle single or recurrence events
		if ($externalEvent['isRecurring'] === "N")
		{
			//new event
			if (!$eventExists)
			{
				$newEventData = array_merge(
					$externalEvent,
					[
						'SECTIONS' => [$localCalendar['ID']],
						'OWNER_ID' => $localCalendar['OWNER_ID'],
						'userId' => $localCalendar['OWNER_ID']
					]
				);

				$newEvent = $newEventData;
				$newEvent['ID'] = CCalendarEvent::Edit(['arFields' => $newEventData, 'path' => CCalendar::GetPath('user', $newEventData['OWNER_ID'])]);
				$localEvents[$externalEvent['DAV_XML_ID']] = $newEvent;
			}
			else // event exists
			{
				$newParentData = [
					'arFields' => array_merge([
						'ID' => $localEvents[$externalEvent['G_EVENT_ID']]['ID'],
						'MEETING' => $localEvents[$externalEvent['G_EVENT_ID'] . '@google.com']['MEETING'],
					], $externalEvent),
					'userId' => $localCalendar['OWNER_ID'],
					'fromWebservice' => true
				];

				// update do not sync with google
				if (!empty($localEvents[$externalEvent['G_EVENT_ID']]['IS_MEETING']) && $localEvents[$externalEvent['G_EVENT_ID']]['IS_MEETING'])
				{
					self::$doNotSendToGoogle = false;
				}

				if (empty($newParentData['arFields']['MEETING']['LANGUAGE_ID']))
				{
					$newParentData['arFields']['MEETING']['LANGUAGE_ID'] = CCalendar::getUserLanguageId((int)$newParentData['arFields']['OWNER_ID']);
				}

				$newParentData['arFields']['DESCRIPTION'] = self::CutAttendeesFromDescription(
					$newParentData['arFields']['DESCRIPTION'],
					self::getAttendeesCodesForCut($localEvents[$externalEvent['G_EVENT_ID']]['ATTENDEES_CODES'] ?? null),
					$newParentData['arFields']['MEETING']['LANGUAGE_ID']
				);

				$newParentData['dontSyncParent'] = true;
				$newParentData['arFields']['SYNC_STATUS'] = GoogleDictionary::SYNC_STATUS['success'];

				CCalendar::SaveEvent($newParentData);

				if (!empty($localEvents[$externalEvent['G_EVENT_ID']]['IS_MEETING']) && $localEvents[$externalEvent['G_EVENT_ID']]['IS_MEETING'])
				{
					self::$doNotSendToGoogle = true;
				}
			}
		}
		elseif ($externalEvent['isRecurring'] === "Y") // is instance
		{
			// change time
			if ($externalEvent['status'] === 'confirmed' && $externalEvent['hasMoved'] === "Y")
			{
				// find parent event
				$recurrentParentEventExists = !empty($localEvents[$externalEvent['recurringEventId']]);
				if (empty($recurrentParentEventExists))
				{
//						$parentGEventId = str_replace('@google.com', '',  $externalEvent['recurringEventId']);
					$parentEvent = self::getLocalEventsList($localCalendar, [$externalEvent['recurringEventId']]);
					if (!empty($parentEvent))
					{
						$localEvents[$externalEvent['recurringEventId']] = $parentEvent[$externalEvent['recurringEventId']];
						$recurrentParentEventExists = $parentEvent[$externalEvent['recurringEventId']];
					}
				}

				// update exdate to parent event
				if ($recurrentParentEventExists)
				{
					$recurrenceId = NULL;

					if ($localEvents[$externalEvent['recurringEventId']])
					{
						$recurrenceId = $localEvents[$externalEvent['recurringEventId']]['ID'];

						$excludeDates = CCalendarEvent::GetExDate($localEvents[$externalEvent['recurringEventId']]['EXDATE']);
						$excludeDates[] = $externalEvent['EXDATE'];
						$localEvents[$externalEvent['recurringEventId']]['EXDATE'] = implode(';', $excludeDates);
						$newParentData = [
							'arFields' => $localEvents[$externalEvent['recurringEventId']],
							'userId' => $localCalendar['OWNER_ID'],
							'fromWebservice' => true
						];

						$newParentData['arFields']['EXDATE'] = CCalendarEvent::SetExDate($excludeDates);
						$newParentData['arFields']['RRULE'] = CCalendarEvent::ParseRRULE($newParentData['arFields']['RRULE']);
						$newParentData['arFields']['SYNC_STATUS'] = GoogleDictionary::SYNC_STATUS['success'];

						$newParentData['sync'] = true;

						CCalendar::SaveEvent($newParentData);
					}


					// find meeting field in instance exists or parent event
					if (empty($externalEvent['MEETING']))
					{
						$externalEvent['MEETING'] = !empty($localEvents[$externalEvent['G_EVENT_ID'] . '@google.com']['MEETING'])
							? $localEvents[$externalEvent['G_EVENT_ID'] . '@google.com']['MEETING']
							: $localEvents[$externalEvent['DAV_XML_ID']]['MEETING'];
					}

					// set lang id
					if (empty($externalEvent['MEETING']['LANGUAGE_ID']))
					{
						$externalEvent['MEETING']['LANGUAGE_ID'] = CCalendar::getUserLanguageId((int)$externalEvent['OWNER_ID']);
					}

					// handle description
					if (isset($externalEvent['DESCRIPTION']))
					{
						$externalEvent['DESCRIPTION'] = self::CutAttendeesFromDescription(
							$externalEvent['DESCRIPTION'],
							self::getAttendeesCodesForCut($localEvents[$externalEvent['recurringEventId']]['ATTENDEES_CODES'] ?? null),
							$externalEvent['MEETING']['LANGUAGE_ID']
						);
					}

					// save instance
					CCalendar::SaveEvent([
						'arFields' => array_merge($externalEvent, [
							'RECURRENCE_ID' => $recurrenceId,
							'DATE_FROM' => $externalEvent['DATE_FROM'],
							'SECTIONS' => [$localCalendar['ID']],
							'DATE_TO' => $externalEvent['DATE_TO'],
							'SYNC_STATUS' => GoogleDictionary::SYNC_STATUS['success'],
							'ATTENDEES' => !empty($localEvents[$externalEvent['G_EVENT_ID']]['ATTENDEES'])
								? $localEvents[$externalEvent['G_EVENT_ID']]['ATTENDEES']
								: $localEvents[$externalEvent['DAV_XML_ID']]['ATTENDEES'],
							'ATTENDEES_CODES' => !empty($localEvents[$externalEvent['G_EVENT_ID']]['ATTENDEES_CODES'])
								? $localEvents[$externalEvent['G_EVENT_ID']]['ATTENDEES_CODES']
								: $localEvents[$externalEvent['DAV_XML_ID']]['ATTENDEES_CODES'],
							'IS_MEETING' => !empty($localEvents[$externalEvent['G_EVENT_ID']]['IS_MEETING'])
								? $localEvents[$externalEvent['G_EVENT_ID']]['IS_MEETING']
								: $localEvents[$externalEvent['DAV_XML_ID']]['IS_MEETING'],
							'MEETING_STATUS' => !empty($localEvents[$externalEvent['G_EVENT_ID']]['MEETING_STATUS'])
								? $localEvents[$externalEvent['G_EVENT_ID']]['MEETING_STATUS']
								: $localEvents[$externalEvent['DAV_XML_ID']]['MEETING_STATUS'],
						]),
						'userId' => $localCalendar['OWNER_ID'],
						'fromWebservice' => true,
						'sync' => true,
					]);
				}
			}
		}
	}
}