Index: trunk/phase3/maintenance/rebuildFileCache.php |
— | — | @@ -37,7 +37,7 @@ |
38 | 38 | if ( !$wgUseFileCache ) { |
39 | 39 | $this->error( "Nothing to do -- \$wgUseFileCache is disabled.", true ); |
40 | 40 | } |
41 | | - $wgDisableCounters = false; |
| 41 | + $wgDisableCounters = true; |
42 | 42 | $start = $this->getArg( 0, "0" ); |
43 | 43 | if ( !ctype_digit( $start ) ) { |
44 | 44 | $this->error( "Invalid value for start parameter.", true ); |
— | — | @@ -83,8 +83,8 @@ |
84 | 84 | $article = new Article( $wgTitle ); |
85 | 85 | // If the article is cacheable, then load it |
86 | 86 | if ( $article->isFileCacheable() ) { |
87 | | - $cache = new HTMLFileCache( $wgTitle ); |
88 | | - if ( $cache->isFileCacheGood() ) { |
| 87 | + $cache = HTMLFileCache::newFromTitle( $wgTitle, 'view' ); |
| 88 | + if ( $cache->isCacheGood() ) { |
89 | 89 | if ( $overwrite ) { |
90 | 90 | $rebuilt = true; |
91 | 91 | } else { |
Index: trunk/phase3/includes/Article.php |
— | — | @@ -1715,10 +1715,10 @@ |
1716 | 1716 | |
1717 | 1717 | $called = true; |
1718 | 1718 | if ( $this->isFileCacheable() ) { |
1719 | | - $cache = new HTMLFileCache( $this->getTitle() ); |
1720 | | - if ( $cache->isFileCacheGood( $this->mPage->getTouched() ) ) { |
| 1719 | + $cache = HTMLFileCache::newFromTitle( $this->getTitle(), 'view' ); |
| 1720 | + if ( $cache->isCacheGood( $this->mPage->getTouched() ) ) { |
1721 | 1721 | wfDebug( "Article::tryFileCache(): about to load file\n" ); |
1722 | | - $cache->loadFromFileCache(); |
| 1722 | + $cache->loadFromFileCache( $this->getContext() ); |
1723 | 1723 | return true; |
1724 | 1724 | } else { |
1725 | 1725 | wfDebug( "Article::tryFileCache(): starting buffer\n" ); |
— | — | @@ -1738,8 +1738,9 @@ |
1739 | 1739 | public function isFileCacheable() { |
1740 | 1740 | $cacheable = false; |
1741 | 1741 | |
1742 | | - if ( HTMLFileCache::useFileCache() ) { |
1743 | | - $cacheable = $this->mPage->getID() && !$this->mRedirectedFrom && !$this->getTitle()->isRedirect(); |
| 1742 | + if ( HTMLFileCache::useFileCache( $this->getContext() ) ) { |
| 1743 | + $cacheable = $this->mPage->getID() |
| 1744 | + && !$this->mRedirectedFrom && !$this->getTitle()->isRedirect(); |
1744 | 1745 | // Extension may have reason to disable file caching on some pages. |
1745 | 1746 | if ( $cacheable ) { |
1746 | 1747 | $cacheable = wfRunHooks( 'IsFileCacheable', array( &$this ) ); |
Index: trunk/phase3/includes/db/DatabaseError.php |
— | — | @@ -232,9 +232,9 @@ |
233 | 233 | $t = Title::newFromText( $this->msg( 'mainpage', 'Main Page' ) ); |
234 | 234 | } |
235 | 235 | |
236 | | - $cache = new HTMLFileCache( $t ); |
237 | | - if ( $cache->isFileCached() ) { |
238 | | - return $cache->fetchPageText(); |
| 236 | + $cache = HTMLFileCache::newFromTitle( $t, 'view' ); |
| 237 | + if ( $cache->isCached() ) { |
| 238 | + return $cache->fetchText(); |
239 | 239 | } else { |
240 | 240 | return ''; |
241 | 241 | } |
Index: trunk/phase3/includes/HistoryPage.php |
— | — | @@ -75,10 +75,11 @@ |
76 | 76 | |
77 | 77 | wfProfileIn( __METHOD__ ); |
78 | 78 | |
| 79 | + $context = RequestContext::getMain(); |
79 | 80 | # Fill in the file cache if not set already |
80 | | - if ( $wgUseFileCache && HTMLFileCache::useFileCache() ) { |
81 | | - $cache = new HTMLFileCache( $this->title, 'history' ); |
82 | | - if ( !$cache->isFileCacheGood( /* Assume up to date */ ) ) { |
| 81 | + if ( $wgUseFileCache && HTMLFileCache::useFileCache( $context ) ) { |
| 82 | + $cache = HTMLFileCache::newFromTitle( $this->title, 'history' ); |
| 83 | + if ( !$cache->isCacheGood( /* Assume up to date */ ) ) { |
83 | 84 | ob_start( array( &$cache, 'saveToFileCache' ) ); |
84 | 85 | } |
85 | 86 | } |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -363,6 +363,7 @@ |
364 | 364 | 'CacheDependency' => 'includes/cache/CacheDependency.php', |
365 | 365 | 'ConstantDependency' => 'includes/cache/CacheDependency.php', |
366 | 366 | 'DependencyWrapper' => 'includes/cache/CacheDependency.php', |
| 367 | + 'FileCacheBase' => 'includes/cache/FileCacheBase.php', |
367 | 368 | 'FileDependency' => 'includes/cache/CacheDependency.php', |
368 | 369 | 'GlobalDependency' => 'includes/cache/CacheDependency.php', |
369 | 370 | 'HTMLCacheUpdate' => 'includes/cache/HTMLCacheUpdate.php', |
— | — | @@ -371,6 +372,7 @@ |
372 | 373 | 'LinkBatch' => 'includes/cache/LinkBatch.php', |
373 | 374 | 'LinkCache' => 'includes/cache/LinkCache.php', |
374 | 375 | 'MessageCache' => 'includes/cache/MessageCache.php', |
| 376 | + 'ObjectFileCache' => 'includes/cache/ObjectFileCache.php', |
375 | 377 | 'SquidUpdate' => 'includes/cache/SquidUpdate.php', |
376 | 378 | 'TitleDependency' => 'includes/cache/CacheDependency.php', |
377 | 379 | 'TitleListDependency' => 'includes/cache/CacheDependency.php', |
Index: trunk/phase3/includes/Wiki.php |
— | — | @@ -596,16 +596,14 @@ |
597 | 597 | |
598 | 598 | if ( $wgUseFileCache && $wgTitle->getNamespace() >= 0 ) { |
599 | 599 | wfProfileIn( 'main-try-filecache' ); |
600 | | - // Raw pages should handle cache control on their own, |
601 | | - // even when using file cache. This reduces hits from clients. |
602 | | - if ( HTMLFileCache::useFileCache() ) { |
| 600 | + if ( HTMLFileCache::useFileCache( $this->context ) ) { |
603 | 601 | /* Try low-level file cache hit */ |
604 | | - $cache = new HTMLFileCache( $wgTitle, $action ); |
605 | | - if ( $cache->isFileCacheGood( /* Assume up to date */ ) ) { |
| 602 | + $cache = HTMLFileCache::newFromTitle( $wgTitle, $action ); |
| 603 | + if ( $cache->isCacheGood( /* Assume up to date */ ) ) { |
606 | 604 | /* Check incoming headers to see if client has this cached */ |
607 | | - $timestamp = $cache->fileCacheTime(); |
| 605 | + $timestamp = $cache->cacheTimestamp(); |
608 | 606 | if ( !$this->context->getOutput()->checkLastModified( $timestamp ) ) { |
609 | | - $cache->loadFromFileCache(); |
| 607 | + $cache->loadFromFileCache( $this->context ); |
610 | 608 | } |
611 | 609 | # Do any stats increment/watchlist stuff |
612 | 610 | $article = WikiPage::factory( $wgTitle ); |
Index: trunk/phase3/includes/cache/ObjectFileCache.php |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +<?php |
| 3 | +class ObjectFileCache extends FileCacheBase { |
| 4 | + |
| 5 | + public static function newFromKey( $key, $type ) { |
| 6 | + $cache = new self(); |
| 7 | + |
| 8 | + $allowedTypes = self::cacheableTypes(); |
| 9 | + if ( !isset( $allowedTypes[$type] ) ) { |
| 10 | + throw new MWException( "Invalid filecache type given." ); |
| 11 | + } |
| 12 | + $cache->mKey = (string)$key; |
| 13 | + $cache->mType = (string)$type; |
| 14 | + $cache->mExt = $allowedTypes[$cache->mType]; |
| 15 | + |
| 16 | + return $cache; |
| 17 | + } |
| 18 | + |
| 19 | + /* |
| 20 | + * Get the type => extension mapping |
| 21 | + * @return array |
| 22 | + */ |
| 23 | + protected static function cacheableTypes() { |
| 24 | + return array( 'resources-js' => 'js', 'resources-css' => 'css' ); |
| 25 | + } |
| 26 | + |
| 27 | + /** |
| 28 | + * Get the base file cache directory |
| 29 | + * @return string |
| 30 | + */ |
| 31 | + protected function cacheDirectory() { |
| 32 | + global $wgCacheDirectory, $wgFileCacheDirectory, $wgFileCacheDepth; |
| 33 | + if ( $wgFileCacheDirectory ) { |
| 34 | + $dir = $wgFileCacheDirectory; |
| 35 | + } elseif ( $wgCacheDirectory ) { |
| 36 | + $dir = "$wgCacheDirectory/object"; |
| 37 | + } else { |
| 38 | + throw new MWException( 'Please set $wgCacheDirectory in LocalSettings.php if you wish to use the HTML file cache' ); |
| 39 | + } |
| 40 | + return $dir; |
| 41 | + } |
| 42 | +} |
Property changes on: trunk/phase3/includes/cache/ObjectFileCache.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 43 | + native |
Index: trunk/phase3/includes/cache/FileCacheBase.php |
— | — | @@ -0,0 +1,173 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Contain the HTMLFileCache class |
| 5 | + * @file |
| 6 | + * @ingroup Cache |
| 7 | + */ |
| 8 | +abstract class FileCacheBase { |
| 9 | + protected $mKey; |
| 10 | + protected $mType; |
| 11 | + protected $mExt; |
| 12 | + protected $mFilePath; |
| 13 | + protected $mUseGzip; |
| 14 | + |
| 15 | + protected function __construct() { |
| 16 | + global $wgUseGzip; |
| 17 | + |
| 18 | + $this->mUseGzip = (bool)$wgUseGzip; |
| 19 | + $this->mExt = 'cache'; |
| 20 | + } |
| 21 | + |
| 22 | + /** |
| 23 | + * Get the base cache directory (not speficic to this file) |
| 24 | + * @return string |
| 25 | + */ |
| 26 | + abstract protected function cacheDirectory(); |
| 27 | + |
| 28 | + /** |
| 29 | + * Get the path to the cache file |
| 30 | + * @return string |
| 31 | + */ |
| 32 | + protected function cachePath() { |
| 33 | + if ( $this->mFilePath !== null ) { |
| 34 | + return $this->mFilePath; |
| 35 | + } |
| 36 | + |
| 37 | + $dir = $this->cacheDirectory(); |
| 38 | + $subDirs = $this->mType . '/' . $this->hashSubdirectory(); // includes '/' |
| 39 | + # Avoid extension confusion |
| 40 | + $key = str_replace( '.', '%2E', urlencode( $this->mKey ) ); |
| 41 | + # Build the full file path |
| 42 | + $this->mFilePath = "{$dir}/{$subDirs}{$key}.{$this->mExt}"; |
| 43 | + if ( $this->useGzip() ) { |
| 44 | + $this->mFilePath .= '.gz'; |
| 45 | + } |
| 46 | + |
| 47 | + return $this->mFilePath; |
| 48 | + } |
| 49 | + |
| 50 | + /** |
| 51 | + * Check if the cache file exists |
| 52 | + * @return bool |
| 53 | + */ |
| 54 | + public function isCached() { |
| 55 | + return file_exists( $this->cachePath() ); |
| 56 | + } |
| 57 | + |
| 58 | + /** |
| 59 | + * Get the last-modified timestamp of the cache file |
| 60 | + * @return string|false TS_MW timestamp |
| 61 | + */ |
| 62 | + public function cacheTimestamp() { |
| 63 | + $timestamp = filemtime( $this->cachePath() ); |
| 64 | + return ( $timestamp !== false ) |
| 65 | + ? wfTimestamp( TS_MW, $timestamp ) |
| 66 | + : false; |
| 67 | + } |
| 68 | + |
| 69 | + /** |
| 70 | + * Check if up to date cache file exists |
| 71 | + * @param $timestamp string MW_TS timestamp |
| 72 | + * |
| 73 | + * @return bool |
| 74 | + */ |
| 75 | + public function isCacheGood( $timestamp = '' ) { |
| 76 | + global $wgCacheEpoch; |
| 77 | + |
| 78 | + if ( !$this->isCached() ) { |
| 79 | + return false; |
| 80 | + } |
| 81 | + |
| 82 | + $cachetime = $this->cacheTimestamp(); |
| 83 | + $good = ( $timestamp <= $cachetime && $wgCacheEpoch <= $cachetime ); |
| 84 | + wfDebug( __METHOD__ . ": cachetime $cachetime, touched '{$timestamp}' epoch {$wgCacheEpoch}, good $good\n"); |
| 85 | + |
| 86 | + return $good; |
| 87 | + } |
| 88 | + |
| 89 | + /** |
| 90 | + * Check if the cache is gzipped |
| 91 | + * @return bool |
| 92 | + */ |
| 93 | + protected function useGzip() { |
| 94 | + return $this->mUseGzip; |
| 95 | + } |
| 96 | + |
| 97 | + /** |
| 98 | + * Get the uncompressed text from the cache |
| 99 | + * @return string |
| 100 | + */ |
| 101 | + public function fetchText() { |
| 102 | + if ( $this->useGzip() ) { |
| 103 | + /* Why is there no gzfile_get_contents() or gzdecode()? */ |
| 104 | + return implode( '', gzfile( $this->cachePath() ) ); |
| 105 | + } else { |
| 106 | + return file_get_contents( $this->cachePath() ); |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + /** |
| 111 | + * Save and compress text to the cache |
| 112 | + * @return string compressed text |
| 113 | + */ |
| 114 | + public function saveText( $text ) { |
| 115 | + global $wgUseFileCache; |
| 116 | + if ( !$wgUseFileCache ) { |
| 117 | + return false; |
| 118 | + } |
| 119 | + |
| 120 | + if ( $this->useGzip() ) { |
| 121 | + $text = gzencode( $text ); |
| 122 | + } |
| 123 | + |
| 124 | + $this->checkCacheDirs(); // build parent dir |
| 125 | + if ( !file_put_contents( $this->cachePath(), $text ) ) { |
| 126 | + return false; |
| 127 | + } |
| 128 | + |
| 129 | + return $text; |
| 130 | + } |
| 131 | + |
| 132 | + /* |
| 133 | + * Clear the cache for this page |
| 134 | + * @return void |
| 135 | + */ |
| 136 | + public function clearCache() { |
| 137 | + wfSuppressWarnings(); |
| 138 | + unlink( $this->cachePath() ); |
| 139 | + wfRestoreWarnings(); |
| 140 | + } |
| 141 | + |
| 142 | + /* |
| 143 | + * Create parent directors of $this->cachePath() |
| 144 | + * @TODO: why call wfMkdirParents() twice? |
| 145 | + * @return void |
| 146 | + */ |
| 147 | + protected function checkCacheDirs() { |
| 148 | + $filename = $this->cachePath(); |
| 149 | + $mydir2 = substr( $filename, 0, strrpos( $filename, '/') ); # subdirectory level 2 |
| 150 | + $mydir1 = substr( $mydir2, 0, strrpos( $mydir2, '/') ); # subdirectory level 1 |
| 151 | + |
| 152 | + wfMkdirParents( $mydir1, null, __METHOD__ ); |
| 153 | + wfMkdirParents( $mydir2, null, __METHOD__ ); |
| 154 | + } |
| 155 | + |
| 156 | + /* |
| 157 | + * Return relative multi-level hash subdirectory with the trailing |
| 158 | + * slash or the empty string if $wgFileCacheDepth is off |
| 159 | + * @return string |
| 160 | + */ |
| 161 | + protected function hashSubdirectory() { |
| 162 | + global $wgFileCacheDepth; |
| 163 | + |
| 164 | + $subdir = ''; |
| 165 | + if ( $wgFileCacheDepth > 0 ) { |
| 166 | + $hash = md5( $this->mKey ); |
| 167 | + for ( $i = 1; $i <= $wgFileCacheDepth; $i++ ) { |
| 168 | + $subdir .= substr( $hash, 0, $i ) . '/'; |
| 169 | + } |
| 170 | + } |
| 171 | + |
| 172 | + return $subdir; |
| 173 | + } |
| 174 | +} |
Property changes on: trunk/phase3/includes/cache/FileCacheBase.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 175 | + native |
Index: trunk/phase3/includes/cache/HTMLFileCache.php |
— | — | @@ -4,167 +4,96 @@ |
5 | 5 | * @file |
6 | 6 | * @ingroup Cache |
7 | 7 | */ |
| 8 | +class HTMLFileCache extends FileCacheBase { |
8 | 9 | |
9 | | -/** |
10 | | - * Handles talking to the file cache, putting stuff in and taking it back out. |
11 | | - * Mostly called from Article.php for the emergency abort/fallback to cache. |
12 | | - * |
13 | | - * Global options that affect this module: |
14 | | - * - $wgCachePages |
15 | | - * - $wgCacheEpoch |
16 | | - * - $wgUseFileCache |
17 | | - * - $wgCacheDirectory |
18 | | - * - $wgFileCacheDirectory |
19 | | - * - $wgUseGzip |
20 | | - * |
21 | | - * @ingroup Cache |
22 | | - */ |
23 | | -class HTMLFileCache { |
| 10 | + public static function newFromTitle( Title $title, $action ) { |
| 11 | + $cache = new self(); |
24 | 12 | |
25 | | - /** |
26 | | - * @var Title |
27 | | - */ |
28 | | - var $mTitle; |
29 | | - var $mFileCache, $mType; |
| 13 | + $allowedTypes = self::cacheablePageActions(); |
| 14 | + if ( !in_array( $action, $allowedTypes ) ) { |
| 15 | + throw new MWException( "Invalid filecache type given." ); |
| 16 | + } |
| 17 | + $cache->mKey = $title->getPrefixedDBkey(); |
| 18 | + $cache->mType = (string)$action; |
| 19 | + $cache->mExt = 'html'; |
30 | 20 | |
31 | | - public function __construct( $title, $type = 'view' ) { |
32 | | - $this->mTitle = $title; |
33 | | - $this->mType = in_array( $type, self::cacheableActions() ) ? $type : false; |
34 | | - $this->fileCacheName(); // init name |
| 21 | + return $cache; |
35 | 22 | } |
36 | 23 | |
37 | | - protected static function cacheableActions() { |
| 24 | + /* |
| 25 | + * Cacheable actions |
| 26 | + * @return array |
| 27 | + */ |
| 28 | + protected static function cacheablePageActions() { |
38 | 29 | return array( 'view', 'history' ); |
39 | 30 | } |
40 | 31 | |
41 | | - public function fileCacheName() { |
42 | | - if( !$this->mFileCache ) { |
43 | | - global $wgCacheDirectory, $wgFileCacheDirectory, $wgFileCacheDepth; |
44 | | - |
45 | | - if ( $wgFileCacheDirectory ) { |
46 | | - $dir = $wgFileCacheDirectory; |
47 | | - } elseif ( $wgCacheDirectory ) { |
48 | | - $dir = "$wgCacheDirectory/html"; |
49 | | - } else { |
50 | | - throw new MWException( 'Please set $wgCacheDirectory in LocalSettings.php if you wish to use the HTML file cache' ); |
51 | | - } |
52 | | - |
53 | | - # Store other views of aspects of pages elsewhere |
54 | | - $subdir = ($this->mType === 'view') ? '' : "{$this->mType}/"; |
55 | | - |
56 | | - $key = $this->mTitle->getPrefixedDbkey(); |
57 | | - if ( $wgFileCacheDepth > 0 ) { |
58 | | - $hash = md5( $key ); |
59 | | - for ( $i = 1; $i <= $wgFileCacheDepth; $i++ ) { |
60 | | - $subdir .= substr( $hash, 0, $i ) . '/'; |
61 | | - } |
62 | | - } |
63 | | - # Avoid extension confusion |
64 | | - $key = str_replace( '.', '%2E', urlencode( $key ) ); |
65 | | - $this->mFileCache = "{$dir}/{$subdir}{$key}.html"; |
66 | | - |
67 | | - if( $this->useGzip() ) { |
68 | | - $this->mFileCache .= '.gz'; |
69 | | - } |
70 | | - |
71 | | - wfDebug( __METHOD__ . ": {$this->mFileCache}\n" ); |
| 32 | + /** |
| 33 | + * Get the base file cache directory |
| 34 | + * @return string |
| 35 | + */ |
| 36 | + protected function cacheDirectory() { |
| 37 | + global $wgCacheDirectory, $wgFileCacheDirectory, $wgFileCacheDepth; |
| 38 | + if ( $wgFileCacheDirectory ) { |
| 39 | + $dir = $wgFileCacheDirectory; |
| 40 | + } elseif ( $wgCacheDirectory ) { |
| 41 | + $dir = "$wgCacheDirectory/object"; |
| 42 | + } else { |
| 43 | + throw new MWException( 'Please set $wgCacheDirectory in LocalSettings.php if you wish to use the HTML file cache' ); |
72 | 44 | } |
73 | | - return $this->mFileCache; |
| 45 | + return $dir; |
74 | 46 | } |
75 | 47 | |
76 | | - public function isFileCached() { |
77 | | - if( $this->mType === false ) { |
78 | | - return false; |
79 | | - } |
80 | | - return file_exists( $this->fileCacheName() ); |
81 | | - } |
82 | | - |
83 | | - public function fileCacheTime() { |
84 | | - return wfTimestamp( TS_MW, filemtime( $this->fileCacheName() ) ); |
85 | | - } |
86 | | - |
87 | 48 | /** |
88 | 49 | * Check if pages can be cached for this request/user |
| 50 | + * @param $context RequestContext |
89 | 51 | * @return bool |
90 | 52 | */ |
91 | | - public static function useFileCache() { |
92 | | - global $wgUser, $wgUseFileCache, $wgShowIPinHeader, $wgRequest, $wgLang, $wgContLang; |
93 | | - if( !$wgUseFileCache ) { |
| 53 | + public static function useFileCache( RequestContext $context ) { |
| 54 | + global $wgUseFileCache, $wgShowIPinHeader, $wgContLang; |
| 55 | + if ( !$wgUseFileCache ) { |
94 | 56 | return false; |
95 | 57 | } |
96 | 58 | // Get all query values |
97 | | - $queryVals = $wgRequest->getValues(); |
98 | | - foreach( $queryVals as $query => $val ) { |
99 | | - if( $query == 'title' || $query == 'curid' ) { |
| 59 | + $queryVals = $context->getRequest()->getValues(); |
| 60 | + foreach ( $queryVals as $query => $val ) { |
| 61 | + if ( $query == 'title' || $query == 'curid' ) { |
100 | 62 | continue; // note: curid sets title |
101 | 63 | // Normal page view in query form can have action=view. |
102 | 64 | // Raw hits for pages also stored, like .css pages for example. |
103 | | - } elseif( $query == 'action' && in_array( $val, self::cacheableActions() ) ) { |
| 65 | + } elseif ( $query == 'action' && in_array( $val, self::cacheablePageActions() ) ) { |
104 | 66 | continue; |
105 | 67 | // Below are header setting params |
106 | | - } elseif( $query == 'maxage' || $query == 'smaxage' ) { |
| 68 | + } elseif ( $query == 'maxage' || $query == 'smaxage' ) { |
107 | 69 | continue; |
108 | 70 | } else { |
109 | 71 | return false; |
110 | 72 | } |
111 | 73 | } |
| 74 | + $user = $context->getUser(); |
112 | 75 | // Check for non-standard user language; this covers uselang, |
113 | 76 | // and extensions for auto-detecting user language. |
114 | | - $ulang = $wgLang->getCode(); |
| 77 | + $ulang = $context->getLang()->getCode(); |
115 | 78 | $clang = $wgContLang->getCode(); |
116 | 79 | // Check that there are no other sources of variation |
117 | | - return !$wgShowIPinHeader && !$wgUser->getId() && !$wgUser->getNewtalk() && $ulang == $clang; |
| 80 | + return !$wgShowIPinHeader && !$user->getId() && !$user->getNewtalk() && $ulang == $clang; |
118 | 81 | } |
119 | 82 | |
120 | 83 | /** |
121 | | - * Check if up to date cache file exists |
122 | | - * @param $timestamp string |
123 | | - * |
124 | | - * @return bool |
| 84 | + * Read from cache to context output |
| 85 | + * @param $context RequestContext |
| 86 | + * @return void |
125 | 87 | */ |
126 | | - public function isFileCacheGood( $timestamp = '' ) { |
127 | | - global $wgCacheEpoch; |
| 88 | + public function loadFromFileCache( RequestContext $context ) { |
| 89 | + global $wgMimeType, $wgLanguageCode; |
128 | 90 | |
129 | | - if( !$this->isFileCached() ) { |
130 | | - return false; |
131 | | - } |
132 | | - |
133 | | - $cachetime = $this->fileCacheTime(); |
134 | | - $good = $timestamp <= $cachetime && $wgCacheEpoch <= $cachetime; |
135 | | - |
136 | | - wfDebug( __METHOD__ . ": cachetime $cachetime, touched '{$timestamp}' epoch {$wgCacheEpoch}, good $good\n"); |
137 | | - return $good; |
138 | | - } |
139 | | - |
140 | | - public function useGzip() { |
141 | | - global $wgUseGzip; |
142 | | - return $wgUseGzip; |
143 | | - } |
144 | | - |
145 | | - /* In handy string packages */ |
146 | | - public function fetchRawText() { |
147 | | - return file_get_contents( $this->fileCacheName() ); |
148 | | - } |
149 | | - |
150 | | - public function fetchPageText() { |
151 | | - if( $this->useGzip() ) { |
152 | | - /* Why is there no gzfile_get_contents() or gzdecode()? */ |
153 | | - return implode( '', gzfile( $this->fileCacheName() ) ); |
154 | | - } else { |
155 | | - return $this->fetchRawText(); |
156 | | - } |
157 | | - } |
158 | | - |
159 | | - /* Working directory to/from output */ |
160 | | - public function loadFromFileCache() { |
161 | | - global $wgOut, $wgMimeType, $wgLanguageCode; |
162 | 91 | wfDebug( __METHOD__ . "()\n"); |
163 | | - $filename = $this->fileCacheName(); |
164 | | - $wgOut->sendCacheControl(); |
| 92 | + $filename = $this->cachePath(); |
| 93 | + $context->getOutput()->sendCacheControl(); |
165 | 94 | header( "Content-Type: $wgMimeType; charset=UTF-8" ); |
166 | 95 | header( "Content-Language: $wgLanguageCode" ); |
167 | | - if( $this->useGzip() ) { |
168 | | - if( wfClientAcceptsGzip() ) { |
| 96 | + if ( $this->useGzip() ) { |
| 97 | + if ( wfClientAcceptsGzip() ) { |
169 | 98 | header( 'Content-Encoding: gzip' ); |
170 | 99 | } else { |
171 | 100 | /* Send uncompressed */ |
— | — | @@ -173,71 +102,70 @@ |
174 | 103 | } |
175 | 104 | } |
176 | 105 | readfile( $filename ); |
177 | | - $wgOut->disable(); // tell $wgOut that output is taken care of |
| 106 | + $context->getOutput()->disable(); // tell $wgOut that output is taken care of |
178 | 107 | } |
179 | 108 | |
180 | | - protected function checkCacheDirs() { |
181 | | - $filename = $this->fileCacheName(); |
182 | | - $mydir2 = substr($filename,0,strrpos($filename,'/')); # subdirectory level 2 |
183 | | - $mydir1 = substr($mydir2,0,strrpos($mydir2,'/')); # subdirectory level 1 |
184 | | - |
185 | | - wfMkdirParents( $mydir1, null, __METHOD__ ); |
186 | | - wfMkdirParents( $mydir2, null, __METHOD__ ); |
187 | | - } |
188 | | - |
| 109 | + /** |
| 110 | + * Save this cache object with the given text. |
| 111 | + * Use this as an ob_start() handler. |
| 112 | + * @param $text string |
| 113 | + * @return bool Whether $wgUseFileCache is enabled |
| 114 | + */ |
189 | 115 | public function saveToFileCache( $text ) { |
190 | 116 | global $wgUseFileCache; |
191 | | - if( !$wgUseFileCache || strlen( $text ) < 512 ) { |
| 117 | + |
| 118 | + if ( !$wgUseFileCache || strlen( $text ) < 512 ) { |
192 | 119 | // Disabled or empty/broken output (OOM and PHP errors) |
193 | 120 | return $text; |
194 | 121 | } |
195 | 122 | |
196 | 123 | wfDebug( __METHOD__ . "()\n", false); |
197 | 124 | |
198 | | - $this->checkCacheDirs(); |
| 125 | + $now = wfTimestampNow(); |
| 126 | + if ( $this->useGzip() ) { |
| 127 | + $text = str_replace( |
| 128 | + '</html>', '<!-- Cached/compressed '.$now." -->\n</html>", $text ); |
| 129 | + } else { |
| 130 | + $text = str_replace( |
| 131 | + '</html>', '<!-- Cached '.$now." -->\n</html>", $text ); |
| 132 | + } |
199 | 133 | |
200 | | - $f = fopen( $this->fileCacheName(), 'w' ); |
201 | | - if($f) { |
202 | | - $now = wfTimestampNow(); |
203 | | - if( $this->useGzip() ) { |
204 | | - $rawtext = str_replace( '</html>', |
205 | | - '<!-- Cached/compressed '.$now." -->\n</html>", |
206 | | - $text ); |
207 | | - $text = gzencode( $rawtext ); |
| 134 | + // Store text to FS... |
| 135 | + $compressed = $this->saveText( $text ); |
| 136 | + if ( $compressed === false ) { |
| 137 | + return $text; // error |
| 138 | + } |
| 139 | + |
| 140 | + // gzip output to buffer as needed and set headers... |
| 141 | + if ( $this->useGzip() ) { |
| 142 | + // @TODO: ugly wfClientAcceptsGzip() function - use context! |
| 143 | + if ( wfClientAcceptsGzip() ) { |
| 144 | + header( 'Content-Encoding: gzip' ); |
| 145 | + return $compressed; |
208 | 146 | } else { |
209 | | - $text = str_replace( '</html>', |
210 | | - '<!-- Cached '.$now." -->\n</html>", |
211 | | - $text ); |
212 | | - } |
213 | | - fwrite( $f, $text ); |
214 | | - fclose( $f ); |
215 | | - if( $this->useGzip() ) { |
216 | | - if( wfClientAcceptsGzip() ) { |
217 | | - header( 'Content-Encoding: gzip' ); |
218 | | - return $text; |
219 | | - } else { |
220 | | - return $rawtext; |
221 | | - } |
222 | | - } else { |
223 | 147 | return $text; |
224 | 148 | } |
| 149 | + } else { |
| 150 | + return $text; |
225 | 151 | } |
226 | | - return $text; |
227 | 152 | } |
228 | 153 | |
229 | | - public static function clearFileCache( $title ) { |
| 154 | + /** |
| 155 | + * Clear the file caches for a page for all actions |
| 156 | + * @param $title Title |
| 157 | + * @return bool Whether $wgUseFileCache is enabled |
| 158 | + */ |
| 159 | + public static function clearFileCache( Title $title ) { |
230 | 160 | global $wgUseFileCache; |
231 | 161 | |
232 | 162 | if ( !$wgUseFileCache ) { |
233 | 163 | return false; |
234 | 164 | } |
235 | 165 | |
236 | | - wfSuppressWarnings(); |
237 | | - foreach( self::cacheableActions() as $type ) { |
238 | | - $fc = new self( $title, $type ); |
239 | | - unlink( $fc->fileCacheName() ); |
| 166 | + foreach ( self::cacheablePageActions() as $type ) { |
| 167 | + $fc = self::newFromTitle( $title, $type ); |
| 168 | + $fc->clearCache(); |
240 | 169 | } |
241 | | - wfRestoreWarnings(); |
242 | 170 | |
243 | 171 | return true; |
244 | 172 | } |