BxInvModule.php 31 KB

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