/content/plugins/w3-total-cache/Cache_File_Generic.php

https://gitlab.com/karlen/ayo_wp · PHP · 285 lines · 161 code · 52 blank · 72 comment · 38 complexity · 49eaa5409477404dea43f9ee24f73030 MD5 · raw file

  1. <?php
  2. namespace W3TC;
  3. /**
  4. * Generic file cache
  5. */
  6. /**
  7. * class Cache_File_Generic
  8. */
  9. class Cache_File_Generic extends Cache_File {
  10. /**
  11. * Expire
  12. *
  13. * @var integer
  14. */
  15. var $_expire = 0;
  16. /**
  17. * PHP5-style constructor
  18. *
  19. * @param array $config
  20. */
  21. function __construct( $config = array() ) {
  22. parent::__construct( $config );
  23. $this->_expire = ( isset( $config['expire'] ) ? (int) $config['expire'] : 0 );
  24. if ( !$this->_expire || $this->_expire > W3TC_CACHE_FILE_EXPIRE_MAX ) {
  25. $this->_expire = W3TC_CACHE_FILE_EXPIRE_MAX;
  26. }
  27. }
  28. /**
  29. * Sets data
  30. *
  31. * @param string $key
  32. * @param string $var
  33. * @param int $expire
  34. * @param string $group Used to differentiate between groups of cache values
  35. * @return boolean
  36. */
  37. function set( $key, $var, $expire = 0, $group = '' ) {
  38. $key = $this->get_item_key( $key );
  39. $sub_path = $this->_get_path( $key );
  40. $path = $this->_cache_dir . '/' . $sub_path;
  41. $dir = dirname( $path );
  42. if ( !@is_dir( $dir ) ) {
  43. if ( !Util_File::mkdir_from( $dir, W3TC_CACHE_DIR ) )
  44. return false;
  45. }
  46. $tmppath = $path . '.' . getmypid();
  47. $fp = @fopen( $tmppath, 'w' );
  48. if ( !$fp )
  49. return false;
  50. if ( $this->_locking )
  51. @flock( $fp, LOCK_EX );
  52. @fputs( $fp, $var['content'] );
  53. @fclose( $fp );
  54. if ( $this->_locking )
  55. @flock( $fp, LOCK_UN );
  56. // some hostings create files with restrictive permissions
  57. // not allowing apache to read it later
  58. @chmod( $path, 0644 );
  59. if ( @filesize( $tmppath ) > 0 ) {
  60. @unlink( $path );
  61. @rename( $tmppath, $path );
  62. }
  63. @unlink( $tmppath );
  64. $old_entry_path = $path . '.old';
  65. @unlink( $old_entry_path );
  66. if ( Util_Environment::is_apache() && isset( $var['headers'] ) &&
  67. isset( $var['headers']['Content-Type'] ) &&
  68. substr( $var['headers']['Content-Type'], 0, 8 ) == 'text/xml' ) {
  69. file_put_contents( dirname( $path ) . '/.htaccess',
  70. "<IfModule mod_mime.c>\n" .
  71. " RemoveType .html_gzip\n" .
  72. " AddType text/xml .html_gzip\n" .
  73. " RemoveType .html\n" .
  74. " AddType text/xml .html\n".
  75. "</IfModule>" );
  76. }
  77. return true;
  78. }
  79. /**
  80. * Returns data
  81. *
  82. * @param string $key
  83. * @param string $group Used to differentiate between groups of cache values
  84. * @return array
  85. */
  86. function get_with_old( $key, $group = '' ) {
  87. $has_old_data = false;
  88. $key = $this->get_item_key( $key );
  89. $path = $this->_cache_dir . '/' . $this->_get_path( $key );
  90. $data = $this->_read( $path );
  91. if ( $data != null )
  92. return array( $data, $has_old_data );
  93. $path_old = $path . '.old';
  94. $too_old_time = time() - 30;
  95. if ( $exists = file_exists( $path_old ) ) {
  96. $file_time = @filemtime( $path_old );
  97. if ( $file_time ) {
  98. if ( $file_time > $too_old_time ) {
  99. // return old data
  100. $has_old_data = true;
  101. return array( $this->_read( $path_old ), $has_old_data );
  102. }
  103. @touch( $path_old );
  104. }
  105. }
  106. $has_old_data = $exists;
  107. return array( null, $has_old_data );
  108. }
  109. /**
  110. * Reads file
  111. *
  112. * @param string $path
  113. * @return array
  114. */
  115. private function _read( $path ) {
  116. if ( !is_readable( $path ) )
  117. return null;
  118. $fp = @fopen( $path, 'r' );
  119. if ( !$fp )
  120. return null;
  121. if ( $this->_locking )
  122. @flock( $fp, LOCK_SH );
  123. $var = '';
  124. while ( !@feof( $fp ) )
  125. $var .= @fread( $fp, 4096 );
  126. @fclose( $fp );
  127. if ( $this->_locking )
  128. @flock( $fp, LOCK_UN );
  129. return array(
  130. '404' => false,
  131. 'headers' => array(),
  132. 'time' => null,
  133. 'content' => $var
  134. );
  135. }
  136. /**
  137. * Deletes data
  138. *
  139. * @param string $key
  140. * @param string $group Used to differentiate between groups of cache values
  141. * @return boolean
  142. */
  143. function delete( $key, $group = '' ) {
  144. $key = $this->get_item_key( $key );
  145. $path = $this->_cache_dir . DIRECTORY_SEPARATOR . $this->_get_path( $key );
  146. if ( !file_exists( $path ) )
  147. return true;
  148. $old_entry_path = $path . '.old';
  149. if ( @rename( $path, $old_entry_path ) )
  150. return true;
  151. // if we can delete old entry - do second attempt to store in old-entry file
  152. if ( @unlink( $old_entry_path ) ) {
  153. if ( @rename( $path, $old_entry_path ) )
  154. return true;
  155. }
  156. return @unlink( $path );
  157. }
  158. /**
  159. * Key to delete, deletes .old and primary if exists.
  160. *
  161. * @param unknown $key
  162. * @return bool
  163. */
  164. function hard_delete( $key ) {
  165. $key = $this->get_item_key( $key );
  166. $path = $this->_cache_dir . DIRECTORY_SEPARATOR . $this->_get_path( $key );
  167. $old_entry_path = $path . '.old';
  168. @unlink( $old_entry_path );
  169. if ( !file_exists( $path ) )
  170. return true;
  171. @unlink( $path );
  172. return true;
  173. }
  174. /**
  175. * Flushes all data
  176. *
  177. * @param string $group Used to differentiate between groups of cache values
  178. * @return boolean
  179. */
  180. function flush( $group = '' ) {
  181. if ( $group == 'sitemaps' ) {
  182. $config = Dispatcher::config();
  183. $sitemap_regex = $config->get_string( 'pgcache.purge.sitemap_regex' );
  184. $this->_flush_based_on_regex( $sitemap_regex );
  185. } else {
  186. $c = new Cache_File_Cleaner_Generic( array(
  187. 'cache_dir' => $this->_flush_dir,
  188. 'exclude' => $this->_exclude,
  189. 'clean_timelimit' => $this->_flush_timelimit
  190. ) );
  191. $c->clean();
  192. }
  193. }
  194. /**
  195. * Returns cache file path by key
  196. *
  197. * @param string $key
  198. * @return string
  199. */
  200. function _get_path( $key ) {
  201. return $key;
  202. }
  203. function get_item_key( $key ) {
  204. return $key;
  205. }
  206. /**
  207. * Flush cache based on regex
  208. *
  209. * @param string $regex
  210. */
  211. private function _flush_based_on_regex( $regex ) {
  212. if ( Util_Environment::is_wpmu() && !Util_Environment::is_wpmu_subdomain() ) {
  213. $domain = get_home_url();
  214. $parsed = parse_url( $domain );
  215. $host = $parsed['host'];
  216. $path = isset( $parsed['path'] ) ? '/' . trim( $parsed['path'], '/' ) : '';
  217. $flush_dir = W3TC_CACHE_PAGE_ENHANCED_DIR . '/' . $host . $path;
  218. } else
  219. $flush_dir = W3TC_CACHE_PAGE_ENHANCED_DIR . '/' . Util_Environment::host();
  220. $dir = @opendir( $flush_dir );
  221. if ( $dir ) {
  222. while ( ( $entry = @readdir( $dir ) ) !== false ) {
  223. if ( $entry == '.' || $entry == '..' ) {
  224. continue;
  225. }
  226. if ( preg_match( '/' . $regex . '/', basename( $entry ) ) ) {
  227. Util_File::rmdir( $flush_dir . DIRECTORY_SEPARATOR . $entry );
  228. }
  229. }
  230. @closedir( $dir );
  231. }
  232. }
  233. }