BxInvModule.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  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. /**
  17. * Constructor
  18. */
  19. function __construct($aModule)
  20. {
  21. parent::__construct($aModule);
  22. $this->_oConfig->init($this->_oDb);
  23. }
  24. /**
  25. * ACTION METHODS
  26. */
  27. function actionGetLink()
  28. {
  29. $iProfileId = $this->getProfileId();
  30. $iAccountId = $this->getAccountId($iProfileId);
  31. $mixedAllowed = $this->isAllowedInvite($iProfileId);
  32. if($mixedAllowed !== true)
  33. return echoJson(array('message' => $mixedAllowed));
  34. if(!isAdmin($iAccountId)) {
  35. $iInvited = (int)$this->_oDb->getInvites(array('type' => 'count_by_account', 'value' => $iAccountId));
  36. if(($this->_oConfig->getCountPerUser() - $iInvited) <= 0)
  37. return echoJson(array('message' => _t('_bx_invites_err_limit_reached')));
  38. }
  39. $oKeys = BxDolKey::getInstance();
  40. if(!$oKeys)
  41. return echoJson(array('message' => _t('_bx_invites_err_not_available')));
  42. $sKey = $oKeys->getNewKey(false, $this->_oConfig->getKeyLifetime());
  43. $oForm = $this->getFormObjectInvite();
  44. $oForm->insert(array(
  45. 'account_id' => $iAccountId,
  46. 'profile_id' => $iProfileId,
  47. 'key' => $sKey,
  48. 'email' => '',
  49. 'date' => time()
  50. ));
  51. echoJson(array('popup' => $this->_oTemplate->getLinkPopup(
  52. $this->getJoinLink($sKey)
  53. )));
  54. }
  55. public function actionSetSeenMark($Code)
  56. {
  57. header('Content-Type: image/png');
  58. if (isset($Code) && trim($Code) != "")
  59. $this->_oDb->updateDateSeenForInvite($Code);
  60. }
  61. /**
  62. * SERVICE METHODS
  63. */
  64. /**
  65. * @page service Service Calls
  66. * @section bx_invites Invitations
  67. * @subsection bx_invites-other Other
  68. * @subsubsection bx_invites-get_include get_include
  69. *
  70. * @code bx_srv('bx_invites', 'get_include', [...]); @endcode
  71. *
  72. * Get all necessary CSS and JS files to include in a page.
  73. *
  74. * @return string with all necessary CSS and JS files.
  75. *
  76. * @see BxInvModule::serviceGetInclude
  77. */
  78. /**
  79. * @ref bx_invites-get_include "get_include"
  80. */
  81. public function serviceGetInclude()
  82. {
  83. return $this->_oTemplate->getInclude();
  84. }
  85. /**
  86. * @page service Service Calls
  87. * @section bx_invites Invitations
  88. * @subsection bx_invites-page_blocks Page Blocks
  89. * @subsubsection bx_invites-get_block_invite get_block_invite
  90. *
  91. * @code bx_srv('bx_invites', 'get_block_invite', [...]); @endcode
  92. *
  93. * Get page block for member's Dashboard which displays invitations related info and action(s).
  94. *
  95. * @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.
  96. *
  97. * @see BxInvModule::serviceGetBlockInvite
  98. */
  99. /**
  100. * @ref bx_invites-get_block_invite "get_block_invite"
  101. */
  102. public function serviceGetBlockInvite()
  103. {
  104. $iProfileId = $this->getProfileId();
  105. $iAccountId = $this->getAccountId($iProfileId);
  106. $mixedAllowed = $this->isAllowedInvite($iProfileId);
  107. if($mixedAllowed !== true)
  108. return '';
  109. $iInvited = (int)$this->_oDb->getInvites(array('type' => 'count_by_account', 'value' => $iAccountId));
  110. if(!isAdmin($iAccountId) && $iInvited >= $this->_oConfig->getCountPerUser())
  111. return '';
  112. return array(
  113. 'content' => $this->_oTemplate->getBlockInvite($iAccountId, $iProfileId)
  114. );
  115. }
  116. /**
  117. * @page service Service Calls
  118. * @section bx_invites Invitations
  119. * @subsection bx_invites-page_blocks Page Blocks
  120. * @subsubsection bx_invites-get_block_form_invite get_block_form_invite
  121. *
  122. * @code bx_srv('bx_invites', 'get_block_form_invite', [...]); @endcode
  123. *
  124. * Get page block with invite form.
  125. *
  126. * @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.
  127. *
  128. * @see BxInvModule::serviceGetBlockFormInvite
  129. */
  130. /**
  131. * @ref bx_invites-get_block_form_invite "get_block_form_invite"
  132. */
  133. public function serviceGetBlockFormInvite()
  134. {
  135. $oForm = $this->getFormObjectInvite();
  136. $oForm->aInputs['text']['value'] = _t('_bx_invites_msg_invitation');
  137. $sResult = '';
  138. $oForm->initChecker();
  139. if($oForm->isSubmittedAndValid()) {
  140. $sResult = $this->processFormObjectInvite($oForm);
  141. $sResult = MsgBox($sResult);
  142. }
  143. return array(
  144. 'content' => $sResult . $oForm->getCode()
  145. );
  146. }
  147. /**
  148. * @page service Service Calls
  149. * @section bx_invites Invitations
  150. * @subsection bx_invites-page_blocks Page Blocks
  151. * @subsubsection bx_invites-get_block_form_request get_block_form_request
  152. *
  153. * @code bx_srv('bx_invites', 'get_block_form_request', [...]); @endcode
  154. *
  155. * Get page block with request invitation form.
  156. *
  157. * @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.
  158. *
  159. * @see BxInvModule::serviceGetBlockFormRequest
  160. */
  161. /**
  162. * @ref bx_invites-get_block_form_request "get_block_form_request"
  163. */
  164. public function serviceGetBlockFormRequest()
  165. {
  166. $mixedResult = $this->_oTemplate->getBlockFormRequest();
  167. if(is_array($mixedResult)) {
  168. echoJson($mixedResult);
  169. exit;
  170. }
  171. return array(
  172. 'content' => $mixedResult
  173. );
  174. }
  175. /**
  176. * @page service Service Calls
  177. * @section bx_invites Invitations
  178. * @subsection bx_invites-page_blocks Page Blocks
  179. * @subsubsection bx_invites-get_block_manage_requests get_block_manage_requests
  180. *
  181. * @code bx_srv('bx_invites', 'get_block_manage_requests', [...]); @endcode
  182. *
  183. * Get page block with manage invitation requests table.
  184. *
  185. * @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.
  186. *
  187. * @see BxInvModule::serviceGetBlockManageRequests
  188. */
  189. /**
  190. * @ref bx_invites-get_block_manage_requests "get_block_manage_requests"
  191. */
  192. public function serviceGetBlockManageRequests()
  193. {
  194. $this->_oTemplate->addJs('jquery.form.min.js');
  195. $this->_oTemplate->addJs('main.js');
  196. $oGrid = BxDolGrid::getObjectInstance($this->_oConfig->getObject('grid_requests'));
  197. if(!$oGrid)
  198. return '';
  199. $this->_oTemplate->addCss(array('main.css'));
  200. $this->_oTemplate->addJsTranslation(array('_sys_grid_search'));
  201. return $this->_oTemplate->getJsCode('main') . $oGrid->getCode();
  202. }
  203. /**
  204. * @page service Service Calls
  205. * @section bx_invites Invitations
  206. * @subsection bx_invites-other Other
  207. * @subsubsection bx_invites-get_menu_addon_requests get_menu_addon_requests
  208. *
  209. * @code bx_srv('bx_invites', 'get_menu_addon_requests', [...]); @endcode
  210. *
  211. * Get number or invitation requests.
  212. *
  213. * @return integer value with number of invitation requests.
  214. *
  215. * @see BxInvModule::serviceGetMenuAddonRequests
  216. */
  217. /**
  218. * @ref bx_invites-get_menu_addon_requests "get_menu_addon_requests"
  219. */
  220. public function serviceGetMenuAddonRequests()
  221. {
  222. return $this->_oDb->getRequests(array('type' => 'count_all'));
  223. }
  224. /**
  225. * @page service Service Calls
  226. * @section bx_invites Invitations
  227. * @subsection bx_invites-other Other
  228. * @subsubsection bx_invites-account_add_form_check account_add_form_check
  229. *
  230. * @code bx_srv('bx_invites', 'account_add_form_check', [...]); @endcode
  231. *
  232. * Perform neccessary checking on join form.
  233. *
  234. * @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.
  235. *
  236. * @see BxInvModule::serviceAccountAddFormCheck
  237. */
  238. /**
  239. * @ref bx_invites-account_add_form_check "account_add_form_check"
  240. */
  241. public function serviceAccountAddFormCheck()
  242. {
  243. $sReturn = '';
  244. if (!$this->_oConfig->isRegistrationByInvitation())
  245. return $sReturn;
  246. $oSession = BxDolSession::getInstance();
  247. $sKeyCode = $this->_oConfig->getKeyCode();
  248. $bKey = bx_get($sKeyCode) !== false;
  249. if($bKey) {
  250. $sKey = bx_process_input(bx_get($sKeyCode));
  251. $oKeys = BxDolKey::getInstance();
  252. if($oKeys && $oKeys->isKeyExists($sKey))
  253. $oSession->setValue($sKeyCode, $sKey);
  254. }
  255. $sKey = $oSession->getValue($sKeyCode);
  256. if($sKey !== false)
  257. return $sReturn;
  258. if($bKey)
  259. $sReturn .= MsgBox(_t('_bx_invites_err_used'));
  260. $sReturn .= $this->_oTemplate->getBlockRequest();
  261. return $sReturn;
  262. }
  263. /**
  264. * Data for Notifications module
  265. */
  266. public function serviceGetNotificationsData()
  267. {
  268. $sModule = $this->_aModule['name'];
  269. $sEventPrivacy = $sModule . '_allow_view_event_to';
  270. if(BxDolPrivacy::getObjectInstance($sEventPrivacy) === false)
  271. $sEventPrivacy = '';
  272. return array(
  273. 'handlers' => array(
  274. 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),
  275. ),
  276. 'alerts' => array(
  277. array('unit' => $sModule, 'action' => 'request_notify'),
  278. )
  279. );
  280. }
  281. /**
  282. * Entry post for Notifications module
  283. */
  284. public function serviceGetNotificationsRequest($aEvent)
  285. {
  286. if (getParam('bx_invites_requests_notifictaions') != 'on')
  287. return array();
  288. $aRequest = $this->_oDb->getRequests(array('type' => 'by_id', 'value' => $aEvent['object_id']));
  289. if (!$aRequest)
  290. return array();
  291. $CNF = &$this->_oConfig->CNF;
  292. $sEntryUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URL_REQUESTS']);
  293. return array(
  294. 'entry_sample' => $aRequest['name'] . '(' . $aRequest['email'] . ')',
  295. 'entry_url' => $sEntryUrl,
  296. 'entry_caption' => $aRequest['text'],
  297. 'entry_author' => '',
  298. 'entry_privacy' => '', //may be empty or not specified. In this case Public privacy will be used.
  299. '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.
  300. );
  301. }
  302. public function invite($sType, $sEmails, $sText, $mixedLimit = false, $oForm = null)
  303. {
  304. $iProfileId = $this->getProfileId();
  305. $iAccountId = $this->getAccountId($iProfileId);
  306. $oKeys = BxDolKey::getInstance();
  307. if(!$oKeys || !in_array($sType, array(BX_INV_TYPE_FROM_MEMBER, BX_INV_TYPE_FROM_SYSTEM)))
  308. return false;
  309. $iKeyLifetime = $this->_oConfig->getKeyLifetime();
  310. $sEmailTemplate = '';
  311. switch($sType) {
  312. case BX_INV_TYPE_FROM_MEMBER:
  313. $sEmailTemplate = 'bx_invites_invite_form_message';
  314. break;
  315. case BX_INV_TYPE_FROM_SYSTEM:
  316. $sEmailTemplate = 'bx_invites_invite_by_request_message';
  317. break;
  318. }
  319. if(empty($oForm))
  320. $oForm = $this->getFormObjectInvite();
  321. $aMessage = BxDolEmailTemplates::getInstance()->parseTemplate($sEmailTemplate, array(
  322. 'text' => $sText
  323. ), $iAccountId, $iProfileId);
  324. $aAccountIds = array();
  325. $iDate = time();
  326. $aEmails = preg_split("/[\s\n,;]+/", $sEmails);
  327. if(is_array($aEmails) && !empty($aEmails)){
  328. foreach($aEmails as $sEmail) {
  329. if($mixedLimit !== false && (int)$mixedLimit <= 0)
  330. break;
  331. $sEmail = trim($sEmail);
  332. if(empty($sEmail))
  333. continue;
  334. $sKey = $oKeys->getNewKey(false, $iKeyLifetime);
  335. if(sendMail($sEmail, $aMessage['Subject'], $aMessage['Body'], 0, array('join_url' => $this->getJoinLink($sKey), 'seen_image_url' => $this->getSeenImageUrl($sKey)), BX_EMAIL_SYSTEM)) {
  336. $iInviteId = (int)$this->_oDb->insertInvite($iAccountId, $iProfileId, $sKey, $sEmail, $iDate);
  337. array_push($aAccountIds, $iInviteId);
  338. $this->onInvite($iAccountId, $iProfileId);
  339. if($mixedLimit !== false)
  340. $mixedLimit -= 1;
  341. }
  342. }
  343. }
  344. return $aAccountIds;
  345. }
  346. public function processFormObjectInvite($oForm)
  347. {
  348. $iProfileId = $this->getProfileId();
  349. $iAccountId = $this->getAccountId($iProfileId);
  350. $mixedAllowed = $this->isAllowedInvite($iProfileId);
  351. if($mixedAllowed !== true)
  352. return array(
  353. 'content' => MsgBox($mixedAllowed)
  354. );
  355. $mixedInvites = false;
  356. if(!isAdmin($iAccountId)) {
  357. $iInvited = (int)$this->_oDb->getInvites(array('type' => 'count_by_account', 'value' => $iAccountId));
  358. $mixedInvites = $this->_oConfig->getCountPerUser() - $iInvited;
  359. if($mixedInvites <= 0)
  360. return array(
  361. 'content' => MsgBox(_t('_bx_invites_err_limit_reached'))
  362. );
  363. }
  364. $sEmails = bx_process_input($oForm->getCleanValue('emails'));
  365. $sText = bx_process_pass($oForm->getCleanValue('text'));
  366. $mixedResult = $this->invite(BX_INV_TYPE_FROM_MEMBER, $sEmails, $sText, $mixedInvites, $oForm);
  367. if($mixedResult !== false)
  368. $sResult = _t('_bx_invites_msg_invitation_sent', count($mixedResult));
  369. else
  370. $sResult = _t('_bx_invites_err_not_available');
  371. return $sResult;
  372. }
  373. public function isAllowedInvite($iProfileId, $bPerform = false)
  374. {
  375. $aCheckResult = checkActionModule($iProfileId, 'invite', $this->getName(), $bPerform);
  376. return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
  377. }
  378. public function isAllowedRequest($iProfileId, $bPerform = false)
  379. {
  380. $aCheckResult = checkActionModule($iProfileId, 'request', $this->getName(), $bPerform);
  381. return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
  382. }
  383. public function isAllowedDeleteRequest($iProfileId, $bPerform = false)
  384. {
  385. $aCheckResult = checkActionModule($iProfileId, 'delete request', $this->getName(), $bPerform);
  386. return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
  387. }
  388. public function getProfileId()
  389. {
  390. return isLogged() ? bx_get_logged_profile_id() : 0;
  391. }
  392. public function getProfileObject($iProfileId = 0)
  393. {
  394. $oProfile = BxDolProfile::getInstance($iProfileId);
  395. if (!$oProfile)
  396. $oProfile = BxDolProfileUndefined::getInstance();
  397. return $oProfile;
  398. }
  399. public function getAccountId($iProfileId)
  400. {
  401. $oProfile = $this->getProfileObject($iProfileId);
  402. if($oProfile->id() == 0)
  403. return 0;
  404. return $oProfile->getAccountId();
  405. }
  406. protected function onInvite($iAccountId, $iProfileId)
  407. {
  408. $this->isAllowedInvite($iProfileId, true);
  409. //--- Event -> Invite for Alerts Engine ---//
  410. bx_alert($this->_oConfig->getObject('alert'), 'invite', 0, $iProfileId);
  411. //--- Event -> Invite for Alerts Engine ---//
  412. }
  413. public function onRequest($iRequestId)
  414. {
  415. //--- Event -> Request for Alerts Engine ---//
  416. bx_alert($this->_oConfig->getObject('alert'), 'request', $iRequestId);
  417. $aProfiles = BxDolAclQuery::getInstance()->getProfilesByMembership(array(MEMBERSHIP_ID_MODERATOR, MEMBERSHIP_ID_ADMINISTRATOR));
  418. foreach($aProfiles as $aProfile) {
  419. bx_alert($this->_oConfig->getObject('alert'), 'request_notify', $iRequestId, 0, array('parent_author_id' => $aProfile['id']));
  420. }
  421. //--- Event -> Request for Alerts Engine ---//
  422. }
  423. public function getFormObjectInvite($sDisplay = '')
  424. {
  425. if(empty($sDisplay))
  426. $sDisplay = $this->_oConfig->getObject('form_display_invite_send');
  427. bx_import('FormCheckerHelper', $this->_aModule);
  428. return BxDolForm::getObjectInstance($this->_oConfig->getObject('form_invite'), $sDisplay);
  429. }
  430. protected function getJoinLink($sKey)
  431. {
  432. $sKeyCode = $this->_oConfig->getKeyCode();
  433. $sJoinUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=create-account');
  434. return bx_append_url_params($sJoinUrl, array($sKeyCode => $sKey));
  435. }
  436. protected function getSeenImageUrl($sKey)
  437. {
  438. return BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'SetSeenMark/' . $sKey . "/";
  439. }
  440. public function attachAccountIdToInvite($iAccountId, $sKey)
  441. {
  442. $this->_oDb->attachAccountIdToInvite($iAccountId, $sKey);
  443. }
  444. }
  445. /** @} */