BxDolAlerts.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php defined('BX_DOL') or defined('BX_DOL_INSTALL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaCore UNA Core
  7. * @{
  8. */
  9. bx_import('BxDolDb');
  10. /**
  11. * # Alert/Handler/Hooks engine.
  12. *
  13. * Is needed to fire some alert(event) in one place and caught it with a handler somewhere else.
  14. *
  15. * Related classes:
  16. * BxDolAlertsResponse - abstract class for all response classes.
  17. *
  18. * ### Example of usage:
  19. *
  20. * **First** Fire an alert
  21. *
  22. * @code
  23. * $oZ = new BxDolAlerts('unit_name', 'action', 'object_id', 'sender_id', array('of_extra_params'));
  24. * $oZ->alert();
  25. * @endcode
  26. * or
  27. * @code
  28. * bx_alert('unit_name', 'action', 'object_id', 'sender_id', ['extra', 'params']);
  29. * @endcode
  30. *
  31. * **Second** Add handler and caught alert(s)
  32. * a. Create Response class by extending BxDolAlertsResponse class. It should process all necessary alerts which are passed to it.
  33. * b. Register your handler in the database by adding it in `sys_alerts_handlers` table.
  34. * c. Associate necessary alerts with the handler by adding them in the `sys_alerts` table.
  35. */
  36. class BxDolAlerts extends BxDol
  37. {
  38. public $sUnit;
  39. public $sAction;
  40. public $iObject;
  41. public $iSender;
  42. public $aExtras;
  43. protected $_aAlerts;
  44. protected $_aHandlers;
  45. protected $_aCacheTriggers;
  46. protected $_aCacheTriggersMarkers;
  47. protected $_oCacheObject;
  48. protected static $_aCacheData;
  49. /**
  50. * Constructor
  51. * @param string $sType - system type
  52. * @param string $sAction - system action
  53. * @param int $iObjectId - object id
  54. * @param int $iSenderId - sender (action's author) profile id, if it is false - then currectly logged in profile id is used
  55. */
  56. public function __construct($sUnit, $sAction, $iObjectId, $iSender = false, $aExtras = array())
  57. {
  58. parent::__construct();
  59. if (!isset(self::$_aCacheData))
  60. self::$_aCacheData = $this->getAlertsData();
  61. $this->_aAlerts = self::$_aCacheData['alerts'];
  62. $this->_aHandlers = self::$_aCacheData['handlers'];
  63. $this->_aCacheTriggers = isset(self::$_aCacheData['cache_triggers']) ? self::$_aCacheData['cache_triggers'] : [];
  64. $this->sUnit = $sUnit;
  65. $this->sAction = $sAction;
  66. $this->iObject = $iObjectId;
  67. $this->aExtras = $aExtras;
  68. if (false === $iSender) {
  69. $oProfile = BxDolProfile::getInstance();
  70. $this->iSender = $oProfile ? $oProfile->id() : 0;
  71. } else {
  72. $this->iSender = (int)$iSender;
  73. }
  74. if (getParam('sys_db_cache_enable')) {
  75. $this->_aCacheTriggersMarkers = $this->aExtras;
  76. $this->_aCacheTriggersMarkers['_alert_content'] = $this->iObject;
  77. $this->_aCacheTriggersMarkers['_alert_sender'] = $this->iSender;
  78. $this->_aCacheTriggersMarkers['_hash'] = bx_site_hash();
  79. $sEngine = getParam('sys_db_cache_engine');
  80. $this->_oCacheObject = bx_instance('BxDolCache'.$sEngine);
  81. if(!$this->_oCacheObject->isAvailable())
  82. $this->_oCacheObject = bx_instance('BxDolCacheFile');
  83. }
  84. }
  85. public static function cacheInvalidate()
  86. {
  87. return BxDolDb::getInstance()->cleanCache ('sys_alerts');
  88. }
  89. /**
  90. * Notifies the necessary handlers about the alert.
  91. */
  92. public function alert()
  93. {
  94. if (isset($this->_aAlerts[$this->sUnit]) && isset($this->_aAlerts[$this->sUnit][$this->sAction]))
  95. foreach($this->_aAlerts[$this->sUnit][$this->sAction] as $iHandlerId) {
  96. $aHandler = $this->_aHandlers[$iHandlerId];
  97. if(!$aHandler['active'])
  98. continue;
  99. if (isset($GLOBALS['bx_profiler']) && 'bx_profiler' != $aHandler['name'])
  100. $GLOBALS['bx_profiler']->beginAlert($this->sUnit, $this->sAction, $aHandler['name']);
  101. if (!empty($aHandler['file']) && !empty($aHandler['class']) && file_exists(BX_DIRECTORY_PATH_ROOT . $aHandler['file'])) {
  102. if(!class_exists($aHandler['class'], false))
  103. require_once(BX_DIRECTORY_PATH_ROOT . $aHandler['file']);
  104. $oHandler = new $aHandler['class']();
  105. $oHandler->response($this);
  106. } else if(!empty($aHandler['service_call']) && BxDolService::isSerializedService($aHandler['service_call'])) {
  107. $aService = unserialize($aHandler['service_call']);
  108. $aParams = array($this);
  109. if(isset($aService['params']) && is_array($aService['params']))
  110. $aParams = array_merge($aParams, $aService['params']);
  111. BxDolService::call($aService['module'], $aService['method'], $aParams, isset($aService['class']) ? $aService['class'] : 'Module');
  112. }
  113. if (isset($GLOBALS['bx_profiler']) && 'bx_profiler' != $aHandler['name'])
  114. $GLOBALS['bx_profiler']->endAlert($this->sUnit, $this->sAction, $aHandler['name']);
  115. }
  116. // process cache triggers
  117. if ($this->_oCacheObject && isset($this->_aCacheTriggers[$this->sUnit]) && isset($this->_aCacheTriggers[$this->sUnit][$this->sAction])) {
  118. foreach($this->_aCacheTriggers[$this->sUnit][$this->sAction] as $a) {
  119. $a['cache_key'] = preg_replace_callback('/({[\d\w]+})/', function ($m) {
  120. $sKey = trim($m[1], '{}');
  121. return $this->_aCacheTriggersMarkers[$sKey];
  122. }, $a['cache_key']);
  123. $this->_oCacheObject->delData($a['cache_key']);
  124. }
  125. }
  126. }
  127. /**
  128. * Cache alerts and handlers.
  129. *
  130. * @return an array with all alerts and handlers.
  131. */
  132. public function getAlertsData()
  133. {
  134. $oDb = BxDolDb::getInstance();
  135. $aResult = array('alerts' => array(), 'handlers' => array());
  136. $aAlerts = $oDb->getAll("SELECT `unit`, `action`, `handler_id` FROM `sys_alerts` ORDER BY `id` ASC");
  137. foreach ($aAlerts as $aAlert)
  138. $aResult['alerts'][$aAlert['unit']][$aAlert['action']][] = $aAlert['handler_id'];
  139. $aHandlers = $oDb->getAll("SELECT * FROM `sys_alerts_handlers` ORDER BY `id` ASC");
  140. foreach ($aHandlers as $aHandler)
  141. $aResult['handlers'][$aHandler['id']] = [
  142. 'name' => $aHandler['name'],
  143. 'class' => $aHandler['class'],
  144. 'file' => $aHandler['file'],
  145. 'service_call' => $aHandler['service_call'],
  146. 'active' => (int)$aHandler['active']
  147. ];
  148. $aCacheTriggers = $oDb->getAll("SELECT * FROM `sys_alerts_cache_triggers` ORDER BY `id` ASC");
  149. $aResult['cache_triggers'] = [];
  150. foreach ($aCacheTriggers as $r)
  151. $aResult['cache_triggers'][$r['unit']][$r['action']][] = [
  152. 'cache_key' => $r['cache_key'],
  153. ];
  154. return $aResult;
  155. }
  156. }
  157. class BxDolAlertsResponse extends BxDol
  158. {
  159. public function __construct()
  160. {
  161. parent::__construct();
  162. }
  163. public function response($oAlert) {}
  164. }
  165. /** @} */