PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

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

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