BxInvModule.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup Invites Invites
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. bx_import('BxDolAcl');
  12. define('BX_INV_TYPE_FROM_MEMBER', 'from_member');
  13. define('BX_INV_TYPE_FROM_SYSTEM', 'from_system');
  14. class BxInvModule extends BxDolModule
  15. {
  16. protected $_bIsApi;
  17. /**
  18. * Constructor
  19. */
  20. public function __construct($aModule)
  21. {
  22. parent::__construct($aModule);
  23. $this->_bIsApi = bx_is_api();
  24. $this->_oConfig->init($this->_oDb);
  25. }
  26. /**
  27. * ACTION METHODS
  28. */
  29. public function actionGetCode()
  30. {
  31. $aParams = $this->_prepareParamsGet();
  32. $this->serviceGetCode($aParams);
  33. }
  34. public function actionGetLink()
  35. {
  36. $aParams = $this->_prepareParamsGet();
  37. $this->serviceGetLink($aParams);
  38. }
  39. public function actionSetSeenMark($Code)
  40. {
  41. header('Content-Type: image/png');
  42. if (isset($Code) && trim($Code) != "")
  43. $this->_oDb->updateDateSeenForInvite($Code);
  44. }
  45. /**
  46. * SERVICE METHODS
  47. */
  48. public function serviceGetSafeServices()
  49. {
  50. return array (
  51. 'GetBlockInvite' => '',
  52. 'GetBlockInviteToContext' => '',
  53. 'GetBlockFormInvite' => '',
  54. 'GetBlockFormRequest' => '',
  55. 'GetLink' => '',
  56. 'GetCode' => '',
  57. 'GetContextByCode' => ''
  58. );
  59. }
  60. public function serviceGetCode($aParams)
  61. {
  62. if($this->_bIsApi && is_string($aParams))
  63. $aParams = bx_api_get_browse_params($aParams);
  64. $iProfileId = $this->getProfileId();
  65. $iAccountId = $this->getAccountId($iProfileId);
  66. $mixedAllowed = $this->isAllowedInvite($iProfileId);
  67. if($mixedAllowed !== true)
  68. return echoJson(['message' => $mixedAllowed]);
  69. $iKeyLength = 0;
  70. $iKeyLifetime = $this->_oConfig->getKeyLifetime();
  71. $bContextAdmin = false;
  72. if(isset($aParams['aj_action'], $aParams['aj_params']) && $aParams['aj_action'] == 'invite_to_context' && ($iContextPid = (int)$aParams['aj_params']) != 0) {
  73. $iKeyLength = $this->_oConfig->getContextKeyLength();
  74. $bContextAdmin = ($oContext = BxDolProfile::getInstance($iContextPid)) !== false && bx_srv($oContext->getModule(), 'is_admin', [$iContextPid, $iProfileId]);
  75. }
  76. if(!isAdmin($iAccountId) && !$bContextAdmin && $this->_oConfig->getCountPerUser() <= 0)
  77. return $this->_bIsApi ? [bx_api_get_msg(_t('_bx_invites_err_limit_reached'))] : echoJson(['message' => _t('_bx_invites_err_limit_reached')]);
  78. $oKeys = BxDolKey::getInstance();
  79. if(!$oKeys)
  80. return $this->_bIsApi ? [bx_api_get_msg(_t('_bx_invites_err_not_available'))] : echoJson(['message' => _t('_bx_invites_err_not_available')]);
  81. $aKeyParams = [];
  82. if(!empty($aParams['key']))
  83. $aKeyParams['key'] = $aParams['key'];
  84. if($iKeyLength)
  85. $aKeyParams['length'] = $iKeyLength;
  86. if($aKeyParams)
  87. $sKey = $oKeys->getNewKeyExt(false, $iKeyLifetime, $aKeyParams);
  88. else
  89. $sKey = $oKeys->getNewKey(false, $iKeyLifetime);
  90. $this->getFormObjectInvite()->insert(array_merge([
  91. 'account_id' => $iAccountId,
  92. 'profile_id' => $iProfileId,
  93. 'key' => $sKey,
  94. 'multi' => 1,
  95. 'date' => time()
  96. ], $aParams));
  97. $this->onInvite($iProfileId);
  98. $sLink = $this->getJoinLink($sKey);
  99. if($this->_bIsApi)
  100. return [
  101. 'code' => $sKey,
  102. 'link' => bx_api_get_relative_url($sLink)
  103. ];
  104. echoJson(['popup' => $this->_oTemplate->getCodePopup($sKey, $sLink)]);
  105. }
  106. function serviceGetLink($aParams)
  107. {
  108. $iProfileId = $this->getProfileId();
  109. $iAccountId = $this->getAccountId($iProfileId);
  110. $mixedAllowed = $this->isAllowedInvite($iProfileId);
  111. if($mixedAllowed !== true)
  112. return echoJson(array('message' => $mixedAllowed));
  113. if(!isAdmin($iAccountId)) {
  114. if($this->_oConfig->getCountPerUser() <= 0)
  115. return $this->_bIsApi ? [bx_api_get_msg(_t('_bx_invites_err_limit_reached'))] : echoJson(array('message' => _t('_bx_invites_err_limit_reached')));
  116. }
  117. $oKeys = BxDolKey::getInstance();
  118. if(!$oKeys)
  119. return $this->_bIsApi ? [bx_api_get_msg(_t('_bx_invites_err_not_available'))] : echoJson(array('message' => _t('_bx_invites_err_not_available')));
  120. $sKey = $oKeys->getNewKey(false, $this->_oConfig->getKeyLifetime());
  121. $this->getFormObjectInvite()->insert(array_merge([
  122. 'account_id' => $iAccountId,
  123. 'profile_id' => $iProfileId,
  124. 'key' => $sKey,
  125. 'date' => time()
  126. ], $aParams));
  127. $this->onInvite($iProfileId);
  128. $sLink = $this->getJoinLink($sKey);
  129. if($this->_bIsApi)
  130. return ['link' => bx_api_get_relative_url($sLink)];
  131. echoJson(['popup' => $this->_oTemplate->getLinkPopup($sLink)]);
  132. }
  133. public function serviceGetContextByCode($sKey = false, $aParams = [])
  134. {
  135. if($this->_bIsApi && !$sKey)
  136. return [bx_api_get_block('invite_in_context', ['request_url' => 'bx_invites/get_context_by_code/&params[]='])];
  137. if($this->_bIsApi && is_string($aParams))
  138. $aParams = bx_api_get_browse_params($aParams);
  139. $oKeys = BxDolKey::getInstance();
  140. $aInvite = $this->_oDb->getInvites(['type' => 'by_key', 'key' => $sKey]);
  141. if(empty($aInvite) || !is_array($aInvite) || !$oKeys->isKeyExists($sKey))
  142. return ($sMsg = _t('_bx_invites_err_code_not_found')) && $this->_bIsApi ? ['result' => false, 'message' => $sMsg] : ['msg' => $sMsg];
  143. $iContextPid = 0;
  144. $oContextProfile = false;
  145. if($aInvite['aj_action'] != 'invite_to_context' || !($iContextPid = (int)$aInvite['aj_params']) || ($oContextProfile = BxDolProfile::getInstance($iContextPid)) == false)
  146. return ($sMsg = _t('_bx_invites_err_context_not_found')) && $this->_bIsApi ? ['result' => false, 'message' => $sMsg] : ['msg' => $sMsg];
  147. if(isset($aParams['initiate']) && (bool)$aParams['initiate'] === true)
  148. $this->_oConfig->setKey($sKey);
  149. return $this->_bIsApi ? ['result' => true, 'data' => BxDolProfile::getData($oContextProfile)] : [
  150. 'module' => $oContextProfile->getModule(),
  151. 'id' => $oContextProfile->getContentId(),
  152. 'profile_id' => $iContextPid,
  153. 'display_name' => $oContextProfile->getDisplayName(),
  154. 'url' => $oContextProfile->getUrl()
  155. ];
  156. }
  157. /**
  158. * @page service Service Calls
  159. * @section bx_invites Invitations
  160. * @subsection bx_invites-other Other
  161. * @subsubsection bx_invites-get_include get_include
  162. *
  163. * @code bx_srv('bx_invites', 'get_include', [...]); @endcode
  164. *
  165. * Get all necessary CSS and JS files to include in a page.
  166. *
  167. * @return string with all necessary CSS and JS files.
  168. *
  169. * @see BxInvModule::serviceGetInclude
  170. */
  171. /**
  172. * @ref bx_invites-get_include "get_include"
  173. */
  174. public function serviceGetInclude()
  175. {
  176. return $this->_oTemplate->getInclude();
  177. }
  178. /**
  179. * @page service Service Calls
  180. * @section bx_invites Invitations
  181. * @subsection bx_invites-page_blocks Page Blocks
  182. * @subsubsection bx_invites-get_block_invite get_block_invite
  183. *
  184. * @code bx_srv('bx_invites', 'get_block_invite', [...]); @endcode
  185. *
  186. * Get page block which displays invitations related info and action(s).
  187. *
  188. * @return an array describing a block to display on the site or empty string if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  189. *
  190. * @see BxInvModule::serviceGetBlockInvite
  191. */
  192. /**
  193. * @ref bx_invites-get_block_invite "get_block_invite"
  194. */
  195. public function serviceGetBlockInvite($bRedirect = false)
  196. {
  197. $iProfileId = $this->getProfileId();
  198. if(($mixedAllowed = $this->isAllowedInvite($iProfileId)) !== true)
  199. return '';
  200. $iAccountId = $this->getAccountId($iProfileId);
  201. if(!isAdmin($iAccountId) && $this->_oConfig->getCountPerUser() <= 0)
  202. return '';
  203. return [
  204. 'content' => $this->_oTemplate->getBlockInvite($iAccountId, $iProfileId, [
  205. 'redirect' => (bool)$bRedirect
  206. ])
  207. ];
  208. }
  209. /**
  210. * @page service Service Calls
  211. * @section bx_invites Invitations
  212. * @subsection bx_invites-page_blocks Page Blocks
  213. * @subsubsection bx_invites-get_block_invite get_block_invite_to_context
  214. *
  215. * @code bx_srv('bx_invites', 'get_block_invite_to_context', [...]); @endcode
  216. *
  217. * Get page block which displays invitations related info and action(s). It's similar to BxInvModule::serviceGetBlockInvite
  218. * but should be used on View Context page (should receive Context Profile ID). It invites to the context after joining the site.
  219. *
  220. * @return an array describing a block to display on the site or empty string if something is wrong.
  221. * All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  222. *
  223. * @see BxInvModule::serviceGetBlockInviteToContext
  224. */
  225. /**
  226. * @ref bx_invites-get_block_invite_to_context "get_block_invite_to_context"
  227. */
  228. public function serviceGetBlockInviteToContext($iContextPid)
  229. {
  230. $oContext = false;
  231. if(!$iContextPid || !($oContext = BxDolProfile::getInstance($iContextPid)))
  232. return '';
  233. $sContext = $oContext->getModule();
  234. if(!bx_srv('system', 'is_module_context', [$sContext]))
  235. return '';
  236. $iProfileId = $this->getProfileId();
  237. if(($mixedAllowed = $this->isAllowedInvite($iProfileId)) !== true)
  238. return '';
  239. $iAccountId = $this->getAccountId($iProfileId);
  240. if(!isAdmin($iAccountId) && !bx_srv($sContext, 'is_admin', [$iContextPid, $iProfileId]) && $this->_oConfig->getCountPerUser() <= 0)
  241. return '';
  242. return [
  243. 'content' => $this->_oTemplate->getBlockInvite($iAccountId, $iProfileId, [
  244. 'context' => (int)$iContextPid
  245. ])
  246. ];
  247. }
  248. /**
  249. * @page service Service Calls
  250. * @section bx_invites Invitations
  251. * @subsection bx_invites-page_blocks Page Blocks
  252. * @subsubsection bx_invites-get_block_accept_by_code get_block_accept_by_code
  253. *
  254. * @code bx_srv('bx_invites', 'get_block_accept_by_code', [...]); @endcode
  255. *
  256. * Get page block with accept invitation (by code) form.
  257. *
  258. * @return an array describing a block to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  259. *
  260. * @see BxInvModule::serviceGetBlockAcceptByCode
  261. */
  262. /**
  263. * @ref bx_invites-get_block_accept_by_code "get_block_accept_by_code"
  264. */
  265. public function serviceGetBlockAcceptByCode()
  266. {
  267. $mixedResult = $this->_oTemplate->getBlockAcceptByCode();
  268. if($this->_bIsApi)
  269. return $mixedResult;
  270. if(is_array($mixedResult)) {
  271. echoJson($mixedResult);
  272. exit;
  273. }
  274. return [
  275. 'content' => $mixedResult
  276. ];
  277. }
  278. /**
  279. * @page service Service Calls
  280. * @section bx_invites Invitations
  281. * @subsection bx_invites-page_blocks Page Blocks
  282. * @subsubsection bx_invites-get_block_form_invite get_block_form_invite
  283. *
  284. * @code bx_srv('bx_invites', 'get_block_form_invite', [...]); @endcode
  285. *
  286. * Get page block with invite form.
  287. *
  288. * @return an array describing a block to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  289. *
  290. * @see BxInvModule::serviceGetBlockFormInvite
  291. */
  292. /**
  293. * @ref bx_invites-get_block_form_invite "get_block_form_invite"
  294. */
  295. public function serviceGetBlockFormInvite($aParams = [])
  296. {
  297. if(!isset($aParams['aj_action'], $aParams['aj_params']))
  298. $aParams = array_merge($aParams, $this->_prepareParamsGet());
  299. $oForm = $this->getFormObjectInvite();
  300. $oForm->aInputs['text']['value'] = _t('_bx_invites_msg_invitation');
  301. foreach(['aj_action', 'aj_params'] as $sKey)
  302. if(!empty($aParams[$sKey]))
  303. $oForm->aInputs[$sKey] = [
  304. 'name' => $sKey,
  305. 'type' => 'hidden',
  306. 'value' => $aParams[$sKey]
  307. ];
  308. $sResult = '';
  309. $oForm->initChecker();
  310. if($oForm->isSubmittedAndValid()){
  311. $sResult = MsgBox($this->processFormObjectInvite($oForm));
  312. if($this->_bIsApi)
  313. return [bx_api_get_msg($sResult)];
  314. }
  315. if($this->_bIsApi)
  316. return [bx_api_get_block('form', $oForm->getCodeAPI(), ['ext' => ['name' => $this->getName(), 'request' => ['url' => '/api.php?r=' . $this->getName() . '/get_block_form_invite', 'immutable' => true]]])];
  317. return [
  318. 'content' => $sResult . $oForm->getCode()
  319. ];
  320. }
  321. /**
  322. * @page service Service Calls
  323. * @section bx_invites Invitations
  324. * @subsection bx_invites-page_blocks Page Blocks
  325. * @subsubsection bx_invites-get_block_form_request get_block_form_request
  326. *
  327. * @code bx_srv('bx_invites', 'get_block_form_request', [...]); @endcode
  328. *
  329. * Get page block with request invitation form.
  330. *
  331. * @return an array describing a block to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  332. *
  333. * @see BxInvModule::serviceGetBlockFormRequest
  334. */
  335. /**
  336. * @ref bx_invites-get_block_form_request "get_block_form_request"
  337. */
  338. public function serviceGetBlockFormRequest()
  339. {
  340. $mixedResult = $this->_oTemplate->getBlockFormRequest();
  341. if ($this->_bIsApi)
  342. return $mixedResult;
  343. if(is_array($mixedResult)) {
  344. echoJson($mixedResult);
  345. exit;
  346. }
  347. return array(
  348. 'content' => $mixedResult
  349. );
  350. }
  351. /**
  352. * @page service Service Calls
  353. * @section bx_invites Invitations
  354. * @subsection bx_invites-page_blocks Page Blocks
  355. * @subsubsection bx_invites-get_block_manage_requests get_block_manage_requests
  356. *
  357. * @code bx_srv('bx_invites', 'get_block_manage_requests', [...]); @endcode
  358. *
  359. * Get page block with manage invitation requests table.
  360. *
  361. * @return HTML string with block content to display on the site or empty string if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  362. *
  363. * @see BxInvModule::serviceGetBlockManageRequests
  364. */
  365. /**
  366. * @ref bx_invites-get_block_manage_requests "get_block_manage_requests"
  367. */
  368. public function serviceGetBlockManageRequests()
  369. {
  370. return $this->getBlockManage('requests');
  371. }
  372. /**
  373. * @page service Service Calls
  374. * @section bx_invites Invitations
  375. * @subsection bx_invites-page_blocks Page Blocks
  376. * @subsubsection bx_invites-get_block_manage_invites get_block_manage_requests
  377. *
  378. * @code bx_srv('bx_invites', 'get_block_manage_invites', [...]); @endcode
  379. *
  380. * Get page block with manage invitations table.
  381. *
  382. * @return HTML string with block content to display on the site or empty string if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  383. *
  384. * @see BxInvModule::serviceGetBlockManageInvites
  385. */
  386. /**
  387. * @ref bx_invites-get_block_manage_invites "get_block_manage_invites"
  388. */
  389. public function serviceGetBlockManageInvites()
  390. {
  391. return $this->getBlockManage('invites');
  392. }
  393. /**
  394. * @page service Service Calls
  395. * @section bx_invites Invitations
  396. * @subsection bx_invites-other Other
  397. * @subsubsection bx_invites-get_menu_addon_requests get_menu_addon_requests
  398. *
  399. * @code bx_srv('bx_invites', 'get_menu_addon_requests', [...]); @endcode
  400. *
  401. * Get number or invitation requests.
  402. *
  403. * @return integer value with number of invitation requests.
  404. *
  405. * @see BxInvModule::serviceGetMenuAddonRequests
  406. */
  407. /**
  408. * @ref bx_invites-get_menu_addon_requests "get_menu_addon_requests"
  409. */
  410. public function serviceGetMenuAddonRequests()
  411. {
  412. return array('counter3_value' => $this->_oDb->getRequests(array('type' => 'count_all')));
  413. }
  414. /**
  415. * @page service Service Calls
  416. * @section bx_invites Invitations
  417. * @subsection bx_invites-other Other
  418. * @subsubsection bx_invites-account_add_form_check account_add_form_check
  419. *
  420. * @code bx_srv('bx_invites', 'account_add_form_check', [...]); @endcode
  421. *
  422. * Perform neccessary checking on join form.
  423. *
  424. * @return empty string - if join is allowed and should be processed as usual, non-empty string - if join form need to be replaced with this code.
  425. *
  426. * @see BxInvModule::serviceAccountAddFormCheck
  427. */
  428. /**
  429. * @ref bx_invites-account_add_form_check "account_add_form_check"
  430. */
  431. public function serviceAccountAddFormCheck()
  432. {
  433. $sReturn = '';
  434. $sKey = bx_get($this->_oConfig->getKeyCode());
  435. $bKey = $sKey !== false;
  436. if($bKey) {
  437. $sKey = bx_process_input($sKey);
  438. $oKeys = BxDolKey::getInstance();
  439. if($oKeys->isKeyExists($sKey))
  440. $this->_oConfig->setKey($sKey);
  441. else
  442. $this->_oConfig->unsetKey();
  443. }
  444. if($this->_oConfig->getKey() !== false)
  445. return $sReturn;
  446. if($bKey)
  447. $sReturn .= MsgBox(_t('_bx_invites_err_used'));
  448. if($this->_oConfig->isRegistrationByInvitation())
  449. $sReturn .= $this->_oTemplate->getBlockRequest();
  450. return $sReturn;
  451. }
  452. /**
  453. * Data for Notifications module
  454. */
  455. public function serviceGetNotificationsData()
  456. {
  457. $sModule = $this->_aModule['name'];
  458. $sEventPrivacy = $sModule . '_allow_view_event_to';
  459. if(BxDolPrivacy::getObjectInstance($sEventPrivacy) === false)
  460. $sEventPrivacy = '';
  461. return array(
  462. 'handlers' => array(
  463. array('group' => $sModule . '_object', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'request_notify', 'module_name' => $sModule, 'module_method' => 'get_notifications_request', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
  464. ),
  465. 'settings' => array(
  466. array('group' => 'request', 'unit' => $sModule, 'action' => 'request_notify', 'types' => array('personal')),
  467. ),
  468. 'alerts' => array(
  469. array('unit' => $sModule, 'action' => 'request_notify'),
  470. )
  471. );
  472. }
  473. /**
  474. * Entry post for Notifications module
  475. */
  476. public function serviceGetNotificationsRequest($aEvent)
  477. {
  478. if (getParam('bx_invites_requests_notifications') != 'on')
  479. return [];
  480. $aRequest = $this->_oDb->getRequests(array('type' => 'by_id', 'value' => $aEvent['object_id']));
  481. if (!$aRequest)
  482. return [];
  483. $CNF = &$this->_oConfig->CNF;
  484. $sEntryUrl = bx_absolute_url(BxDolPermalinks::getInstance()->permalink($CNF['URL_REQUESTS']), '{bx_url_root}');
  485. return [
  486. 'entry_sample' => $aRequest['name'] . '(' . $aRequest['email'] . ')',
  487. 'entry_url' => $sEntryUrl,
  488. 'entry_caption' => $aRequest['text'],
  489. 'entry_author' => '',
  490. 'entry_privacy' => '', //may be empty or not specified. In this case Public privacy will be used.
  491. 'lang_key' => '_bx_invites_alert_action_request', //may be empty or not specified. In this case the default one from Notification module will be used.
  492. ];
  493. }
  494. public function attachAccountIdToInvite($iAccountId, $sKey)
  495. {
  496. $this->_oDb->attachAccountIdToInvite($iAccountId, $sKey);
  497. }
  498. public function invite($sType, $aEmails, $sText, $aParams = [])
  499. {
  500. if(empty($aEmails) || !is_array($aEmails))
  501. return false;
  502. $oKeys = BxDolKey::getInstance();
  503. if(!$oKeys || !in_array($sType, [BX_INV_TYPE_FROM_MEMBER, BX_INV_TYPE_FROM_SYSTEM]))
  504. return false;
  505. $iKeyLifetime = $this->_oConfig->getKeyLifetime();
  506. $sEmailTemplate = '';
  507. switch($sType) {
  508. case BX_INV_TYPE_FROM_MEMBER:
  509. $sEmailTemplate = 'bx_invites_invite_form_message';
  510. break;
  511. case BX_INV_TYPE_FROM_SYSTEM:
  512. $sEmailTemplate = 'bx_invites_invite_by_request_message';
  513. break;
  514. }
  515. $iDate = time();
  516. $iProfileId = $this->getProfileId();
  517. $iAccountId = $this->getAccountId($iProfileId);
  518. $aMessage = BxDolEmailTemplates::getInstance()->parseTemplate($sEmailTemplate, array(
  519. 'text' => $sText
  520. ), $iAccountId, $iProfileId);
  521. $iEmailUse = !empty($aParams['email_use']) ? (int)$aParams['email_use'] : 0;
  522. $bLimit = !empty($aParams['limit']) && is_numeric($aParams['limit']);
  523. $aResults = [];
  524. foreach($aEmails as $sEmail) {
  525. $sEmail = trim($sEmail);
  526. if(empty($sEmail))
  527. continue;
  528. $sKey = $oKeys->getNewKey(false, $iKeyLifetime);
  529. $aMarkers = [
  530. 'join_url' => $this->getJoinLink($sKey),
  531. 'seen_image_url' => $this->getSeenImageUrl($sKey)
  532. ];
  533. if(sendMail($sEmail, $aMessage['Subject'], $aMessage['Body'], 0, $aMarkers, BX_EMAIL_SYSTEM, 'html', false, [], true)) {
  534. $iInviteId = (int)$this->_oDb->insertInvite([
  535. 'account_id' => $iAccountId,
  536. 'profile_id' => $iProfileId,
  537. 'key' => $sKey,
  538. 'email' => $sEmail,
  539. 'email_use' => $iEmailUse,
  540. 'aj_action' => !empty($aParams['aj_action']) ? $aParams['aj_action'] : '',
  541. 'aj_params' => !empty($aParams['aj_params']) ? $aParams['aj_params'] : '',
  542. 'date' => $iDate
  543. ]);
  544. $this->onInvite($iProfileId);
  545. $aResults[$iInviteId] = $sEmail;
  546. if($bLimit && count($aResults) == (int)$aParams['limit'])
  547. break;
  548. }
  549. }
  550. return $aResults;
  551. }
  552. public function processFormObjectInvite(&$oForm)
  553. {
  554. $iProfileId = $this->getProfileId();
  555. $iAccountId = $this->getAccountId($iProfileId);
  556. $mixedAllowed = $this->isAllowedInvite($iProfileId);
  557. if($mixedAllowed !== true)
  558. return $mixedAllowed;
  559. $aInviteParams = [];
  560. if(!isAdmin($iAccountId) && ($aInviteParams['limit'] = $this->_oConfig->getCountPerUser()) <= 0)
  561. return _t('_bx_invites_err_limit_reached');
  562. $sEmails = bx_process_input($oForm->getCleanValue('emails'));
  563. $aEmails = preg_split("/[\s\n,;]+/", $sEmails);
  564. $aInviteParams['email_use'] = (int)$oForm->getCleanValue('email_use');
  565. if(($sA = 'aj_action') && ($$sA = $oForm->getCleanValue($sA)) && ($sP = 'aj_params') && ($$sP = $oForm->getCleanValue($sP)))
  566. $aInviteParams = array_merge($aInviteParams, [
  567. $sA => $$sA,
  568. $sP => $$sP
  569. ]);
  570. $sText = bx_process_pass($oForm->getCleanValue('text'));
  571. $sResult = _t('_bx_invites_err_not_available');
  572. if(($aEmailsSent = $this->invite(BX_INV_TYPE_FROM_MEMBER, $aEmails, $sText, $aInviteParams)) !== false) {
  573. $sEmailsResult = '';
  574. if(count($aEmails) != count($aEmailsSent))
  575. $sEmailsResult = implode('; ', array_diff($aEmails, $aEmailsSent));
  576. $oForm->aInputs['emails']['value'] = $sEmailsResult;
  577. $sResult = _t('_bx_invites_msg_invitation_sent', count($aEmailsSent));
  578. }
  579. return $sResult;
  580. }
  581. public function processInviteToContext($iPid, $iContextPid)
  582. {
  583. $oContext = null;
  584. if(!$iPid || !$iContextPid || !($oContext = BxDolProfile::getInstance($iContextPid)))
  585. return false;
  586. $sContext = $oContext->getModule();
  587. if(!bx_srv('system', 'is_module_context', [$sContext]))
  588. return false;
  589. $bAutoJoin = $this->_oConfig->isContextAutoJoin();
  590. $bResult = false;
  591. if($bAutoJoin && ($oConnection = bx_srv($sContext, 'get_fans_connection_object')) !== false)
  592. $bResult = $oConnection->addConnection($iContextPid, $iPid) && $oConnection->addConnection($iPid, $iContextPid);
  593. if(!$bAutoJoin || !$bResult)
  594. $bResult = bx_srv($sContext, 'add_invitation', [$iContextPid, $iPid]);
  595. return $bResult;
  596. }
  597. public function isAllowedInvite($iProfileId, $bPerform = false)
  598. {
  599. $aCheckResult = checkActionModule($iProfileId, 'invite', $this->getName(), $bPerform);
  600. return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
  601. }
  602. public function isAllowedRequest($iProfileId, $bPerform = false)
  603. {
  604. $aCheckResult = checkActionModule($iProfileId, 'request', $this->getName(), $bPerform);
  605. return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
  606. }
  607. public function isAllowedDeleteRequest($iProfileId, $bPerform = false)
  608. {
  609. $aCheckResult = checkActionModule($iProfileId, 'delete request', $this->getName(), $bPerform);
  610. return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
  611. }
  612. public function isAllowedDeleteInvite($iProfileId, $bPerform = false)
  613. {
  614. $aCheckResult = checkActionModule($iProfileId, 'delete invite', $this->getName(), $bPerform);
  615. return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
  616. }
  617. public function getProfileId()
  618. {
  619. return isLogged() ? bx_get_logged_profile_id() : 0;
  620. }
  621. public function getProfileObject($iProfileId = 0)
  622. {
  623. $oProfile = BxDolProfile::getInstance($iProfileId);
  624. if (!$oProfile)
  625. $oProfile = BxDolProfileUndefined::getInstance();
  626. return $oProfile;
  627. }
  628. public function getAccountId($iProfileId)
  629. {
  630. $oProfile = $this->getProfileObject($iProfileId);
  631. if($oProfile->id() == 0)
  632. return 0;
  633. return $oProfile->getAccountId();
  634. }
  635. public function onRequest($iRequestId)
  636. {
  637. /**
  638. * @hooks
  639. * @hookdef hook-bx_invites-deleted_answer_notif 'bx_invites', 'request' - hook on create new request on invite
  640. * - $unit_name - equals `bx_invites`
  641. * - $action - equals `request`
  642. * - $object_id - request id
  643. * - $sender_id - not used
  644. * @hook @ref hook-bx_invites-request
  645. */
  646. bx_alert($this->_oConfig->getObject('alert'), 'request', $iRequestId);
  647. $aProfiles = BxDolAclQuery::getInstance()->getProfilesByMembership(array(MEMBERSHIP_ID_MODERATOR, MEMBERSHIP_ID_ADMINISTRATOR));
  648. foreach($aProfiles as $aProfile) {
  649. /**
  650. * @hooks
  651. * @hookdef hook-bx_invites-request_notify 'bx_invites', 'request_notify' - hook on notify all admins&moderators about new request
  652. * - $unit_name - equals `bx_invites`
  653. * - $action - equals `request_notify`
  654. * - $object_id - request id
  655. * - $sender_id - not used
  656. * - $extra_params - array of additional params with the following array keys:
  657. * - `parent_author_id` - [int] profile_id of notified profile
  658. * @hook @ref hook-bx_invites-request_notify
  659. */
  660. bx_alert($this->_oConfig->getObject('alert'), 'request_notify', $iRequestId, 0, array('parent_author_id' => $aProfile['id']));
  661. }
  662. //--- Event -> Request for Alerts Engine ---//
  663. }
  664. public function getFormObjectInvite($sDisplay = '')
  665. {
  666. if(empty($sDisplay))
  667. $sDisplay = $this->_oConfig->getObject('form_display_invite_send');
  668. bx_import('FormCheckerHelper', $this->_aModule);
  669. return BxDolForm::getObjectInstance($this->_oConfig->getObject('form_invite'), $sDisplay);
  670. }
  671. protected function getBlockManage($sType)
  672. {
  673. $oGrid = BxDolGrid::getObjectInstance($this->_oConfig->getObject('grid_' . $sType));
  674. if(!$oGrid)
  675. return '';
  676. if($this->_bIsApi)
  677. return [
  678. bx_api_get_block('grid', $oGrid->getCodeAPI())
  679. ];
  680. $this->_oTemplate->addCss(['main.css']);
  681. $this->_oTemplate->addJs(['jquery.form.min.js', 'main.js']);
  682. $this->_oTemplate->addJsTranslation(['_sys_grid_search']);
  683. return [
  684. 'menu' => $this->_oTemplate->getMenuForManageBlocks($sType),
  685. 'content' => $this->_oTemplate->getJsCode('main', ['grid' => $sType]) . $oGrid->getCode()
  686. ];
  687. }
  688. public function onInvite($iProfileId)
  689. {
  690. $this->isAllowedInvite($iProfileId, true);
  691. /**
  692. * @hooks
  693. * @hookdef hook-bx_invites-invite 'bx_invites', 'invite' - hook on new invite
  694. * - $unit_name - equals `bx_invites`
  695. * - $action - equals `invite`
  696. * - $object_id - not used
  697. * - $sender_id - invited profile_id
  698. * @hook @ref hook-bx_invites-invite
  699. */
  700. bx_alert($this->_oConfig->getObject('alert'), 'invite', 0, $iProfileId);
  701. }
  702. public function getJoinLink($sKey)
  703. {
  704. return bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=create-account', [
  705. $this->_oConfig->getKeyCode() => $sKey
  706. ]));
  707. }
  708. public function getSeenImageUrl($sKey)
  709. {
  710. return BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'SetSeenMark/' . $sKey . "/";
  711. }
  712. protected function _prepareParamsGet()
  713. {
  714. $sAjAction = bx_get('aja');
  715. if(!$sAjAction || !($sAjAction = bx_process_input($sAjAction)) || !in_array($sAjAction, ['redirect', 'invite_to_context']))
  716. return [];
  717. $sAjParams = bx_get('ajp');
  718. if(!$sAjParams)
  719. return [];
  720. switch($sAjAction) {
  721. case 'redirect':
  722. $sAjParams = $this->_oConfig->urlDecode(bx_process_input($sAjParams));
  723. break;
  724. case 'invite_to_context':
  725. $sAjParams = bx_process_input($sAjParams, BX_DATA_INT);
  726. break;
  727. }
  728. return [
  729. 'aj_action' => $sAjAction,
  730. 'aj_params' => $sAjParams
  731. ];
  732. }
  733. }
  734. /** @} */