PageRenderTime 100ms CodeModel.GetById 47ms RepoModel.GetById 17ms app.codeStats 1ms

/wp-content/plugins/w3-total-cache/lib/W3/ObjectCache.php

https://gitlab.com/endomorphosis/jeffersonsmithmayor
PHP | 627 lines | 302 code | 103 blank | 222 comment | 50 complexity | 0217756cf8b81230ab48618fb589b8ac MD5 | raw file
  1. <?php
  2. /**
  3. * W3 Object Cache object
  4. */
  5. class W3_ObjectCache {
  6. /**
  7. * Internal cache array
  8. *
  9. * @var array
  10. */
  11. var $cache = array();
  12. /**
  13. * Array of global groups
  14. *
  15. * @var array
  16. */
  17. var $global_groups = array();
  18. /**
  19. * List of non-persistent groups
  20. *
  21. * @var array
  22. */
  23. var $nonpersistent_groups = array();
  24. /**
  25. * Total count of calls
  26. *
  27. * @var integer
  28. */
  29. var $cache_total = 0;
  30. /**
  31. * Cache hits count
  32. *
  33. * @var integer
  34. */
  35. var $cache_hits = 0;
  36. /**
  37. * Cache misses count
  38. *
  39. * @var integer
  40. */
  41. var $cache_misses = 0;
  42. /**
  43. * Total time
  44. *
  45. * @var integer
  46. */
  47. var $time_total = 0;
  48. /**
  49. * Store debug information of w3tc using
  50. *
  51. * @var array
  52. */
  53. var $debug_info = array();
  54. /**
  55. * Key cache
  56. *
  57. * @var array
  58. */
  59. var $_key_cache = array();
  60. /**
  61. * Config
  62. *
  63. * @var W3_Config
  64. */
  65. var $_config = null;
  66. /**
  67. * Caching flag
  68. *
  69. * @var boolean
  70. */
  71. var $_caching = false;
  72. /**
  73. * Cache reject reason
  74. *
  75. * @var string
  76. */
  77. var $_cache_reject_reason = '';
  78. /**
  79. * Lifetime
  80. *
  81. * @var integer
  82. */
  83. var $_lifetime = null;
  84. /**
  85. * Debug flag
  86. *
  87. * @var boolean
  88. */
  89. var $_debug = false;
  90. /**
  91. * Returns instance. for backward compatibility with 0.9.2.3 version of /wp-content files
  92. *
  93. * @return W3_ObjectCache
  94. */
  95. function &instance() {
  96. return w3_instance('W3_ObjectCache');
  97. }
  98. /**
  99. * PHP5 style constructor
  100. */
  101. function __construct() {
  102. global $_wp_using_ext_object_cache;
  103. $this->_config = & w3_instance('W3_Config');
  104. $this->_lifetime = $this->_config->get_integer('objectcache.lifetime');
  105. $this->_debug = $this->_config->get_boolean('objectcache.debug');
  106. $this->_caching = $_wp_using_ext_object_cache = $this->_can_cache();
  107. $this->global_groups = $this->_config->get_array('objectcache.groups.global');
  108. $this->nonpersistent_groups = $this->_config->get_array('objectcache.groups.nonpersistent');
  109. if ($this->_can_ob()) {
  110. ob_start(array(
  111. &$this,
  112. 'ob_callback'
  113. ));
  114. }
  115. }
  116. /**
  117. * PHP4 style constructor
  118. */
  119. function W3_ObjectCache() {
  120. $this->__construct();
  121. }
  122. /**
  123. * Get from the cache
  124. *
  125. * @param string $id
  126. * @param string $group
  127. * @return mixed
  128. */
  129. function get($id, $group = 'default') {
  130. if ($this->_debug) {
  131. $time_start = w3_microtime();
  132. }
  133. $key = $this->_get_cache_key($id, $group);
  134. $internal = isset($this->cache[$key]);
  135. if ($internal) {
  136. $value = $this->cache[$key];
  137. } elseif ($this->_caching && !in_array($group, $this->nonpersistent_groups)) {
  138. $cache = & $this->_get_cache();
  139. $value = $cache->get($key);
  140. } else {
  141. $value = false;
  142. }
  143. if ($value === null) {
  144. $value = false;
  145. }
  146. if (is_object($value)) {
  147. $value = wp_clone($value);
  148. }
  149. $this->cache[$key] = $value;
  150. $this->cache_total++;
  151. if ($value !== false) {
  152. $cached = true;
  153. $this->cache_hits++;
  154. } else {
  155. $cached = false;
  156. $this->cache_misses++;
  157. }
  158. /**
  159. * Add debug info
  160. */
  161. if ($this->_debug) {
  162. $time = w3_microtime() - $time_start;
  163. $this->time_total += $time;
  164. if (!$group) {
  165. $group = 'default';
  166. }
  167. $this->debug_info[] = array(
  168. 'id' => $id,
  169. 'group' => $group,
  170. 'cached' => $cached,
  171. 'internal' => $internal,
  172. 'data_size' => ($value ? strlen(serialize($value)) : 0),
  173. 'time' => $time
  174. );
  175. }
  176. return $value;
  177. }
  178. /**
  179. * Set to the cache
  180. *
  181. * @param string $id
  182. * @param mixed $data
  183. * @param string $group
  184. * @param integer $expire
  185. * @return boolean
  186. */
  187. function set($id, $data, $group = 'default', $expire = 0) {
  188. $key = $this->_get_cache_key($id, $group);
  189. if (is_object($data)) {
  190. $data = wp_clone($data);
  191. }
  192. $this->cache[$key] = $data;
  193. if ($this->_caching && !in_array($group, $this->nonpersistent_groups)) {
  194. $cache = & $this->_get_cache();
  195. return $cache->set($key, $data, ($expire ? $expire : $this->_lifetime));
  196. }
  197. return true;
  198. }
  199. /**
  200. * Delete from the cache
  201. *
  202. * @param string $id
  203. * @param string $group
  204. * @param bool $force
  205. * @return boolean
  206. */
  207. function delete($id, $group = 'default', $force = false) {
  208. if (!$force && $this->get($id, $group) === false) {
  209. return false;
  210. }
  211. $key = $this->_get_cache_key($id, $group);
  212. unset($this->cache[$key]);
  213. if ($this->_caching && !in_array($group, $this->nonpersistent_groups)) {
  214. $cache = & $this->_get_cache();
  215. return $cache->delete($key);
  216. }
  217. return true;
  218. }
  219. /**
  220. * Add to the cache
  221. *
  222. * @param string $id
  223. * @param mixed $data
  224. * @param string $group
  225. * @param integer $expire
  226. * @return boolean
  227. */
  228. function add($id, $data, $group = 'default', $expire = 0) {
  229. if ($this->get($id, $group) !== false) {
  230. return false;
  231. }
  232. return $this->set($id, $data, $group, $expire);
  233. }
  234. /**
  235. * Replace in the cache
  236. *
  237. * @param string $id
  238. * @param mixed $data
  239. * @param string $group
  240. * @param integer $expire
  241. * @return boolean
  242. */
  243. function replace($id, $data, $group = 'default', $expire = 0) {
  244. if ($this->get($id, $group) === false) {
  245. return false;
  246. }
  247. return $this->set($id, $data, $group, $expire);
  248. }
  249. /**
  250. * Reset keys
  251. *
  252. * @return boolean
  253. */
  254. function reset() {
  255. global $_wp_using_ext_object_cache;
  256. $_wp_using_ext_object_cache = $this->_caching;
  257. return true;
  258. }
  259. /**
  260. * Flush cache
  261. *
  262. * @return boolean
  263. */
  264. function flush() {
  265. $this->cache = array();
  266. if ($this->_caching) {
  267. $cache = & $this->_get_cache();
  268. return $cache->flush();
  269. }
  270. return true;
  271. }
  272. /**
  273. * Add global groups
  274. *
  275. * @param array $groups
  276. * @return void
  277. */
  278. function add_global_groups($groups) {
  279. if (!is_array($groups)) {
  280. $groups = (array) $groups;
  281. }
  282. $this->global_groups = array_merge($this->global_groups, $groups);
  283. $this->global_groups = array_unique($this->global_groups);
  284. }
  285. /**
  286. * Add non-persistent groups
  287. *
  288. * @param array $groups
  289. * @return void
  290. */
  291. function add_nonpersistent_groups($groups) {
  292. if (!is_array($groups)) {
  293. $groups = (array) $groups;
  294. }
  295. $this->nonpersistent_groups = array_merge($this->nonpersistent_groups, $groups);
  296. $this->nonpersistent_groups = array_unique($this->nonpersistent_groups);
  297. }
  298. /**
  299. * Output buffering callback
  300. *
  301. * @param string $buffer
  302. * @return string
  303. */
  304. function ob_callback(&$buffer) {
  305. if ($buffer != '' && w3_is_xml($buffer)) {
  306. $buffer .= "\r\n\r\n" . $this->_get_debug_info();
  307. }
  308. return $buffer;
  309. }
  310. /**
  311. * Print Object Cache stats
  312. *
  313. * @return void
  314. */
  315. function stats()
  316. {
  317. echo '<h2>Summary</h2>';
  318. echo '<p>';
  319. echo '<strong>Engine</strong>: ' . w3_get_engine_name($this->_config->get_string('objectcache.engine')) . '<br />';
  320. echo '<strong>Caching</strong>: ' . ($this->_caching ? 'enabled' : 'disabled') . '<br />';
  321. if (!$this->_caching) {
  322. echo '<strong>Reject reason</strong>: ' . $this->_cache_reject_reason . '<br />';
  323. }
  324. echo '<strong>Total calls</strong>: ' . $this->cache_total . '<br />';
  325. echo '<strong>Cache hits</strong>: ' . $this->cache_hits . '<br />';
  326. echo '<strong>Cache misses</strong>: ' . $this->cache_misses . '<br />';
  327. echo '<strong>Total time</strong>: '. round($this->time_total, 4) . 's';
  328. echo '</p>';
  329. echo '<h2>Cache info</h2>';
  330. if ($this->_debug) {
  331. echo '<table cellpadding="0" cellspacing="3" border="1">';
  332. echo '<tr><td>#</td><td>Status</td><td>Source</td><td>Data size (b)</td><td>Query time (s)</td><td>ID:Group</td></tr>';
  333. foreach ($this->debug_info as $index => $debug) {
  334. echo '<tr>';
  335. echo '<td>' . ($index + 1) . '</td>';
  336. echo '<td>' . ($debug['cached'] ? 'cached' : 'not cached') . '</td>';
  337. echo '<td>' . ($debug['internal'] ? 'internal' : 'persistent') . '</td>';
  338. echo '<td>' . $debug['data_size'] . '</td>';
  339. echo '<td>' . round($debug['time'], 4) . '</td>';
  340. echo '<td>' . sprintf('%s:%s', $debug['id'], $debug['group']) . '</td>';
  341. echo '</tr>';
  342. }
  343. echo '</table>';
  344. } else {
  345. echo '<p>Enable debug mode.</p>';
  346. }
  347. }
  348. /**
  349. * Returns cache key
  350. *
  351. * @param string $id
  352. * @param string $group
  353. * @return string
  354. */
  355. function _get_cache_key($id, $group = 'default') {
  356. if (!$group) {
  357. $group = 'default';
  358. }
  359. $blog_id = w3_get_blog_id();
  360. $key_cache_id = $blog_id . $group . $id;
  361. if (isset($this->_key_cache[$key_cache_id])) {
  362. $key = $this->_key_cache[$key_cache_id];
  363. } else {
  364. $host = w3_get_host();
  365. if (in_array($group, $this->global_groups)) {
  366. $host_id = $host;
  367. } else {
  368. $host_id = sprintf('%s_%d', $host, $blog_id);
  369. }
  370. $key = sprintf('w3tc_%s_object_%s', $host_id, md5($group . $id));
  371. $this->_key_cache[$key_cache_id] = $key;
  372. }
  373. /**
  374. * Allow to modify cache key by W3TC plugins
  375. */
  376. $key = w3tc_do_action('w3tc_objectcache_cache_key', $key);
  377. return $key;
  378. }
  379. /**
  380. * Returns cache object
  381. *
  382. * @return W3_Cache_Base
  383. */
  384. function &_get_cache() {
  385. static $cache = array();
  386. if (!isset($cache[0])) {
  387. $engine = $this->_config->get_string('objectcache.engine');
  388. switch ($engine) {
  389. case 'memcached':
  390. $engineConfig = array(
  391. 'servers' => $this->_config->get_array('objectcache.memcached.servers'),
  392. 'persistant' => $this->_config->get_boolean('objectcache.memcached.persistant')
  393. );
  394. break;
  395. case 'file':
  396. $engineConfig = array(
  397. 'cache_dir' => W3TC_CACHE_FILE_OBJECTCACHE_DIR,
  398. 'locking' => $this->_config->get_boolean('objectcache.file.locking'),
  399. 'flush_timelimit' => $this->_config->get_integer('timelimit.cache_flush')
  400. );
  401. break;
  402. default:
  403. $engineConfig = array();
  404. }
  405. require_once W3TC_LIB_W3_DIR . '/Cache.php';
  406. @$cache[0] = & W3_Cache::instance($engine, $engineConfig);
  407. }
  408. return $cache[0];
  409. }
  410. /**
  411. * Check if caching allowed on init
  412. *
  413. * @return boolean
  414. */
  415. function _can_cache() {
  416. /**
  417. * Skip if disabled
  418. */
  419. if (!$this->_config->get_boolean('objectcache.enabled')) {
  420. $this->_cache_reject_reason = 'Object caching is disabled';
  421. return false;
  422. }
  423. /**
  424. * Check for DONOTCACHEOBJECT constant
  425. */
  426. if (defined('DONOTCACHEOBJECT') && DONOTCACHEOBJECT) {
  427. $this->_cache_reject_reason = 'DONOTCACHEOBJECT constant is defined';
  428. return false;
  429. }
  430. return true;
  431. }
  432. /**
  433. * Check if we can start OB
  434. *
  435. * @return boolean
  436. */
  437. function _can_ob() {
  438. /**
  439. * Object cache should be enabled
  440. */
  441. if (!$this->_config->get_boolean('objectcache.enabled')) {
  442. return false;
  443. }
  444. /**
  445. * Debug should be enabled
  446. */
  447. if (!$this->_debug) {
  448. return false;
  449. }
  450. /**
  451. * Skip if doing AJAX
  452. */
  453. if (defined('DOING_AJAX')) {
  454. return false;
  455. }
  456. /**
  457. * Skip if doing cron
  458. */
  459. if (defined('DOING_CRON')) {
  460. return false;
  461. }
  462. /**
  463. * Skip if APP request
  464. */
  465. if (defined('APP_REQUEST')) {
  466. return false;
  467. }
  468. /**
  469. * Skip if XMLRPC request
  470. */
  471. if (defined('XMLRPC_REQUEST')) {
  472. return false;
  473. }
  474. /**
  475. * Check for WPMU's and WP's 3.0 short init
  476. */
  477. if (defined('SHORTINIT') && SHORTINIT) {
  478. return false;
  479. }
  480. /**
  481. * Check User Agent
  482. */
  483. if (isset($_SERVER['HTTP_USER_AGENT']) && stristr($_SERVER['HTTP_USER_AGENT'], W3TC_POWERED_BY) !== false) {
  484. return false;
  485. }
  486. return true;
  487. }
  488. /**
  489. * Returns debug info
  490. *
  491. * @return string
  492. */
  493. function _get_debug_info() {
  494. $debug_info = "<!-- W3 Total Cache: Object Cache debug info:\r\n";
  495. $debug_info .= sprintf("%s%s\r\n", str_pad('Engine: ', 20), w3_get_engine_name($this->_config->get_string('objectcache.engine')));
  496. $debug_info .= sprintf("%s%s\r\n", str_pad('Caching: ', 20), ($this->_caching ? 'enabled' : 'disabled'));
  497. if (!$this->_caching) {
  498. $debug_info .= sprintf("%s%s\r\n", str_pad('Reject reason: ', 20), $this->_cache_reject_reason);
  499. }
  500. $debug_info .= sprintf("%s%d\r\n", str_pad('Total calls: ', 20), $this->cache_total);
  501. $debug_info .= sprintf("%s%d\r\n", str_pad('Cache hits: ', 20), $this->cache_hits);
  502. $debug_info .= sprintf("%s%d\r\n", str_pad('Cache misses: ', 20), $this->cache_misses);
  503. $debug_info .= sprintf("%s%.4f\r\n", str_pad('Total time: ', 20), $this->time_total);
  504. $debug_info .= "W3TC Object Cache info:\r\n";
  505. $debug_info .= sprintf("%s | %s | %s | %s | %s | %s\r\n",
  506. str_pad('#', 5, ' ', STR_PAD_LEFT),
  507. str_pad('Status', 15, ' ', STR_PAD_BOTH),
  508. str_pad('Source', 15, ' ', STR_PAD_BOTH),
  509. str_pad('Data size (b)', 13, ' ', STR_PAD_LEFT),
  510. str_pad('Query time (s)', 14, ' ', STR_PAD_LEFT),
  511. 'ID:Group');
  512. foreach ($this->debug_info as $index => $debug) {
  513. $debug_info .= sprintf("%s | %s | %s | %s | %s | %s\r\n",
  514. str_pad($index + 1, 5, ' ', STR_PAD_LEFT),
  515. str_pad(($debug['cached'] ? 'cached' : 'not cached'), 15, ' ', STR_PAD_BOTH),
  516. str_pad(($debug['internal'] ? 'internal' : 'persistent'), 15, ' ', STR_PAD_BOTH),
  517. str_pad($debug['data_size'], 13, ' ', STR_PAD_LEFT),
  518. str_pad(round($debug['time'], 4), 14, ' ', STR_PAD_LEFT),
  519. sprintf('%s:%s', $debug['id'], $debug['group']));
  520. }
  521. $debug_info .= '-->';
  522. return $debug_info;
  523. }
  524. }