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