PageRenderTime 28ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/b24connector/lib/connection.php

https://gitlab.com/alexprowars/bitrix
PHP | 455 lines | 302 code | 74 blank | 79 comment | 50 complexity | 6cd8971368f320c87e0cdd39f9f8fc09 MD5 | raw file
  1. <?
  2. namespace Bitrix\B24Connector;
  3. use Bitrix\Main\Error;
  4. use Bitrix\Main\Loader;
  5. use Bitrix\Main\Result;
  6. use Bitrix\Main\Config\Option;
  7. use Bitrix\Main\Localization\Loc;
  8. use Bitrix\Socialservices\ApClient;
  9. use Bitrix\Socialservices\ApTable;
  10. Loc::loadMessages(__FILE__);
  11. /**
  12. * Class Connection
  13. * @package Bitrix\B24Connector
  14. */
  15. class Connection
  16. {
  17. const DEFAULT_CACHE_TTL = 3600;
  18. /**
  19. * @return bool|string
  20. * @throws \Bitrix\Main\LoaderException
  21. */
  22. private static function getAppId()
  23. {
  24. if(!Loader::includeModule('socialservices'))
  25. return '';
  26. if(!self::isLinkedToNet())
  27. self::linkToNet();
  28. $interface = new \CBitrix24NetOAuthInterface();
  29. return $interface->getAppID();
  30. }
  31. /**
  32. * Link site to Bitrix24.Network
  33. * Code borrowed from socialservices/options.php
  34. * @throws \Bitrix\Main\ArgumentNullException
  35. * @throws \Bitrix\Main\LoaderException
  36. *
  37. */
  38. private static function linkToNet()
  39. {
  40. if(!Loader::includeModule('socialservices'))
  41. return false;
  42. if(self::isLinkedToNet())
  43. return true;
  44. $result = false;
  45. $request = \Bitrix\Main\Context::getCurrent()->getRequest();
  46. $host = ($request->isHttps() ? 'https://' : 'http://').$request->getHttpHost();
  47. $registerResult = \CSocServBitrix24Net::registerSite($host);
  48. if(is_array($registerResult) && isset($registerResult["client_id"]) && isset($registerResult["client_secret"]))
  49. {
  50. Option::set('socialservices', 'bitrix24net_domain', $host);
  51. Option::set('socialservices', 'bitrix24net_id', $registerResult["client_id"]);
  52. Option::set('socialservices', 'bitrix24net_secret', $registerResult["client_secret"]);
  53. $result = true;
  54. }
  55. return $result;
  56. }
  57. /**
  58. * @return bool
  59. * @throws \Bitrix\Main\ArgumentNullException
  60. */
  61. private static function isLinkedToNet()
  62. {
  63. return Option::get('socialservices', 'bitrix24net_id', '') !== '';
  64. }
  65. /**
  66. * @return Result
  67. * @throws \Bitrix\Main\ArgumentException
  68. * @throws \Bitrix\Main\LoaderException
  69. * @throws \Exception
  70. */
  71. public static function delete()
  72. {
  73. $result = new Result();
  74. if(!Loader::includeModule('socialservices'))
  75. {
  76. $result->addError(new Error('Module socialservices is not installed'));
  77. return $result;
  78. }
  79. if($connection = self::getFields())
  80. {
  81. $res = ApTable::delete($connection['ID']);
  82. if(!$res->isSuccess())
  83. $result->addErrors($res->getErrors());
  84. $dbRes = ButtonTable::getList(array(
  85. 'filter' => array(
  86. '=APP_ID' => $connection['ID']
  87. )
  88. ));
  89. while($but = $dbRes->fetch())
  90. {
  91. $res = ButtonTable::delete($but['ID']);
  92. if(!$res->isSuccess())
  93. $result->addErrors($res->getErrors());
  94. }
  95. }
  96. return $result;
  97. }
  98. /**
  99. * @param string $title Button title
  100. * @return string Button HTML.
  101. * @throws \Bitrix\Main\LoaderException
  102. * @throws \Bitrix\Main\ArgumentNullException
  103. */
  104. public static function getButtonHtml($title = '')
  105. {
  106. global $APPLICATION;
  107. $onclick = '';
  108. $class = 'connector-btn-blue';
  109. $href = 'javascript:void(0)';
  110. $moduleAccess = $APPLICATION->GetGroupRight('b24connector');
  111. if($title == '')
  112. $title = Loc::getMessage('B24C_CONN_BUTT_CONNECT');
  113. if(!Loader::includeModule('socialservices') || $moduleAccess <= "R")
  114. {
  115. $class .= ' connector-btn-blue-disabled';
  116. }
  117. else
  118. {
  119. if(!self::isLinkedToNet())
  120. self::linkToNet();
  121. $hosts = self::getHostsList();
  122. if(!empty($hosts))
  123. {
  124. $urlTeml = self::getUrl('##HOST##');
  125. if(!empty($urlTeml))
  126. {
  127. $onclick = 'BX.B24Connector.showPortalChoosingDialog(\''.\CUtil::JSEscape($urlTeml).'\', '.\CUtil::PhpToJSObject($hosts).');';
  128. }
  129. else
  130. {
  131. $onclick = 'alert(\''.Loc::getMessage('B24C_CONN_CONNECT_ERROR').'\');';
  132. }
  133. }
  134. else
  135. {
  136. $href = self::getUrlNet();
  137. }
  138. }
  139. $result = '<a href="'.htmlspecialcharsbx($href).'"'.
  140. ($onclick <> '' ? ' onclick="'.$onclick.'"' : '').
  141. ' class="'.$class.'" >'.
  142. $title.'</a>';
  143. return $result;
  144. }
  145. /**
  146. * @param string $title Button title
  147. * @return string HTML for connect button.
  148. * @throws \Bitrix\Main\LoaderException
  149. * @throws \Bitrix\Main\ArgumentNullException
  150. */
  151. public static function getOptionButtonHtml($title)
  152. {
  153. $onclick = '';
  154. $disabled = false;
  155. if(!\Bitrix\Main\Loader::includeModule('socialservices'))
  156. {
  157. $disabled = true;
  158. }
  159. else
  160. {
  161. if(!self::isLinkedToNet())
  162. self::linkToNet();
  163. $hosts = self::getHostsList();
  164. if(!empty($hosts))
  165. {
  166. $urlTeml = self::getUrl('##HOST##');
  167. if(!empty($urlTeml))
  168. {
  169. $onclick = 'BX.B24Connector.showPortalChoosingDialog(\''.\CUtil::JSEscape($urlTeml).'\', '.\CUtil::PhpToJSObject($hosts).');';
  170. }
  171. else
  172. {
  173. $onclick = 'alert(\''.\CUtil::JSEscape(Loc::getMessage('B24C_CONN_CONNECT_ERROR')).'\');';
  174. }
  175. }
  176. else
  177. {
  178. $onclick = 'window.location.href="'.\CUtil::JSEscape(self::getUrlNet()).'"';
  179. }
  180. }
  181. return '<input type="button" onclick="'.htmlspecialcharsbx($onclick).'" value="'.$title.'"'.($disabled ? ' disabled' : '').'>';
  182. }
  183. /**
  184. * @return array Connection fields.
  185. * @throws \Bitrix\Main\LoaderException
  186. */
  187. public static function getFields()
  188. {
  189. static $result = null;
  190. if($result === null)
  191. {
  192. $result = array();
  193. if(Loader::includeModule('socialservices'))
  194. $result = ApTable::getConnection();
  195. }
  196. return is_array($result) ? $result : array();
  197. }
  198. /**
  199. * @return string Domain.
  200. * @throws \Bitrix\Main\LoaderException
  201. */
  202. public static function getDomain()
  203. {
  204. $fields = self::getFields();
  205. return !empty($fields['DOMAIN']) ? $fields['DOMAIN'] : '';
  206. }
  207. /**
  208. * Check if connection exists.
  209. * @return bool
  210. */
  211. public static function isExist()
  212. {
  213. $fields = self::getFields();
  214. return !empty($fields);
  215. }
  216. /**
  217. * Check that connection with remote Bitrix24 exists and REST API is available according current tariff
  218. * Result is cached for 1 hour.
  219. * @return bool
  220. */
  221. public static function isRestAvailable(): bool
  222. {
  223. static $result = null;
  224. if ($result === null)
  225. {
  226. if (!Loader::includeModule('socialservices'))
  227. {
  228. $result = false;
  229. }
  230. elseif (!$client = ApClient::init())
  231. {
  232. $result = false;
  233. }
  234. else
  235. {
  236. $cacheId = 'b24connector_rest_status';
  237. $cached = Cache::remember($cacheId, self::DEFAULT_CACHE_TTL, function () use ($client)
  238. {
  239. $response = $client->call('app.info');
  240. return (isset($response['result']) && empty($response['error']));
  241. });
  242. $result = (bool)$cached;
  243. }
  244. }
  245. return $result;
  246. }
  247. /**
  248. * @param $host
  249. * @return string
  250. * @throws \Bitrix\Main\LoaderException
  251. */
  252. private static function getUrl($host)
  253. {
  254. global $APPLICATION;
  255. if($host == '')
  256. return '';
  257. if(!Loader::includeModule("socialservices"))
  258. return '';
  259. $result = '';
  260. $appId = self::getAppID();
  261. if($appId <> '')
  262. {
  263. $result = $host.'apconnect/?client_id='.urlencode($appId).'&preset=ap&state='.urlencode(http_build_query(array(
  264. 'check_key' => \CSocServAuthManager::GetUniqueKey(),
  265. 'admin' => 1,
  266. 'backurl' => $APPLICATION->GetCurPageParam(),
  267. )));
  268. }
  269. return $result;
  270. }
  271. /**
  272. * @return string
  273. * @throws \Bitrix\Main\LoaderException
  274. */
  275. private static function getUrlNet()
  276. {
  277. if(!Loader::includeModule("socialservices"))
  278. return '';
  279. global $APPLICATION;
  280. $appId = self::getAppID();
  281. $result = '';
  282. if($appId <> '')
  283. {
  284. $result = \CBitrix24NetOAuthInterface::NET_URL.'/oauth/select/?preset=ap&client_id='.urlencode($appId).'&state='.urlencode(http_build_query(array(
  285. 'check_key' => \CSocServAuthManager::GetUniqueKey(),
  286. 'admin' => 1,
  287. 'backurl' => $APPLICATION->GetCurPageParam('', array('apaction', 'apID')),
  288. )));
  289. }
  290. return $result;
  291. }
  292. /**
  293. * @return array
  294. * @throws \Bitrix\Main\LoaderException
  295. */
  296. private static function getHostsList()
  297. {
  298. if(!Loader::includeModule('socialservices'))
  299. return array();
  300. $result = array();
  301. $query = \CBitrix24NetTransport::init();
  302. if($query)
  303. $result = $query->call('admin.profile.list', array());
  304. return !empty($result['result']) && is_array($result['result']) ? $result['result'] : array();
  305. }
  306. /**
  307. * @return string Url to edit open lines settings.
  308. */
  309. public static function getOpenLinesConfigUrl()
  310. {
  311. $res = self::getDataFromRest('imopenlines.config.path.get', array('result'));
  312. if(is_array($res) && !empty($res['SERVER_ADDRESS']) && !empty($res['PUBLIC_PATH']))
  313. {
  314. $result = $res['SERVER_ADDRESS'].$res['PUBLIC_PATH'];
  315. }
  316. else
  317. {
  318. $domain = self::getDomain();
  319. if($domain == '')
  320. return '';
  321. $result = 'https://'.htmlspecialcharsbx($domain).'/settings/openlines/'; //default for b24 cloud
  322. }
  323. return $result;
  324. }
  325. /**
  326. * @return string Url to edit telephony settings.
  327. */
  328. public static function getTelephonyConfigUrl()
  329. {
  330. return self::getDataFromRest('voximplant.url.get', array('result', 'lines'), '/telephony/lines.php');
  331. }
  332. /**
  333. * @return string Url to edit webform settings.
  334. */
  335. public static function getWebformConfigUrl()
  336. {
  337. return self::getDataFromRest('crm.webform.configuration.get', array('result', 'URL'), '/crm/webform/');
  338. }
  339. /**
  340. * @return string Url to edit widgets.
  341. */
  342. public static function getWidgetsConfigUrl()
  343. {
  344. return self::getDataFromRest('crm.sitebutton.configuration.get', array('result', 'URL'), '/crm/button/');
  345. }
  346. private static function getDataFromRest($method, $pathToData, $defaultPath = '')
  347. {
  348. if(!Loader::includeModule('socialservices'))
  349. return '';
  350. $result = '';
  351. if($client = ApClient::init())
  352. {
  353. $result = $client->call($method);
  354. if(is_array($result))
  355. {
  356. foreach($pathToData as $idx)
  357. {
  358. if(!empty($result[$idx]))
  359. {
  360. $result = $result[$idx];
  361. }
  362. else
  363. {
  364. $result = '';
  365. break;
  366. }
  367. }
  368. }
  369. }
  370. if(is_array($result))
  371. return $result;
  372. if($result == '')
  373. {
  374. $domain = self::getDomain();
  375. if($domain == '')
  376. return '';
  377. $result = 'https://'.htmlspecialcharsbx($domain).$defaultPath; //default for b24 cloud
  378. }
  379. return $result;
  380. }
  381. }