BxDolCacheUtilities.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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 UnaCore UNA Core
  7. * @{
  8. */
  9. // TODO: check if it is used or maybe usefull for future use, also it needs some refactoring
  10. class BxDolCacheUtilities extends BxDol
  11. {
  12. protected $_aCacheTypes = array();
  13. protected $_bRevisionBumped = false; ///< 'sys_revision' is bumped at most once per request even when several caches are cleared
  14. public function __construct ()
  15. {
  16. parent::__construct();
  17. $this->_aCacheTypes = array(
  18. 'content' => array('option' => 'sys_content_cache_enable'),
  19. 'db' => array('option' => 'sys_db_cache_enable'),
  20. 'template' => array('option' => 'sys_template_cache_enable'),
  21. 'less' => array(),
  22. 'css' => array('option' => 'sys_template_cache_css_enable'),
  23. 'js' => array('option' => 'sys_template_cache_js_enable'),
  24. 'purifier' => array(),
  25. 'opcache' => array(),
  26. 'custom' => array(),
  27. );
  28. }
  29. /**
  30. * Get singleton instance of the class
  31. */
  32. public static function getInstance()
  33. {
  34. if(!isset($GLOBALS['bxDolClasses'][__CLASS__]))
  35. $GLOBALS['bxDolClasses'][__CLASS__] = new BxDolCacheUtilities();
  36. return $GLOBALS['bxDolClasses'][__CLASS__];
  37. }
  38. function isEnabled($sCache)
  39. {
  40. if(!isset($this->_aCacheTypes[$sCache]))
  41. return false;
  42. if ('opcache' == $sCache)
  43. return function_exists('opcache_reset');
  44. return !isset($this->_aCacheTypes[$sCache]['option']) || getParam($this->_aCacheTypes[$sCache]['option']) == 'on';
  45. }
  46. function clear($sCache)
  47. {
  48. return $this->_action($sCache, 'clear');
  49. }
  50. function size($sCache, $isFormatted = false)
  51. {
  52. $iSize = $this->_action($sCache, 'size');
  53. return $isFormatted ? sprintf("%.2f", $iSize / 1024 / 1024) : $iSize;
  54. }
  55. protected function _action($sCache, $sMode = 'clear')
  56. {
  57. $mixedResult = false;
  58. if(!$this->isEnabled($sCache))
  59. return $mixedResult;
  60. $bClear = $sMode == 'clear';
  61. $sAction = $bClear ? '_clear' : '_getSize';
  62. $oTemplate = BxDolStudioTemplate::getInstance();
  63. switch ($sCache) {
  64. case 'content':
  65. $oCache = bx_content_cache_obj();
  66. $mixedResult = $this->{$sAction . 'Object'}($oCache, 'content_');
  67. break;
  68. case 'db':
  69. $oCacheDb = BxDolDb::getInstance()->getDbCacheObject();
  70. $this->{$sAction . 'Object'}($oCacheDb, 'menu_');
  71. $mixedResult = $this->{$sAction . 'Object'}($oCacheDb, 'db_');
  72. break;
  73. case 'template':
  74. $oCacheTemplates = $oTemplate->getTemplatesCacheObject();
  75. $mixedResult = $this->{$sAction . 'Object'}($oCacheTemplates, $oTemplate->getCacheFilePrefix($sCache));
  76. break;
  77. case 'less':
  78. $mixedResult = $this->{$sAction . 'File'}($oTemplate->getCacheFilePrefix($sCache), BX_DIRECTORY_PATH_CACHE_PUBLIC);
  79. break;
  80. case 'css':
  81. if($bClear)
  82. $this->clear('less');
  83. $mixedResult = $this->{$sAction . 'File'}($oTemplate->getCacheFilePrefix($sCache), BX_DIRECTORY_PATH_CACHE_PUBLIC);
  84. if($bClear)
  85. $this->_bumpRevision($mixedResult);
  86. break;
  87. case 'js':
  88. $mixedResult = $this->{$sAction . 'File'}($oTemplate->getCacheFilePrefix($sCache), BX_DIRECTORY_PATH_CACHE_PUBLIC);
  89. if($bClear)
  90. $this->_bumpRevision($mixedResult);
  91. break;
  92. default:
  93. $sMethod = $sAction . bx_gen_method_name($sCache);
  94. if(!method_exists($this, $sMethod))
  95. $sMethod = $sAction . 'Unsupported';
  96. $mixedResult = $this->$sMethod();
  97. break;
  98. }
  99. return $mixedResult;
  100. }
  101. /**
  102. * Compiled CSS/JS bundles are served with a long max-age under file names derived from bx_site_hash(),
  103. * which includes the 'sys_revision' option. Bumping it after a successful clear gives the regenerated
  104. * bundles new names, so browsers fetch them instead of reusing stale cached copies.
  105. */
  106. protected function _bumpRevision($aResult)
  107. {
  108. if($this->_bRevisionBumped || !isset($aResult['code']) || $aResult['code'] != 0)
  109. return;
  110. setParam('sys_revision', (int)getParam('sys_revision') + 1);
  111. $this->_bRevisionBumped = true;
  112. }
  113. protected function _clearObject($oCache, $sPrefix)
  114. {
  115. if (!$oCache->removeAllByPrefix ($sPrefix))
  116. return array('code' => 1, 'message' => _t('_adm_dbd_err_c_clean_failed'));
  117. else
  118. return array('code' => 0, 'message' => _t('_adm_dbd_msg_c_clean_success'));
  119. }
  120. protected function _clearFile($sPrefix, $sPath)
  121. {
  122. if (!($rHandler = opendir($sPath)))
  123. return array('code' => 1, 'message' => _t('_adm_dbd_err_c_clean_failed'));
  124. $l = strlen($sPrefix);
  125. while (($sFile = readdir($rHandler)) !== false)
  126. if (0 === strncmp($sFile, $sPrefix, $l))
  127. @unlink($sPath . $sFile);
  128. closedir($rHandler);
  129. return array('code' => 0, 'message' => _t('_adm_dbd_msg_c_clean_success'));
  130. }
  131. protected function _clearPurifier()
  132. {
  133. HTMLPurifier_Bootstrap::registerAutoload();
  134. $oConfig = HTMLPurifier_Config::createDefault();
  135. $oConfig->set('Cache.DefinitionImpl', null);
  136. $oHtmlPurifier = new HTMLPurifier($oConfig);
  137. $oHtmlPurifier->purify('');
  138. return ['code' => 0, 'message' => _t('_adm_dbd_msg_c_clean_success')];
  139. }
  140. protected function _clearOpcache()
  141. {
  142. if(function_exists('opcache_reset'))
  143. opcache_reset();
  144. return ['code' => 0, 'message' => _t('_adm_dbd_msg_c_clean_success')];
  145. }
  146. protected function _clearCustom()
  147. {
  148. return ['code' => 0, 'message' => _t('_adm_dbd_msg_c_clean_success')];
  149. }
  150. protected function _clearUnsupported()
  151. {
  152. return ['code' => 2, 'message' => _t('_adm_dbd_err_c_clean_unsupported')];
  153. }
  154. protected function _getSizeObject($oCache, $sPrefix)
  155. {
  156. return $oCache->getSizeByPrefix ($sPrefix);
  157. }
  158. protected function _getSizeFile($sPrefix, $sPath)
  159. {
  160. if (!($rHandler = opendir($sPath)))
  161. return 0;
  162. $iSize = 0;
  163. $l = strlen($sPrefix);
  164. while (($sFile = readdir($rHandler)) !== false)
  165. if (0 === strncmp($sFile, $sPrefix, $l))
  166. $iSize += filesize($sPath . $sFile);
  167. closedir($rHandler);
  168. return $iSize;
  169. }
  170. protected function _getSizeOpcache()
  171. {
  172. if(!function_exists('opcache_get_status'))
  173. return 0;
  174. $mixedResult = opcache_get_status();
  175. if(empty($mixedResult) || !is_array($mixedResult))
  176. return 0;
  177. return isset($mixedResult['memory_usage'], $mixedResult['memory_usage']['used_memory']) ? $mixedResult['memory_usage']['used_memory'] : 0;
  178. }
  179. protected function _getSizeUnsupported()
  180. {
  181. return 0;
  182. }
  183. }
  184. /** @} */