BxNtfsCronNotify.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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 Notifications Notifications
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. /**
  12. * Get notifications list and retrieve recipients for each notification. Put emails in:
  13. * a) internal queue, if Delivery Timeout is set,
  14. * b) system queue otherwise
  15. */
  16. class BxNtfsCronNotify extends BxDolCron
  17. {
  18. protected $_sModule;
  19. protected $_oModule;
  20. protected $_bOwnActions;
  21. protected $_bEventsGroupedDb;
  22. protected $_bDeliveryTimeout;
  23. public function __construct()
  24. {
  25. $this->_sModule = 'bx_notifications';
  26. $this->_oModule = BxDolModule::getInstance($this->_sModule);
  27. parent::__construct();
  28. $CNF = &$this->_oModule->_oConfig->CNF;
  29. $this->_bOwnActions = getParam($CNF['PARAM_OWN_ACTIONS']) == 'on';
  30. $this->_bEventsGroupedDb = $this->_oModule->_oConfig->isEventsGroupedDb();
  31. $this->_bDeliveryTimeout = $this->_oModule->_oConfig->getDeliveryTimeout() > 0;
  32. }
  33. public function processing()
  34. {
  35. $CNF = &$this->_oModule->_oConfig->CNF;
  36. if($this->_bDeliveryTimeout) {
  37. $iCount = (int)$this->_oModule->_oDb->queueGet(['type' => 'count']);
  38. if($iCount > (int)getParam($CNF['PARAM_QUEUE_ADD_THRESHOLD']))
  39. return;
  40. }
  41. $aEvents = $this->_oModule->_oDb->getEventsToProcess((int)getParam($CNF['PARAM_QUEUE_ADD_LIMIT']));
  42. foreach($aEvents as $aEvent) {
  43. if(!empty($aEvent['content']) && is_string($aEvent['content']))
  44. $aEvent['content'] = unserialize($aEvent['content']);
  45. $this->_processNotifications($aEvent);
  46. }
  47. if($this->_bEventsGroupedDb && ($aProfiles = $this->_oModule->_oDb->aggregatorGetProfiles()) && is_array($aProfiles))
  48. foreach($aProfiles as $iProfile) {
  49. $aEventsIds = [];
  50. foreach([BX_BASE_MOD_NTFS_DTYPE_EMAIL, BX_BASE_MOD_NTFS_DTYPE_PUSH] as $sDeliveryType) {
  51. $sMethodGet = 'getNotification' . bx_gen_method_name($sDeliveryType);
  52. $aEvents = $this->_oModule->_oDb->aggregatorGetEvents($iProfile, $sDeliveryType);
  53. foreach($aEvents as $aEvent) {
  54. if(($sGroupedByMac = $aEvent['grouped_by_mac'] ?? false))
  55. $aEventsIds = array_merge($aEventsIds, explode(',', $sGroupedByMac));
  56. $sEvent = $this->_oModule->_oTemplate->getPost($aEvent, ['perform_privacy_check_for' => $iProfile, 'show_real_profile' => false]);
  57. if(empty($sEvent) || empty($aEvent['content_parsed']))
  58. continue;
  59. $mixedNotification = false;
  60. if(($mixedNotification = $this->_oModule->_oTemplate->$sMethodGet($iProfile, $aEvent)) === false)
  61. continue;
  62. $this->_sendNotification($iProfile, $aEvent['id'], $sDeliveryType, $mixedNotification);
  63. }
  64. }
  65. $this->_oModule->_oDb->aggregatorDelete($iProfile, array_unique($aEventsIds));
  66. }
  67. }
  68. protected function _processNotifications(&$aEvent)
  69. {
  70. $aHandler = $this->_oModule->_oConfig->getHandlers($aEvent['type'] . '_' . $aEvent['action']);
  71. if(empty($aHandler) || !is_array($aHandler))
  72. return;
  73. $aDeliveryTypes = [];
  74. $iId = (int)$aEvent['id'];
  75. $iSilentMode = $this->_oModule->getSilentMode($aEvent['content']);
  76. switch($iSilentMode) {
  77. case BX_BASE_MOD_NTFS_SLTMODE_ABSOLUTE:
  78. case BX_NTFS_SLTMODE_ABSOLUTE:
  79. case BX_NTFS_SLTMODE_SITE:
  80. return;
  81. case BX_NTFS_SLTMODE_SITE_EMAIL:
  82. $aDeliveryTypes[] = BX_BASE_MOD_NTFS_DTYPE_EMAIL;
  83. break;
  84. case BX_NTFS_SLTMODE_SITE_PUSH:
  85. $aDeliveryTypes[] = BX_BASE_MOD_NTFS_DTYPE_PUSH;
  86. break;
  87. default:
  88. $aDeliveryTypes = [BX_BASE_MOD_NTFS_DTYPE_EMAIL, BX_BASE_MOD_NTFS_DTYPE_PUSH];
  89. }
  90. $aSendUsing = [];
  91. foreach($aDeliveryTypes as $sDeliveryType) {
  92. $aHidden = $this->_oModule->_oConfig->getHandlersHidden($sDeliveryType);
  93. if(in_array($aHandler['id'], $aHidden))
  94. continue;
  95. $sMethod = 'Notification' . bx_gen_method_name($sDeliveryType);
  96. $sMethodGet = 'get' . $sMethod;
  97. if(!$this->_oModule->_oTemplate->isMethodExists($sMethodGet) || !method_exists($this->_oModule, 'send' . $sMethod))
  98. continue;
  99. $aSendUsing[$sDeliveryType] = $sMethodGet;
  100. }
  101. if(empty($aSendUsing) || !is_array($aSendUsing))
  102. return;
  103. $iOwner = (int)$aEvent['owner_id'];
  104. $aRecipients = [];
  105. //--- Get recipients: Subscribers.
  106. $oConnection = BxDolConnection::getObjectInstance($this->_oModule->_oConfig->getObject('conn_subscriptions'));
  107. $aSubscribers = $oConnection->getConnectedInitiators($iOwner);
  108. if(!empty($aSubscribers) && is_array($aSubscribers)) {
  109. $oOwner = BxDolProfile::getInstance($iOwner);
  110. if(!empty($oOwner)) {
  111. $sSettingType = bx_srv($oOwner->getModule(), 'act_as_profile') ? BX_NTFS_STYPE_FOLLOW_MEMBER : BX_NTFS_STYPE_FOLLOW_CONTEXT;
  112. foreach($aSubscribers as $iSubscriber)
  113. $this->_addRecipient($iSubscriber, $sSettingType, $aRecipients);
  114. }
  115. }
  116. //--- Get recipients: Content owner.
  117. $iObjectOwner = (int)$aEvent['object_owner_id'];
  118. if($iOwner != $iObjectOwner)
  119. $this->_addRecipient($iObjectOwner, BX_NTFS_STYPE_PERSONAL, $aRecipients);
  120. //--- Check recipients and send notifications.
  121. list($aModulesProfiles) = $this->_oModule->_oConfig->getProfileBasedModules();
  122. $aRecipientsId = $this->_oModule->_oDb->filterProfileIdsByModule(array_keys($aRecipients), $aModulesProfiles);
  123. $aRecipients = array_intersect_key($aRecipients, array_flip($aRecipientsId));
  124. $oPrivacyInt = BxDolPrivacy::getObjectInstance($this->_oModule->_oConfig->getObject('privacy_view'));
  125. $oPrivacyExt = $this->_oModule->_oConfig->getPrivacyObject($aEvent['type'] . '_' . $aEvent['action']);
  126. foreach($aRecipients as $iRecipient => $aSettingTypes) {
  127. $iIdRead = $this->_oModule->_oDb->getLastRead($iRecipient);
  128. if($iIdRead >= $iId)
  129. continue;
  130. if(!$this->_bOwnActions && $aEvent['author_id'] == $iRecipient)
  131. continue;
  132. if($oPrivacyExt !== false && !$oPrivacyExt->check($aEvent['id'], $iRecipient))
  133. continue;
  134. if($oPrivacyInt !== false && !$oPrivacyInt->check($aEvent['id'], $iRecipient))
  135. continue;
  136. /**
  137. * Check if the Recipient can view the notification.
  138. */
  139. $sEvent = $this->_oModule->_oTemplate->getPost($aEvent, ['perform_privacy_check_for' => $iRecipient, 'show_real_profile' => false]);
  140. if(empty($sEvent) || empty($aEvent['content_parsed']))
  141. continue;
  142. foreach($aSendUsing as $sDeliveryType => $sDeliveryTypeGet) {
  143. $mixedNotification = false;
  144. if(!$this->_bEventsGroupedDb && ($mixedNotification = $this->_oModule->_oTemplate->$sDeliveryTypeGet($iRecipient, $aEvent)) === false)
  145. continue;
  146. foreach($aSettingTypes as $sSettingType) {
  147. $aSetting = $this->_oModule->_oDb->getSetting(['by' => 'tsu_allowed', 'handler_id' => $aHandler['id'], 'delivery' => $sDeliveryType, 'type' => $sSettingType, 'user_id' => $iRecipient]);
  148. if(empty($aSetting) || !is_array($aSetting))
  149. continue;
  150. if((int)$aSetting['active_adm'] == 0 || (int)$aSetting['active_pnl'] == 0)
  151. continue;
  152. if($this->_bEventsGroupedDb) {
  153. $this->_oModule->_oDb->aggregatorAdd([
  154. 'profile_id' => $iRecipient,
  155. 'event_id' => $aEvent['id'],
  156. 'delivery' => $sDeliveryType
  157. ]);
  158. break;
  159. }
  160. /**
  161. * (break) is essential to avoid duplicate sending to the same recipient.
  162. */
  163. if($this->_sendNotification($iRecipient, $aEvent['id'], $sDeliveryType, $mixedNotification) !== false)
  164. break;
  165. }
  166. }
  167. }
  168. }
  169. protected function _addRecipient($iUser, $sSettingType, &$aRecipients)
  170. {
  171. if(!isset($aRecipients[$iUser]))
  172. $aRecipients[$iUser] = [];
  173. $aRecipients[$iUser][] = $sSettingType;
  174. }
  175. private function _sendNotification($iRecipient, $iEventId, $sDeliveryType, $aNotification)
  176. {
  177. /**
  178. * 'return true' (break) is essential to avoid duplicate sending to the same recipient.
  179. * Don't send directly if message was successfully queued.
  180. */
  181. if($this->_bDeliveryTimeout && $this->_oModule->_oDb->queueAdd([
  182. 'profile_id' => $iRecipient,
  183. 'event_id' => $iEventId,
  184. 'delivery' => $sDeliveryType,
  185. 'content' => serialize($aNotification),
  186. 'date' => time()
  187. ]) !== false)
  188. return true;
  189. /**
  190. * 'return true' (break) is essential to avoid duplicate sending to the same recipient.
  191. * If a message was sent as 'personal', don't send it by subscription ('follow_member', 'follow_context').
  192. */
  193. if($this->_oModule->{'sendNotification' . bx_gen_method_name($sDeliveryType)}($iRecipient, $aNotification) !== false)
  194. return true;
  195. return false;
  196. }
  197. }
  198. /** @} */