%PDF- %PDF-
Direktori : /home/bitrix/www/bitrix/modules/messageservice/lib/ |
Current File : //home/bitrix/www/bitrix/modules/messageservice/lib/restservice.php |
<? namespace Bitrix\MessageService; use \Bitrix\Main\Loader; use \Bitrix\Rest\AppTable; use \Bitrix\Rest\RestException; use \Bitrix\Rest\AccessException; Loader::includeModule('rest'); class RestService extends \IRestService { const SCOPE = 'messageservice'; protected static $app; const ERROR_UNSUPPORTED_PROTOCOL = 'ERROR_UNSUPPORTED_PROTOCOL'; const ERROR_WRONG_HANDLER_URL = 'ERROR_WRONG_HANDLER_URL'; const ERROR_HANDLER_URL_MATCH = 'ERROR_HANDLER_URL_MATCH'; const ERROR_SENDER_ALREADY_INSTALLED = 'ERROR_SENDER_ALREADY_INSTALLED'; const ERROR_SENDER_ADD_FAILURE = 'ERROR_SENDER_ADD_FAILURE'; const ERROR_SENDER_VALIDATION_FAILURE = 'ERROR_SENDER_VALIDATION_FAILURE'; const ERROR_SENDER_NOT_FOUND = 'ERROR_SENDER_NOT_FOUND'; const ERROR_MESSAGE_NOT_FOUND = 'ERROR_MESSAGE_NOT_FOUND'; const ERROR_MESSAGE_STATUS_INCORRECT = 'ERROR_MESSAGE_STATUS_INCORRECT'; public static function onRestServiceBuildDescription() { return array(static::SCOPE => array( 'messageservice.sender.add' => array(__CLASS__, 'addSender'), 'messageservice.sender.delete' => array(__CLASS__, 'deleteSender'), 'messageservice.sender.list' => array(__CLASS__, 'getSenderList'), 'messageservice.message.status.update' => array(__CLASS__, 'updateMessageStatus'), )); } /** * @param array $fields Fields describes application. * @return void */ public static function onRestAppDelete(array $fields) { $fields = array_change_key_case($fields, CASE_UPPER); if (empty($fields['APP_ID'])) return; if (!Loader::includeModule('rest')) return; $dbRes = AppTable::getById($fields['APP_ID']); $app = $dbRes->fetch(); if (!$app) return; $iterator = Internal\Entity\RestAppTable::getList(array( 'select' => array('ID'), 'filter' => array('=APP_ID' => $app['CLIENT_ID']) )); while ($row = $iterator->fetch()) { Internal\Entity\RestAppTable::delete($row['ID']); } } /** * @param array $fields Fields describes application. * @return void */ public static function onRestAppUpdate(array $fields) { static::onRestAppDelete($fields); } /** * @param array $params Input params. * @param int $n Offset. * @param \CRestServer $server Rest server instance. * @return bool * @throws \Exception */ public static function addSender($params, $n, $server) { global $USER; if(!$server->getClientId()) { throw new AccessException("Application context required"); } self::checkAdminPermissions(); $params = array_change_key_case($params, CASE_UPPER); self::validateSender($params, $server); $params['APP_ID'] = $server->getClientId(); $iterator = Internal\Entity\RestAppTable::getList(array( 'select' => array('ID'), 'filter' => array( '=APP_ID' => $params['APP_ID'], '=CODE' => $params['CODE'] ) )); $result = $iterator->fetch(); if ($result) { throw new RestException('Sender already installed!', self::ERROR_SENDER_ALREADY_INSTALLED); } $senderLang = array( 'NAME' => $params['NAME'], 'DESCRIPTION' => isset($params['DESCRIPTION']) ? $params['DESCRIPTION'] : '' ); unset($params['NAME'], $params['DESCRIPTION']); $params['AUTHOR_ID'] = $USER->getId(); $result = Internal\Entity\RestAppTable::add($params); if ($result->getErrors()) throw new RestException('Sender save error!', self::ERROR_SENDER_ADD_FAILURE); $senderLang['APP_ID'] = $result->getId(); static::addSenderLang($senderLang, $server->getClientId()); return true; } /** * @param array $params Input params. * @param int $n Offset. * @param \CRestServer $server Rest server instance. * @return bool * @throws \Exception */ public static function deleteSender($params, $n, $server) { if(!$server->getClientId()) { throw new AccessException("Application context required"); } $params = array_change_key_case($params, CASE_UPPER); self::checkAdminPermissions(); self::validateSenderCode($params['CODE']); $params['APP_ID'] = $server->getClientId(); $iterator = Internal\Entity\RestAppTable::getList(array( 'select' => array('ID'), 'filter' => array( '=APP_ID' => $params['APP_ID'], '=CODE' => $params['CODE'] ) )); $result = $iterator->fetch(); if (!$result) { throw new RestException('Sender not found!', self::ERROR_SENDER_NOT_FOUND); } Internal\Entity\RestAppTable::delete($result['ID']); Internal\Entity\RestAppLangTable::deleteByApp($result['ID']); return true; } /** * @param array $params Input params. * @param int $n Offset. * @param \CRestServer $server Rest server instance. * @return array * @throws AccessException * @throws \Bitrix\Main\ArgumentException */ public static function getSenderList($params, $n, $server) { if(!$server->getClientId()) { throw new AccessException("Application context required"); } self::checkAdminPermissions(); $iterator = Internal\Entity\RestAppTable::getList(array( 'select' => array('CODE'), 'filter' => array( '=APP_ID' => $server->getClientId() ) )); $result = array(); while ($row = $iterator->fetch()) { $result[] = $row['CODE']; } return $result; } /** * @param array $params Input params. * @param int $n Offset. * @param \CRestServer $server Rest server instance. * @return bool * @throws AccessException * @throws RestException */ public static function updateMessageStatus($params, $n, $server) { if(!$server->getClientId()) { throw new AccessException("Application context required"); } $params = array_change_key_case($params, CASE_UPPER); static::validateSenderCode($params['CODE']); if (empty($params['MESSAGE_ID'])) { throw new RestException('Message not found!', self::ERROR_MESSAGE_NOT_FOUND); } $statusId = isset($params['STATUS']) ? Sender\Sms\Rest::resolveStatus($params['STATUS']) : null; if ($statusId === null) { throw new RestException('Message status incorrect!', self::ERROR_MESSAGE_STATUS_INCORRECT); } $message = Internal\Entity\MessageTable::getList(array( 'select' => array('ID', 'AUTHOR_ID', 'STATUS_ID'), 'filter' => array( '=SENDER_ID' => 'rest', '=MESSAGE_FROM' => $server->getClientId().'|'.$params['CODE'], '=EXTERNAL_ID' => $params['MESSAGE_ID'] ) ))->fetch(); if (!$message) { throw new RestException('Message not found!', self::ERROR_MESSAGE_NOT_FOUND); } $previousStatusId = (int)$message['STATUS_ID']; if ($previousStatusId === $statusId) { return true; } $authorId = (int)$message['AUTHOR_ID']; if ($authorId !== static::getUserId()) { static::checkAdminPermissions(); } Internal\Entity\MessageTable::update($message['ID'], array('STATUS_ID' => $statusId)); Integration\Pull::onMessagesUpdate(array( array('ID' => $message['ID'], 'STATUS_ID' => $statusId) )); return true; } private static function getUserId() { global $USER; if (isset($USER) && $USER instanceof \CUser) { return (int)$USER->getID(); } return 0; } private static function checkAdminPermissions() { global $USER; if (!isset($USER) || !is_object($USER) || (!$USER->isAdmin() && !(Loader::includeModule('bitrix24') && \CBitrix24::isPortalAdmin($USER->getID()))) ) { throw new AccessException(); } } private static function validateSender($data, $server) { if (!is_array($data) || empty($data)) throw new RestException('Empty data!', self::ERROR_SENDER_VALIDATION_FAILURE); static::validateSenderCode($data['CODE']); static::validateSenderHandler($data['HANDLER'], $server); if (empty($data['NAME'])) throw new RestException('Empty sender NAME!', self::ERROR_SENDER_VALIDATION_FAILURE); if (empty($data['TYPE'])) throw new RestException('Empty sender message TYPE!', self::ERROR_SENDER_VALIDATION_FAILURE); if (!in_array($data['TYPE'], array('SMS'), true)) throw new RestException('Unknown sender message TYPE!', self::ERROR_SENDER_VALIDATION_FAILURE); } private static function validateSenderCode($code) { if (empty($code)) throw new RestException('Empty sender code!', self::ERROR_SENDER_VALIDATION_FAILURE); if (!preg_match('#^[a-z0-9\.\-_]+$#i', $code)) throw new RestException('Wrong sender code!', self::ERROR_SENDER_VALIDATION_FAILURE); } private static function validateSenderHandler($handler, $server) { $handlerData = parse_url($handler); if (is_array($handlerData) && strlen($handlerData['host']) > 0 && strpos($handlerData['host'], '.') > 0 ) { if ($handlerData['scheme'] == 'http' || $handlerData['scheme'] == 'https') { $host = $handlerData['host']; $app = self::getApp($server); if (strlen($app['URL']) > 0) { $urls = array($app['URL']); if (strlen($app['URL_DEMO']) > 0) { $urls[] = $app['URL_DEMO']; } if (strlen($app['URL_INSTALL']) > 0) { $urls[] = $app['URL_INSTALL']; } $found = false; foreach($urls as $url) { $a = parse_url($url); if ($host == $a['host'] || $a['host'] == 'localhost') { $found = true; break; } } if(!$found) { throw new RestException('Handler URL host doesn\'t match application url', self::ERROR_HANDLER_URL_MATCH); } } } else { throw new RestException('Unsupported event handler protocol', self::ERROR_UNSUPPORTED_PROTOCOL); } } else { throw new RestException('Wrong handler URL', self::ERROR_WRONG_HANDLER_URL); } } /** * @param \CRestServer $server * @return array|bool|false|mixed|null * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\LoaderException */ private static function getApp($server) { if(self::$app == null) { if (Loader::includeModule('rest')) { $result = AppTable::getList( array( 'filter' => array( '=CLIENT_ID' => $server->getClientId() ) ) ); self::$app = $result->fetch(); } } return self::$app; } private static function addSenderLang($langFields, $clientId) { $langData = array(); if (!is_array($langFields['NAME'])) { $langData['**'] = array( 'APP_ID' => $langFields['APP_ID'], 'LANGUAGE_ID' => '**', 'NAME' => $langFields['NAME'], 'DESCRIPTION' => is_scalar($langFields['DESCRIPTION']) ? (string)$langFields['DESCRIPTION'] : null ); } else { foreach ($langFields['NAME'] as $langId => $langName) { $langData[strtolower($langId)] = array( 'APP_ID' => $langFields['APP_ID'], 'LANGUAGE_ID' => strtolower($langId), 'NAME' => $langFields['NAME'][$langId], 'DESCRIPTION' => is_array($langFields['DESCRIPTION']) && isset($langFields['DESCRIPTION'][$langId]) ? (string)$langFields['DESCRIPTION'][$langId] : null ); if (!isset($langData['**'])) { $langData['**'] = array( 'APP_ID' => $langFields['APP_ID'], 'LANGUAGE_ID' => '**', 'NAME' => $langFields['NAME'][$langId], 'DESCRIPTION' => is_array($langFields['DESCRIPTION']) && isset($langFields['DESCRIPTION'][$langId]) ? (string)$langFields['DESCRIPTION'][$langId] : null ); } } } $appNames = static::getAppNames($clientId); foreach ($appNames as $langId => $appName) { if (isset($langData[$langId])) { $langData[$langId]['APP_NAME'] = $appName; } } foreach ($langData as $toAdd) { Internal\Entity\RestAppLangTable::add($toAdd); } } private static function getAppNames($clientId) { $iterator = \Bitrix\Rest\AppTable::getList( array( 'filter' => array( '=CLIENT_ID' => $clientId ), 'select' => array('ID', 'APP_NAME', 'CODE'), ) ); $app = $iterator->fetch(); $result = array( '**' => $app['APP_NAME'] ? $app['APP_NAME'] : $app['CODE'] ); $orm = \Bitrix\Rest\AppLangTable::getList(array( 'filter' => array( '=APP_ID' => $app['ID'] ), 'select' => array('LANGUAGE_ID', 'MENU_NAME') )); while ($row = $orm->fetch()) { $result[strtolower($row['LANGUAGE_ID'])] = $row['MENU_NAME']; } if (isset($result[LANGUAGE_ID])) { $result['**'] = $result[LANGUAGE_ID]; } return $result; } }