• Модуль: rest
  • Путь к файлу: ~/bitrix/modules/rest/lib/preset/provider.php
  • Класс: BitrixRestPresetProvider
  • Вызов: Provider::saveIntegration
static function saveIntegration($requestData, $elementCode = '', $id = 0)
{
	global $USER;
	$result = [
		'status' => true,
	];
	$itemsEvent = [];
	$errorList = [];
	$id = (isset($requestData['ID']) && intVal($requestData['ID']) > 0) ? intVal($requestData['ID']) : $id;
	$userId = $GLOBALS['USER']->getID();
	$isAdmin = CRestUtil::isAdmin();

	$presetData = Element::get($elementCode);

	if (
		!$isAdmin
		&&
		(
			$presetData['ADMIN_ONLY'] === 'Y'
			|| $presetData['OPTIONS']['WIDGET_NEEDED'] !== 'D'
			|| $presetData['OPTIONS']['APPLICATION_NEEDED'] !== 'D'
		)
	)
	{
		$result['status'] = false;
		$result['errors'][] = Loc::getMessage('INTEGRATION_PRESET_PROVIDER_ERROR_ACCESS_DENIED');
		return $result;
	}

	if (!OAuthService::getEngine()->isRegistered())
	{
		try
		{
			OAuthService::register();
			OAuthService::getEngine()->getClient()->getApplicationList();
		}
		catch (SystemException $e)
		{
			$result['status'] = false;
			$result['errors'][] = $e->getCode() . ': ' . $e->getMessage();
			return $result;
		}
	}

	$presetData = $presetData['OPTIONS'];

	$saveData = [
		'ELEMENT_CODE' => $elementCode,
		'USER_ID' => $USER->GetID(),
		'TITLE' => $requestData['TITLE'],
		'SCOPE' => is_array($requestData['SCOPE']) ? $requestData['SCOPE'] : [],
		'QUERY' => $requestData['QUERY'],
		'OUTGOING_HANDLER_URL' => trim($requestData['OUTGOING_HANDLER_URL'] ?? null),
		'OUTGOING_EVENTS' => is_array($requestData['OUTGOING_EVENTS']) ? $requestData['OUTGOING_EVENTS'] : [],
		'APPLICATION_ONLY_API' => (isset($requestData['APPLICATION_ONLY_API']) && $requestData['APPLICATION_ONLY_API'] === 'Y') ? 'Y' : 'N',
		'APPLICATION_NEEDED' => (isset($requestData['APPLICATION_NEEDED']) && $requestData['APPLICATION_NEEDED'] === 'Y') ? 'Y' : 'N',
		'APPLICATION_EVENTS' => (isset($requestData['APPLICATION_EVENTS']) && is_array($requestData['APPLICATION_EVENTS'])) ? $requestData['APPLICATION_EVENTS'] : [],
		'OUTGOING_NEEDED' => ($requestData['OUTGOING_NEEDED'] === 'Y') ? 'Y' : 'N',
		'WIDGET_NEEDED' => ($requestData['WIDGET_NEEDED'] === 'Y') ? 'Y' : 'N',
		'WIDGET_HANDLER_URL' => trim($requestData['WIDGET_HANDLER_URL'] ?? null),
		'WIDGET_LIST' => $requestData['WIDGET_LIST'],
		'WIDGET_LANG_LIST' => (isset($requestData['WIDGET_LANG_LIST']) && is_array($requestData['WIDGET_LANG_LIST'])) ? $requestData['WIDGET_LANG_LIST'] : [],
		'BOT_HANDLER_URL' => trim($requestData['BOT_HANDLER_URL'] ?? null)
	];

	if ($id > 0)
	{
		$itemsEvent = EventTable::getList(
			[
				'filter' => [
					'=INTEGRATION_ID' => $id
				]
			]
		)->fetchAll();
	}

	if (!empty($itemsEvent['0']['APPLICATION_TOKEN']))
	{
		$saveData['APPLICATION_TOKEN'] = $itemsEvent['0']['APPLICATION_TOKEN'];
	}
	else
	{
		$saveData['APPLICATION_TOKEN'] = Random::getString(32);
	}

	$isAdd = false;
	if ($id == 0)
	{
		$saveResult = IntegrationTable::add($saveData);
		$isAdd = true;
		$id = $saveResult->getId();
		if (!$result['status'] = $saveResult->isSuccess())
		{
			$errorList = $saveResult->getErrorMessages();
		}
	}

	if ($id > 0 || $result['status'])
	{
		EventController::disableEvents();
		if (!empty($saveData['TITLE']))
		{
			$title = $saveData['TITLE'];
		}
		else
		{
			$title = Loc::getMessage('INTEGRATION_PRESET_PROVIDER_TITLE_PREFIX', ['#ID#' => $id]);
		}

		if (!$isAdd)
		{
			$resIntegration = IntegrationTable::getList(
				[
					'filter' => [
						'ID' => $id
					]
				]
			);
			if ($integrationData = $resIntegration->fetch())
			{
				if (!$isAdmin && $integrationData['USER_ID'] != $userId)
				{
					$result['status'] = false;
					$result['errors'][] = Loc::getMessage('INTEGRATION_PRESET_PROVIDER_ERROR_ACCESS_DENIED');
					return $result;
				}
				if ($integrationData['PASSWORD_ID'] > 0 && ($requestData['MODE'] === 'GEN_SAVE' || $integrationData['USER_ID'] != $userId))
				{
					Analytic::logToFile(
						'integrationRegen',
						'integration' . $integrationData['ID'],
						$integrationData['ELEMENT_CODE'],
						'code'
					);
					if (static::deleteWebHook($integrationData['PASSWORD_ID']))
					{
						$integrationData['PASSWORD_ID'] = 0;
					}
					else
					{
						$result['status'] = false;
						$errorList[] = Loc::getMessage('INTEGRATION_PRESET_PROVIDER_ERROR_DELETE_WEBHOOK');
						return $result;
					}
				}

				$saveData = array_merge($integrationData, $saveData);
			}
			//bot on webhooks
			if ($presetData['BOT_NEEDED'] !== 'D' && Loader::includeModule('im'))
			{
				if (!empty($requestData['BOT_NAME']) && !empty($requestData['BOT_HANDLER_URL']))
				{
					$botId = 0;
					$allEvents = [
						'onImBotMessageAdd',
						'onImBotJoinChat',
						'onImBotDelete',
						'onImBotMessageUpdate',
						'onImBotMessageDelete'
					];
					$params = [
						'TYPE' => $requestData['BOT_TYPE'],
						'EVENT_MESSAGE_ADD' => $saveData['BOT_HANDLER_URL'],
						'EVENT_WELCOME_MESSAGE' => $saveData['BOT_HANDLER_URL'],
						'EVENT_BOT_DELETE' => $saveData['BOT_HANDLER_URL'],
						'MODULE_ID' => 'rest',
						'PROPERTIES' => [
							'NAME' => $requestData['BOT_NAME']
						]
					];

					if ($integrationData['BOT_ID'] > 0)
					{
						$res = BotTable::getList(
							[
								'filter' => [
									'=BOT_ID' => $integrationData['BOT_ID'],
								]
							]
						);
						if ($bot = $res->fetch())
						{
							$params = array_merge($bot, $params);
						}
					}
					$clientId = $params['APP_ID'];
					if (!$params['APP_ID'])
					{
						$clientId = Random::getString(32);
						$params['APP_ID'] = 'custom' . $clientId;
						$params['CODE'] = Random::getString(16);
					}
					elseif (mb_stripos($clientId, 'custom') === 0)
					{
						$clientId = mb_substr($clientId, 6);
					}

					$uriWithClientId = $saveData['BOT_HANDLER_URL']
						. (mb_strpos($saveData['BOT_HANDLER_URL'], '?') === false ? '?' : '&')
						. 'CLIENT_ID=' . $clientId;
					$events = [
						'onImBotMessageAdd' => $uriWithClientId,
						'onImBotJoinChat' => $uriWithClientId,
						'onImBotDelete' => $uriWithClientId,
					];
					if (in_array($requestData['BOT_TYPE'], ['S', 'O']))
					{
						$events['onImBotMessageUpdate'] = $uriWithClientId;
						$events['onImBotMessageDelete'] = $uriWithClientId;
						$params['EVENT_MESSAGE_UPDATE'] = $uriWithClientId;
						$params['EVENT_MESSAGE_DELETE'] = $uriWithClientId;
					}

					if ($integrationData['BOT_ID'] > 0)
					{
						if (Bot::update(['BOT_ID' => $integrationData['BOT_ID']], $params) ===	true)
						{
							$botId = $integrationData['BOT_ID'];
						}
					}
					else
					{
						$botId = Bot::register($params);
					}

					if ($botId > 0)
					{
						$allEvents = array_change_key_case(array_combine($allEvents, $allEvents), CASE_UPPER);
						$saveData['BOT_ID'] = $botId;
						if ($integrationData['BOT_ID'] > 0)
						{
							$res = EventTable::getList(
								[
									'filter' => [
										'=APP_ID' => '',
										'=EVENT_NAME' => array_keys($allEvents),
										'=APPLICATION_TOKEN' => [
											$clientId,
											$params['APP_ID'],
										],
									],
									'select' => [
										'ID',
										'EVENT_NAME',
										'EVENT_HANDLER'
									]
								]
							);
							while ($event = $res->fetch())
							{
								if (isset($events[$allEvents[$event['EVENT_NAME']]]) &&
									$event['EVENT_HANDLER'] === $events[$allEvents[$event['EVENT_NAME']]])
								{
									unset($events[$allEvents[$event['EVENT_NAME']]]);
								}
								else
								{
									EventTable::delete($event['ID']);
								}
							}
						}
						if ($params['APP_ID'])
						{
							foreach ($events as $event => $eventHandler)
							{
								$res = EventTable::add(
									[
										'APP_ID' => '',
										'EVENT_NAME' => toUpper($event),
										'EVENT_HANDLER' => $eventHandler,
										'APPLICATION_TOKEN' => $clientId,
										'USER_ID' => 0,
									]
								);
								if ($result['status'] = $res->isSuccess())
								{
									Sender::bind('im', $event);
								}
								else
								{
									$errors = $res->getErrorMessages();
									if (is_array($errors))
									{
										$errorList = array_merge($errorList, $errors);
									}
									break;
								}
							}
						}
					}
					else
					{
						$errorList[] = Loc::getMessage('INTEGRATION_PRESET_PROVIDER_ERROR_BOT_CREATE');
					}
				}
				else
				{
					$errorList[] = Loc::getMessage(
						'INTEGRATION_PRESET_PROVIDER_ERROR_BOT_REQUIRED_FIELD_EMPTY'
					);
				}
			}
		}

		if (!isset($presetData['QUERY_NEEDED']) || $presetData['QUERY_NEEDED'] !== 'D')
		{
			$webhook = static::getWebHook($saveData['SCOPE'], $saveData['PASSWORD_ID'] ?? null, $title);
			$saveData['PASSWORD_ID'] = $webhook['ID'];
		}

		if (
			$presetData['OUTGOING_NEEDED'] !== 'D'
			&& !empty($saveData['OUTGOING_HANDLER_URL'])
			&& !empty($saveData['OUTGOING_EVENTS'])
			&& $saveData['OUTGOING_NEEDED'] == 'Y'
		)
		{
			$eventAddList = [];
			$eventUpdateList = [];
			if (!empty($itemsEvent))
			{
				$itemsEvent = array_column($itemsEvent, null, 'EVENT_NAME');
			}

			foreach ($saveData['OUTGOING_EVENTS'] as $event)
			{
				if ($itemsEvent[$event])
				{
					$eventUpdateList[] = $itemsEvent[$event]['ID'];
					unset($itemsEvent[$event]);
				}
				else
				{
					$eventAddList[] = [
						'TITLE' => $title,
						'EVENT_NAME' => $event,
						'EVENT_HANDLER' => $saveData['OUTGOING_HANDLER_URL'],
						'USER_ID' => $userId,
						'DATE_CREATE' => new DateTime(),
						'APPLICATION_TOKEN' => $saveData['APPLICATION_TOKEN'],
						'INTEGRATION_ID' => $saveData['ID']
					];
				}
			}

			foreach ($itemsEvent as $event)
			{
				EventTable::delete($event['ID']);
			}

			foreach ($eventAddList as $item)
			{
				$res = EventTable::add($item);
				if (!$result['status'] = $res->isSuccess())
				{
					$errors = $res->getErrorMessages();
					if (is_array($errors))
					{
						$errorList = array_merge($errorList, $errors);
					}
					break;
				}
			}

			if ($result['status'] && !empty($eventUpdateList))
			{
				$res = EventTable::updateMulti(
					$eventUpdateList,
					[
						'TITLE' => $title,
						'EVENT_HANDLER' => $saveData['OUTGOING_HANDLER_URL'],
						'USER_ID' => $userId,
						'APPLICATION_TOKEN' => $saveData['APPLICATION_TOKEN'],
					]
				);
				if (!$result['status'] = $res->isSuccess())
				{
					$errors = $res->getErrorMessages();
					if (is_array($errors))
					{
						$errorList = array_merge($errorList, $errors);
					}
				}
			}
		}
		else
		{
			foreach ($itemsEvent as $event)
			{
				EventTable::delete($event['ID']);
			}
		}

		if (
			$presetData['WIDGET_NEEDED'] !== 'D'
			&& $saveData['WIDGET_NEEDED'] == 'Y'
			&& !empty($saveData['WIDGET_HANDLER_URL'])
			&& is_array($saveData['WIDGET_LIST'])
		)
		{
			$app = static::saveApp(
				[
					'ID' => $saveData['APP_ID'],
					'FIELDS' => [
						'URL' => $saveData['WIDGET_HANDLER_URL'],
						'URL_INSTALL' => $saveData['WIDGET_HANDLER_URL'],
						'SCOPE' => $saveData['SCOPE'],
						'ONLY_API' => 'Y',
						'MOBILE' => 'N',
						'APP_NAME' => $saveData['TITLE'],
					],
					'PLACEMENTS' => $saveData['WIDGET_LIST'],
					'PLACEMENTS_LANG_LIST' => $saveData['WIDGET_LANG_LIST'],
					'PLACEMENT_HANDLER_URL' => $saveData['WIDGET_HANDLER_URL'],
					'INTEGRATION_CODE' => $saveData['ELEMENT_CODE'],
					'INTEGRATION_ID' => $saveData['ID']
				]
			);
			if ($app['ID'] > 0)
			{
				$saveData['APP_ID'] = $app['ID'];
			}

			if (!empty($app['errors']))
			{
				$errorList = array_merge($errorList, $app['errors']);
			}
		}
		elseif (
			$presetData['APPLICATION_NEEDED'] !== 'D'
			&& $saveData['APPLICATION_NEEDED'] == 'Y'
		)
		{
			$app = static::saveApp(
				[
					'ID' => $saveData['APP_ID'],
					'FIELDS' => [
						'URL' => trim($requestData['APPLICATION_URL_HANDLER']),
						'URL_INSTALL' => trim($requestData['APPLICATION_URL_INSTALL']),
						'SCOPE' => $saveData['SCOPE'],
						'ONLY_API' => ($saveData['APPLICATION_ONLY_API'] == 'Y') ? 'Y' : 'N',
						'MOBILE' => ($saveData['APPLICATION_ONLY_API'] != 'Y'
							&& $requestData['APPLICATION_MOBILE'] === 'Y') ? 'Y' : 'N',
						'APP_NAME' => $saveData['TITLE'],
					],
					'LANG_NAME' => ($saveData['APPLICATION_ONLY_API'] != 'Y' && is_array($requestData['APPLICATION_LANG_NAME'])) ?
										$requestData['APPLICATION_LANG_NAME']
										:
										[],
					'INTEGRATION_CODE' => $saveData['ELEMENT_CODE'],
					'INTEGRATION_ID' => $saveData['ID']
				]
			);

			if ($app['ID'] > 0)
			{
				$saveData['APP_ID'] = $app['ID'];
			}

			if (!empty($app['errors']))
			{
				$errorList = array_merge($errorList, $app['errors']);
			}
		}
		elseif (isset($saveData['APP_ID']) && $saveData['APP_ID'] > 0)
		{
			$res = AppTable::getList(
				[
					'filter' => [
						'=ID' => $saveData['APP_ID']
					]
				]
			);
			if ($app = $res->fetch())
			{
				AppTable::delete($app['ID']);
			}
			$placementList = PlacementTable::getList(
				[
					'filter' => [
						'=APP_ID' => $app['ID']
					]
				]
			)->fetchAll();
			if (is_array($placementList))
			{
				foreach ($placementList as $placement)
				{
					PlacementTable::delete($placement['ID']);
				}
			}
		}

		$resultSave = IntegrationTable::update($id, $saveData);
		if (!$resultSave->isSuccess())
		{
			$errors = $resultSave->getErrorMessages();
			if (is_array($errors))
			{
				$errorList = array_merge($errorList, $errors);
			}
		}

		EventController::enableEvents();
	}

	$result['ID'] = $id;
	if (!empty($errorList))
	{
		$result['status'] = false;
		$result['errors'] = $errorList;
	}
	BitrixRestEngineAccess::getActiveEntity(true);

	return $result;
}