PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/2.0/wp-includes/cache.php

#
PHP | 373 lines | 171 code | 46 blank | 156 comment | 31 complexity | 10140ee0d9f2b01431a5b40bfc78f6c0 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.0, LGPL-2.1, GPL-2.0
  1. <?php
  2. function wp_cache_add($key, $data, $flag = '', $expire = 0) {
  3. global $wp_object_cache;
  4. return $wp_object_cache->add($key, $data, $flag, $expire);
  5. }
  6. function wp_cache_close() {
  7. global $wp_object_cache;
  8. return $wp_object_cache->save();
  9. }
  10. function wp_cache_delete($id, $flag = '') {
  11. global $wp_object_cache;
  12. return $wp_object_cache->delete($id, $flag);
  13. }
  14. function wp_cache_flush() {
  15. global $wp_object_cache;
  16. return $wp_object_cache->flush();
  17. }
  18. function wp_cache_get($id, $flag = '') {
  19. global $wp_object_cache;
  20. return $wp_object_cache->get($id, $flag);
  21. }
  22. function wp_cache_init() {
  23. global $wp_object_cache;
  24. $wp_object_cache = new WP_Object_Cache();
  25. }
  26. function wp_cache_replace($key, $data, $flag = '', $expire = 0) {
  27. global $wp_object_cache;
  28. return $wp_object_cache->replace($key, $data, $flag, $expire);
  29. }
  30. function wp_cache_set($key, $data, $flag = '', $expire = 0) {
  31. global $wp_object_cache;
  32. return $wp_object_cache->set($key, $data, $flag, $expire);
  33. }
  34. define('CACHE_SERIAL_HEADER', "<?php\n//");
  35. define('CACHE_SERIAL_FOOTER', "\n?".">");
  36. class WP_Object_Cache {
  37. var $cache_dir;
  38. var $cache_enabled = false;
  39. var $expiration_time = 86400;
  40. var $flock_filename = 'wp_object_cache.lock';
  41. var $cache = array ();
  42. var $dirty_objects = array ();
  43. var $non_existant_objects = array ();
  44. var $global_groups = array ('users', 'userlogins', 'usermeta');
  45. var $blog_id;
  46. var $cold_cache_hits = 0;
  47. var $warm_cache_hits = 0;
  48. var $cache_misses = 0;
  49. function add($id, $data, $group = 'default', $expire = '') {
  50. if (empty ($group))
  51. $group = 'default';
  52. if (false !== $this->get($id, $group, false))
  53. return false;
  54. return $this->set($id, $data, $group, $expire);
  55. }
  56. function delete($id, $group = 'default', $force = false) {
  57. if (empty ($group))
  58. $group = 'default';
  59. if (!$force && false === $this->get($id, $group, false))
  60. return false;
  61. unset ($this->cache[$group][$id]);
  62. $this->non_existant_objects[$group][$id] = true;
  63. $this->dirty_objects[$group][] = $id;
  64. return true;
  65. }
  66. function flush() {
  67. if ( !$this->cache_enabled )
  68. return;
  69. $this->rm($this->cache_dir.'*');
  70. $this->cache = array ();
  71. $this->dirty_objects = array ();
  72. $this->non_existant_objects = array ();
  73. return true;
  74. }
  75. function get($id, $group = 'default', $count_hits = true) {
  76. if (empty ($group))
  77. $group = 'default';
  78. if (isset ($this->cache[$group][$id])) {
  79. if ($count_hits)
  80. $this->warm_cache_hits += 1;
  81. return $this->cache[$group][$id];
  82. }
  83. if (isset ($this->non_existant_objects[$group][$id]))
  84. return false;
  85. // If caching is not enabled, we have to fall back to pulling from the DB.
  86. if (!$this->cache_enabled) {
  87. if (!isset ($this->cache[$group]))
  88. $this->load_group_from_db($group);
  89. if (isset ($this->cache[$group][$id])) {
  90. $this->cold_cache_hits += 1;
  91. return $this->cache[$group][$id];
  92. }
  93. $this->non_existant_objects[$group][$id] = true;
  94. $this->cache_misses += 1;
  95. return false;
  96. }
  97. $cache_file = $this->cache_dir.$this->get_group_dir($group)."/".md5($id.DB_PASSWORD).'.php';
  98. if (!file_exists($cache_file)) {
  99. $this->non_existant_objects[$group][$id] = true;
  100. $this->cache_misses += 1;
  101. return false;
  102. }
  103. // If the object has expired, remove it from the cache and return false to force
  104. // a refresh.
  105. $now = time();
  106. if ((filemtime($cache_file) + $this->expiration_time) <= $now) {
  107. $this->cache_misses += 1;
  108. $this->delete($id, $group, true);
  109. return false;
  110. }
  111. $this->cache[$group][$id] = unserialize(substr(@ file_get_contents($cache_file), strlen(CACHE_SERIAL_HEADER), -strlen(CACHE_SERIAL_FOOTER)));
  112. if (false === $this->cache[$group][$id])
  113. $this->cache[$group][$id] = '';
  114. $this->cold_cache_hits += 1;
  115. return $this->cache[$group][$id];
  116. }
  117. function get_group_dir($group) {
  118. if (false !== array_search($group, $this->global_groups))
  119. return $group;
  120. return "{$this->blog_id}/$group";
  121. }
  122. function load_group_from_db($group) {
  123. global $wpdb;
  124. if ('category' == $group) {
  125. $this->cache['category'] = array ();
  126. if ($dogs = $wpdb->get_results("SELECT * FROM $wpdb->categories")) {
  127. foreach ($dogs as $catt)
  128. $this->cache['category'][$catt->cat_ID] = $catt;
  129. foreach ($this->cache['category'] as $catt) {
  130. $curcat = $catt->cat_ID;
  131. $fullpath = '/'.$this->cache['category'][$catt->cat_ID]->category_nicename;
  132. while ($this->cache['category'][$curcat]->category_parent != 0) {
  133. $curcat = $this->cache['category'][$curcat]->category_parent;
  134. $fullpath = '/'.$this->cache['category'][$curcat]->category_nicename.$fullpath;
  135. }
  136. $this->cache['category'][$catt->cat_ID]->fullpath = $fullpath;
  137. }
  138. }
  139. } else
  140. if ('options' == $group) {
  141. $wpdb->hide_errors();
  142. if (!$options = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'")) {
  143. $options = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options");
  144. }
  145. $wpdb->show_errors();
  146. if ( ! $options )
  147. return;
  148. foreach ($options as $option) {
  149. $this->cache['options'][$option->option_name] = $option->option_value;
  150. }
  151. }
  152. }
  153. function make_group_dir($group, $perms) {
  154. $group_dir = $this->get_group_dir($group);
  155. $make_dir = '';
  156. foreach (split('/', $group_dir) as $subdir) {
  157. $make_dir .= "$subdir/";
  158. if (!file_exists($this->cache_dir.$make_dir)) {
  159. if (! @ mkdir($this->cache_dir.$make_dir))
  160. break;
  161. @ chmod($this->cache_dir.$make_dir, $perms);
  162. }
  163. if (!file_exists($this->cache_dir.$make_dir."index.php")) {
  164. @ touch($this->cache_dir.$make_dir."index.php");
  165. }
  166. }
  167. return $this->cache_dir."$group_dir/";
  168. }
  169. function rm($fileglob) {
  170. if (is_file($fileglob)) {
  171. return @ unlink($fileglob);
  172. } else
  173. if (is_dir($fileglob)) {
  174. $ok = WP_Object_Cache::rm("$fileglob/*");
  175. if (!$ok)
  176. return false;
  177. return @ rmdir($fileglob);
  178. } else {
  179. $matching = glob($fileglob);
  180. if ($matching === false)
  181. return true;
  182. $rcs = array_map(array ('WP_Object_Cache', 'rm'), $matching);
  183. if (in_array(false, $rcs)) {
  184. return false;
  185. }
  186. }
  187. return true;
  188. }
  189. function replace($id, $data, $group = 'default', $expire = '') {
  190. if (empty ($group))
  191. $group = 'default';
  192. if (false === $this->get($id, $group, false))
  193. return false;
  194. return $this->set($id, $data, $group, $expire);
  195. }
  196. function set($id, $data, $group = 'default', $expire = '') {
  197. if (empty ($group))
  198. $group = 'default';
  199. if (NULL == $data)
  200. $data = '';
  201. $this->cache[$group][$id] = $data;
  202. unset ($this->non_existant_objects[$group][$id]);
  203. $this->dirty_objects[$group][] = $id;
  204. return true;
  205. }
  206. function save() {
  207. //$this->stats();
  208. if (!$this->cache_enabled)
  209. return;
  210. if (empty ($this->dirty_objects))
  211. return;
  212. // Give the new dirs the same perms as wp-content.
  213. $stat = stat(ABSPATH.'wp-content');
  214. $dir_perms = $stat['mode'] & 0000777; // Get the permission bits.
  215. // Make the base cache dir.
  216. if (!file_exists($this->cache_dir)) {
  217. if (! @ mkdir($this->cache_dir))
  218. return;
  219. @ chmod($this->cache_dir, $dir_perms);
  220. }
  221. if (!file_exists($this->cache_dir."index.php")) {
  222. @ touch($this->cache_dir."index.php");
  223. }
  224. // Acquire a write lock.
  225. $mutex = @fopen($this->cache_dir.$this->flock_filename, 'w');
  226. if ( false == $mutex)
  227. return;
  228. flock($mutex, LOCK_EX);
  229. // Loop over dirty objects and save them.
  230. foreach ($this->dirty_objects as $group => $ids) {
  231. $group_dir = $this->make_group_dir($group, $dir_perms);
  232. $ids = array_unique($ids);
  233. foreach ($ids as $id) {
  234. $cache_file = $group_dir.md5($id.DB_PASSWORD).'.php';
  235. // Remove the cache file if the key is not set.
  236. if (!isset ($this->cache[$group][$id])) {
  237. if (file_exists($cache_file))
  238. unlink($cache_file);
  239. continue;
  240. }
  241. $temp_file = tempnam($group_dir, 'tmp');
  242. $serial = CACHE_SERIAL_HEADER.serialize($this->cache[$group][$id]).CACHE_SERIAL_FOOTER;
  243. $fd = @fopen($temp_file, 'w');
  244. if ( false === $fd )
  245. continue;
  246. fputs($fd, $serial);
  247. fclose($fd);
  248. if (!@ rename($temp_file, $cache_file)) {
  249. if (@ copy($temp_file, $cache_file)) {
  250. @ unlink($temp_file);
  251. }
  252. }
  253. }
  254. }
  255. // Release write lock.
  256. flock($mutex, LOCK_UN);
  257. fclose($mutex);
  258. }
  259. function stats() {
  260. echo "<p>";
  261. echo "<strong>Cold Cache Hits:</strong> {$this->cold_cache_hits}<br/>";
  262. echo "<strong>Warm Cache Hits:</strong> {$this->warm_cache_hits}<br/>";
  263. echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br/>";
  264. echo "</p>";
  265. foreach ($this->cache as $group => $cache) {
  266. echo "<p>";
  267. echo "<strong>Group:</strong> $group<br/>";
  268. echo "<strong>Cache:</strong>";
  269. echo "<pre>";
  270. print_r($cache);
  271. echo "</pre>";
  272. if (isset ($this->dirty_objects[$group])) {
  273. echo "<strong>Dirty Objects:</strong>";
  274. echo "<pre>";
  275. print_r(array_unique($this->dirty_objects[$group]));
  276. echo "</pre>";
  277. echo "</p>";
  278. }
  279. }
  280. }
  281. function WP_Object_Cache() {
  282. global $blog_id;
  283. if (defined('DISABLE_CACHE'))
  284. return;
  285. if (defined('CACHE_PATH'))
  286. $this->cache_dir = CACHE_PATH;
  287. else
  288. $this->cache_dir = ABSPATH.'wp-content/cache/';
  289. if (is_writable($this->cache_dir) && is_dir($this->cache_dir)) {
  290. $this->cache_enabled = true;
  291. } else
  292. if (is_writable(ABSPATH.'wp-content')) {
  293. $this->cache_enabled = true;
  294. }
  295. if (defined('CACHE_EXPIRATION_TIME'))
  296. $this->expiration_time = CACHE_EXPIRATION_TIME;
  297. $this->blog_id = md5($blog_id);
  298. }
  299. }
  300. ?>