MediaWiki  REL1_24
HTMLFileCache.php
Go to the documentation of this file.
00001 <?php
00031 class HTMLFileCache extends FileCacheBase {
00041     public static function newFromTitle( $title, $action ) {
00042         return new self( $title, $action );
00043     }
00044 
00050     public function __construct( $title, $action ) {
00051         $allowedTypes = self::cacheablePageActions();
00052         if ( !in_array( $action, $allowedTypes ) ) {
00053             throw new MWException( 'Invalid file cache type given.' );
00054         }
00055         $this->mKey = ( $title instanceof Title )
00056             ? $title->getPrefixedDBkey()
00057             : (string)$title;
00058         $this->mType = (string)$action;
00059         $this->mExt = 'html';
00060     }
00061 
00066     protected static function cacheablePageActions() {
00067         return array( 'view', 'history' );
00068     }
00069 
00074     protected function cacheDirectory() {
00075         return $this->baseCacheDirectory(); // no subdir for b/c with old cache files
00076     }
00077 
00084     protected function typeSubdirectory() {
00085         if ( $this->mType === 'view' ) {
00086             return ''; //  b/c to not skip existing cache
00087         } else {
00088             return $this->mType . '/';
00089         }
00090     }
00091 
00097     public static function useFileCache( IContextSource $context ) {
00098         global $wgUseFileCache, $wgShowIPinHeader, $wgDebugToolbar, $wgContLang;
00099         if ( !$wgUseFileCache ) {
00100             return false;
00101         }
00102         if ( $wgShowIPinHeader || $wgDebugToolbar ) {
00103             wfDebug( "HTML file cache skipped. Either \$wgShowIPinHeader and/or \$wgDebugToolbar on\n" );
00104 
00105             return false;
00106         }
00107 
00108         // Get all query values
00109         $queryVals = $context->getRequest()->getValues();
00110         foreach ( $queryVals as $query => $val ) {
00111             if ( $query === 'title' || $query === 'curid' ) {
00112                 continue; // note: curid sets title
00113             // Normal page view in query form can have action=view.
00114             } elseif ( $query === 'action' && in_array( $val, self::cacheablePageActions() ) ) {
00115                 continue;
00116             // Below are header setting params
00117             } elseif ( $query === 'maxage' || $query === 'smaxage' ) {
00118                 continue;
00119             }
00120 
00121             return false;
00122         }
00123         $user = $context->getUser();
00124         // Check for non-standard user language; this covers uselang,
00125         // and extensions for auto-detecting user language.
00126         $ulang = $context->getLanguage()->getCode();
00127         $clang = $wgContLang->getCode();
00128 
00129         // Check that there are no other sources of variation
00130         if ( $user->getId() || $user->getNewtalk() || $ulang != $clang ) {
00131             return false;
00132         }
00133         // Allow extensions to disable caching
00134         return wfRunHooks( 'HTMLFileCache::useFileCache', array( $context ) );
00135     }
00136 
00142     public function loadFromFileCache( IContextSource $context ) {
00143         global $wgMimeType, $wgLanguageCode;
00144 
00145         wfDebug( __METHOD__ . "()\n" );
00146         $filename = $this->cachePath();
00147 
00148         $context->getOutput()->sendCacheControl();
00149         header( "Content-Type: $wgMimeType; charset=UTF-8" );
00150         header( "Content-Language: $wgLanguageCode" );
00151         if ( $this->useGzip() ) {
00152             if ( wfClientAcceptsGzip() ) {
00153                 header( 'Content-Encoding: gzip' );
00154                 readfile( $filename );
00155             } else {
00156                 /* Send uncompressed */
00157                 wfDebug( __METHOD__ . " uncompressing cache file and sending it\n" );
00158                 readgzfile( $filename );
00159             }
00160         } else {
00161             readfile( $filename );
00162         }
00163         $context->getOutput()->disable(); // tell $wgOut that output is taken care of
00164     }
00165 
00172     public function saveToFileCache( $text ) {
00173         global $wgUseFileCache;
00174 
00175         if ( !$wgUseFileCache || strlen( $text ) < 512 ) {
00176             // Disabled or empty/broken output (OOM and PHP errors)
00177             return $text;
00178         }
00179 
00180         wfDebug( __METHOD__ . "()\n", 'log' );
00181 
00182         $now = wfTimestampNow();
00183         if ( $this->useGzip() ) {
00184             $text = str_replace(
00185                 '</html>', '<!-- Cached/compressed ' . $now . " -->\n</html>", $text );
00186         } else {
00187             $text = str_replace(
00188                 '</html>', '<!-- Cached ' . $now . " -->\n</html>", $text );
00189         }
00190 
00191         // Store text to FS...
00192         $compressed = $this->saveText( $text );
00193         if ( $compressed === false ) {
00194             return $text; // error
00195         }
00196 
00197         // gzip output to buffer as needed and set headers...
00198         if ( $this->useGzip() ) {
00199             // @todo Ugly wfClientAcceptsGzip() function - use context!
00200             if ( wfClientAcceptsGzip() ) {
00201                 header( 'Content-Encoding: gzip' );
00202 
00203                 return $compressed;
00204             } else {
00205                 return $text;
00206             }
00207         } else {
00208             return $text;
00209         }
00210     }
00211 
00217     public static function clearFileCache( Title $title ) {
00218         global $wgUseFileCache;
00219 
00220         if ( !$wgUseFileCache ) {
00221             return false;
00222         }
00223 
00224         foreach ( self::cacheablePageActions() as $type ) {
00225             $fc = new self( $title, $type );
00226             $fc->clearCache();
00227         }
00228 
00229         return true;
00230     }
00231 }