BxDolLiveUpdates.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  4. * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  5. *
  6. * @defgroup TridentCore Trident Core
  7. * @{
  8. */
  9. /**
  10. * @page objects
  11. * @section live updates Live Updates
  12. * @ref BxDolLiveUpdates
  13. */
  14. class BxDolLiveUpdates extends BxDol
  15. {
  16. protected $_oQuery;
  17. protected $_aSystems;
  18. protected $_aSystemsActive;
  19. protected $_iInterval;
  20. protected $_iCacheTTL;
  21. protected $_sCacheKey;
  22. protected $_sJsClass;
  23. protected $_sJsObject;
  24. public function __construct()
  25. {
  26. parent::__construct();
  27. $this->_oQuery = new BxDolLiveUpdatesQuery();
  28. $this->_iInterval = (int)$this->_oQuery->getParam('sys_live_updates_interval');
  29. $this->_iCacheTTL = 86400;
  30. $this->_sCacheKey = 'sys_live_updates_' . bx_get_logged_profile_id();
  31. $this->_sJsClass = 'BxDolLiveUpdates';
  32. $this->_sJsObject = 'oLiveUpdates';
  33. $this->_aSystemsActive = array();
  34. $this->_aSystems = $this->_getCachedSystems();
  35. }
  36. /**
  37. * get live updates instanse
  38. * @return ready to use class instance
  39. */
  40. public static function getInstance()
  41. {
  42. if(!isset($GLOBALS['bxDolClasses'][__CLASS__]))
  43. $GLOBALS['bxDolClasses'][__CLASS__] = new BxTemplLiveUpdates();
  44. return $GLOBALS['bxDolClasses'][__CLASS__];
  45. }
  46. /**
  47. *
  48. * Is called via Ajax Requests only.
  49. */
  50. public function perform()
  51. {
  52. $iIndex = (int)bx_get('index');
  53. $mixedSystemsActive = bx_get('systems_active');
  54. if($mixedSystemsActive !== false)
  55. $this->_aSystemsActive = $mixedSystemsActive;
  56. $this->_aSystems = $this->_getCachedSystems();
  57. if(empty($this->_aSystems) || !is_array($this->_aSystems))
  58. return array();
  59. $aCached = $this->_getCachedData();
  60. $aRequested = $this->_getRequestedData($iIndex, true, $aCached);
  61. $aResult = array();
  62. $bUpdateCache = false;
  63. foreach($aRequested as $sName => $aData) {
  64. $bCached = isset($aCached[$sName]);
  65. if($bCached && (int)$aCached[$sName] == (int)$aData['count'])
  66. continue;
  67. if($bCached) {
  68. $aResultData = array('count_new' => $aData['count'], 'count_old' => $aCached[$sName]);
  69. if(isset($aData['data']))
  70. $aResultData = array_merge($aResultData, $aData['data']);
  71. $aResult[] = array(
  72. 'data' => $aResultData,
  73. 'method' => $aData['method']
  74. );
  75. }
  76. $aCached[$sName] = $aData['count'];
  77. $bUpdateCache = true;
  78. }
  79. if($bUpdateCache)
  80. $this->_updateCached('data', $aCached);
  81. return $aResult;
  82. }
  83. /**
  84. *
  85. * Add transient live update for current user on this current page.
  86. * @param string $sName - unique name.
  87. * @param integer $iFrequency - call frequency.
  88. * @param string $sServiceCall - serialized service call.
  89. * @param boolean $bActive - add active/not active live update.
  90. */
  91. public function add($sName, $iFrequency, $sServiceCall, $bActive = true)
  92. {
  93. if(!in_array($sName, $this->_aSystemsActive))
  94. $this->_aSystemsActive[] = $sName;
  95. if(empty($this->_aSystems[$sName])) {
  96. $this->_aSystems[$sName] = array(
  97. 'name' => $sName,
  98. 'frequency' => $iFrequency,
  99. 'service_call' => $sServiceCall,
  100. 'active' => $bActive ? 1 : 0
  101. );
  102. $this->_updateCached('systems', $this->_aSystems);
  103. }
  104. $mixedResponce = $this->_getRequestedDataBySystem($this->_aSystems[$sName]);
  105. if($mixedResponce !== false) {
  106. $aCachedData = $this->_getCachedData();
  107. $aCachedData[$sName] = $mixedResponce['count'];
  108. $this->_updateCached('data', $aCachedData);
  109. }
  110. return true;
  111. }
  112. protected function _getCacheInfo()
  113. {
  114. return array(
  115. $this->_oQuery->getDbCacheObject(),
  116. $this->_oQuery->genDbCacheKey($this->_sCacheKey),
  117. $this->_iCacheTTL
  118. );
  119. }
  120. protected function _getCached($sType)
  121. {
  122. list($oCache, $sCacheKey, $iCacheTtl) = $this->_getCacheInfo();
  123. $aCached = $oCache->getData($sCacheKey, $iCacheTtl);
  124. if(empty($aCached[$sType])) {
  125. switch($sType) {
  126. case 'systems':
  127. $aCached[$sType] = $this->_oQuery->getSystems();
  128. break;
  129. case 'data':
  130. $aRequested = $this->_getRequestedData();
  131. foreach($aRequested as $sName => $aData)
  132. $aCached[$sType][$sName] = $aData['count'];
  133. break;
  134. }
  135. if(!empty($aCached[$sType]))
  136. $oCache->setData($sCacheKey, $aCached, $iCacheTtl);
  137. }
  138. return $aCached[$sType];
  139. }
  140. protected function _getCachedSystems()
  141. {
  142. $aSystems = $this->_getCached('systems');
  143. if(!empty($aSystems) && !empty($this->_aSystemsActive))
  144. $aSystems = array_intersect_key($aSystems, array_flip($this->_aSystemsActive));
  145. return $aSystems;
  146. }
  147. protected function _getCachedData()
  148. {
  149. return $this->_getCached('data');
  150. }
  151. protected function _updateCached($sKey, $aData)
  152. {
  153. list($oCache, $sCacheKey, $iCacheTtl) = $this->_getCacheInfo();
  154. $aCached = $oCache->getData($sCacheKey, $iCacheTtl);
  155. $aCached[$sKey] = $aData;
  156. $oCache->setData($sCacheKey, $aCached, $iCacheTtl);
  157. }
  158. protected function _getRequestedData($iIndex = 0, $bIndexCheck = false, $aCachedData = array())
  159. {
  160. $aResult = array();
  161. foreach($this->_aSystems as $sName => $aSystem) {
  162. if(empty($aSystem) || !is_array($aSystem) || (int)$aSystem['active'] != 1)
  163. continue;
  164. if($bIndexCheck && $iIndex % (int)$aSystem['frequency'] != 0)
  165. continue;
  166. $mixedResponce = $this->_getRequestedDataBySystem($aSystem, (!empty($aCachedData) && isset($aCachedData[$sName]) ? (int)$aCachedData[$sName] : 0));
  167. if($mixedResponce === false)
  168. continue;
  169. $aResult[$sName] = $mixedResponce;
  170. }
  171. return $aResult;
  172. }
  173. protected function _getRequestedDataBySystem($aSystem, $iCachedData = 0)
  174. {
  175. if(!BxDolService::isSerializedService($aSystem['service_call']))
  176. return false;
  177. $aResponce = BxDolService::callSerialized($aSystem['service_call'], array('count' => (int)$iCachedData));
  178. if(empty($aResponce) || !is_array($aResponce) || !isset($aResponce['count'], $aResponce['method']))
  179. return false;
  180. return $aResponce;
  181. }
  182. }
  183. /** @} */