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;
}