MediaWiki  master
HTMLFileCache.php
Go to the documentation of this file.
1 <?php
25 
34  const MODE_NORMAL = 0; // normal cache mode
35  const MODE_OUTAGE = 1; // fallback cache for DB outages
36  const MODE_REBUILD = 2; // background cache rebuild mode
37 
43  public function __construct( $title, $action ) {
44  parent::__construct();
45 
46  $allowedTypes = self::cacheablePageActions();
47  if ( !in_array( $action, $allowedTypes ) ) {
48  throw new MWException( 'Invalid file cache type given.' );
49  }
50  $this->mKey = ( $title instanceof Title )
51  ? $title->getPrefixedDBkey()
52  : (string)$title;
53  $this->mType = (string)$action;
54  $this->mExt = 'html';
55  }
56 
61  protected static function cacheablePageActions() {
62  return [ 'view', 'history' ];
63  }
64 
69  protected function cacheDirectory() {
70  return $this->baseCacheDirectory(); // no subdir for b/c with old cache files
71  }
72 
79  protected function typeSubdirectory() {
80  if ( $this->mType === 'view' ) {
81  return ''; // b/c to not skip existing cache
82  } else {
83  return $this->mType . '/';
84  }
85  }
86 
93  public static function useFileCache( IContextSource $context, $mode = self::MODE_NORMAL ) {
94  $config = MediaWikiServices::getInstance()->getMainConfig();
95 
96  if ( !$config->get( 'UseFileCache' ) && $mode !== self::MODE_REBUILD ) {
97  return false;
98  }
99 
100  // Get all query values
101  $queryVals = $context->getRequest()->getValues();
102  foreach ( $queryVals as $query => $val ) {
103  if ( $query === 'title' || $query === 'curid' ) {
104  continue; // note: curid sets title
105  // Normal page view in query form can have action=view.
106  } elseif ( $query === 'action' && in_array( $val, self::cacheablePageActions() ) ) {
107  continue;
108  // Below are header setting params
109  } elseif ( $query === 'maxage' || $query === 'smaxage' ) {
110  continue;
111  }
112 
113  return false;
114  }
115 
116  $user = $context->getUser();
117  // Check for non-standard user language; this covers uselang,
118  // and extensions for auto-detecting user language.
119  $ulang = $context->getLanguage();
120 
121  // Check that there are no other sources of variation
122  if ( $user->getId() ||
123  !$ulang->equals( MediaWikiServices::getInstance()->getContentLanguage() ) ) {
124  return false;
125  }
126 
127  if ( ( $mode === self::MODE_NORMAL ) && $user->getNewtalk() ) {
128  return false;
129  }
130 
131  // Allow extensions to disable caching
132  return Hooks::run( 'HTMLFileCache::useFileCache', [ $context ] );
133  }
134 
141  public function loadFromFileCache( IContextSource $context, $mode = self::MODE_NORMAL ) {
142  $config = MediaWikiServices::getInstance()->getMainConfig();
143 
144  wfDebug( __METHOD__ . "()\n" );
145  $filename = $this->cachePath();
146 
147  if ( $mode === self::MODE_OUTAGE ) {
148  // Avoid DB errors for queries in sendCacheControl()
149  $context->getTitle()->resetArticleID( 0 );
150  }
151 
152  $context->getOutput()->sendCacheControl();
153  header( "Content-Type: {$config->get( 'MimeType' )}; charset=UTF-8" );
154  header( 'Content-Language: ' .
155  MediaWikiServices::getInstance()->getContentLanguage()->getHtmlCode() );
156  if ( $this->useGzip() ) {
157  if ( wfClientAcceptsGzip() ) {
158  header( 'Content-Encoding: gzip' );
159  readfile( $filename );
160  } else {
161  /* Send uncompressed */
162  wfDebug( __METHOD__ . " uncompressing cache file and sending it\n" );
163  readgzfile( $filename );
164  }
165  } else {
166  readfile( $filename );
167  }
168 
169  $context->getOutput()->disable(); // tell $wgOut that output is taken care of
170  }
171 
184  public function saveToFileCache( $text ) {
185  if ( strlen( $text ) < 512 ) {
186  // Disabled or empty/broken output (OOM and PHP errors)
187  return $text;
188  }
189 
190  wfDebug( __METHOD__ . "()\n", 'private' );
191 
192  $now = wfTimestampNow();
193  if ( $this->useGzip() ) {
194  $text = str_replace(
195  '</html>', '<!-- Cached/compressed ' . $now . " -->\n</html>", $text );
196  } else {
197  $text = str_replace(
198  '</html>', '<!-- Cached ' . $now . " -->\n</html>", $text );
199  }
200 
201  // Store text to FS...
202  $compressed = $this->saveText( $text );
203  if ( $compressed === false ) {
204  return $text; // error
205  }
206 
207  // gzip output to buffer as needed and set headers...
208  // @todo Ugly wfClientAcceptsGzip() function - use context!
209  if ( $this->useGzip() && wfClientAcceptsGzip() ) {
210  header( 'Content-Encoding: gzip' );
211 
212  return $compressed;
213  }
214 
215  return $text;
216  }
217 
223  public static function clearFileCache( Title $title ) {
224  $config = MediaWikiServices::getInstance()->getMainConfig();
225 
226  if ( !$config->get( 'UseFileCache' ) ) {
227  return false;
228  }
229 
230  foreach ( self::cacheablePageActions() as $type ) {
231  $fc = new self( $title, $type );
232  $fc->clearCache();
233  }
234 
235  return true;
236  }
237 }
$context
Definition: load.php:40
static useFileCache(IContextSource $context, $mode=self::MODE_NORMAL)
Check if pages can be cached for this request/user.
baseCacheDirectory()
Get the base file cache directory.
Page view caching in the file system.
static cacheablePageActions()
Cacheable actions.
loadFromFileCache(IContextSource $context, $mode=self::MODE_NORMAL)
Read from cache to context output.
saveToFileCache( $text)
Save this cache object with the given text.
wfClientAcceptsGzip( $force=false)
Whether the client accept gzip encoding.
typeSubdirectory()
Get the cache type subdirectory (with the trailing slash) or the empty string Alter the type -> direc...
static clearFileCache(Title $title)
Clear the file caches for a page for all actions.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Base class for data storage in the file system.
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
cachePath()
Get the path to the cache file.
__construct( $title, $action)
useGzip()
Check if the cache is gzipped.
cacheDirectory()
Get the base file cache directory.
saveText( $text)
Save and compress text to the cache.
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200