[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Cache of various elements in a single cache entry. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * http://www.gnu.org/copyleft/gpl.html 19 * 20 * @file 21 * @license GNU GPL v2 or later 22 * @author Jeroen De Dauw < [email protected] > 23 */ 24 25 /** 26 * Interface for all classes implementing CacheHelper functionality. 27 * 28 * @since 1.20 29 */ 30 interface ICacheHelper { 31 /** 32 * Sets if the cache should be enabled or not. 33 * 34 * @since 1.20 35 * @param bool $cacheEnabled 36 */ 37 function setCacheEnabled( $cacheEnabled ); 38 39 /** 40 * Initializes the caching. 41 * Should be called before the first time anything is added via addCachedHTML. 42 * 43 * @since 1.20 44 * 45 * @param int|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp. 46 * @param bool|null $cacheEnabled Sets if the cache should be enabled or not. 47 */ 48 function startCache( $cacheExpiry = null, $cacheEnabled = null ); 49 50 /** 51 * Get a cached value if available or compute it if not and then cache it if possible. 52 * The provided $computeFunction is only called when the computation needs to happen 53 * and should return a result value. $args are arguments that will be passed to the 54 * compute function when called. 55 * 56 * @since 1.20 57 * 58 * @param callable $computeFunction 59 * @param array|mixed $args 60 * @param string|null $key 61 * 62 * @return mixed 63 */ 64 function getCachedValue( $computeFunction, $args = array(), $key = null ); 65 66 /** 67 * Saves the HTML to the cache in case it got recomputed. 68 * Should be called after the last time anything is added via addCachedHTML. 69 * 70 * @since 1.20 71 */ 72 function saveCache(); 73 74 /** 75 * Sets the time to live for the cache, in seconds or a unix timestamp 76 * indicating the point of expiry... 77 * 78 * @since 1.20 79 * 80 * @param int $cacheExpiry 81 */ 82 function setExpiry( $cacheExpiry ); 83 } 84 85 /** 86 * Helper class for caching various elements in a single cache entry. 87 * 88 * To get a cached value or compute it, use getCachedValue like this: 89 * $this->getCachedValue( $callback ); 90 * 91 * To add HTML that should be cached, use addCachedHTML like this: 92 * $this->addCachedHTML( $callback ); 93 * 94 * The callback function is only called when needed, so do all your expensive 95 * computations here. This function should returns the HTML to be cached. 96 * It should not add anything to the PageOutput object! 97 * 98 * Before the first addCachedHTML call, you should call $this->startCache(); 99 * After adding the last HTML that should be cached, call $this->saveCache(); 100 * 101 * @since 1.20 102 */ 103 class CacheHelper implements ICacheHelper { 104 /** 105 * The time to live for the cache, in seconds or a unix timestamp indicating the point of expiry. 106 * 107 * @since 1.20 108 * @var int 109 */ 110 protected $cacheExpiry = 3600; 111 112 /** 113 * List of HTML chunks to be cached (if !hasCached) or that where cached (of hasCached). 114 * If not cached already, then the newly computed chunks are added here, 115 * if it as cached already, chunks are removed from this list as they are needed. 116 * 117 * @since 1.20 118 * @var array 119 */ 120 protected $cachedChunks; 121 122 /** 123 * Indicates if the to be cached content was already cached. 124 * Null if this information is not available yet. 125 * 126 * @since 1.20 127 * @var bool|null 128 */ 129 protected $hasCached = null; 130 131 /** 132 * If the cache is enabled or not. 133 * 134 * @since 1.20 135 * @var bool 136 */ 137 protected $cacheEnabled = true; 138 139 /** 140 * Function that gets called when initialization is done. 141 * 142 * @since 1.20 143 * @var callable 144 */ 145 protected $onInitHandler = false; 146 147 /** 148 * Elements to build a cache key with. 149 * 150 * @since 1.20 151 * @var array 152 */ 153 protected $cacheKey = array(); 154 155 /** 156 * Sets if the cache should be enabled or not. 157 * 158 * @since 1.20 159 * @param bool $cacheEnabled 160 */ 161 public function setCacheEnabled( $cacheEnabled ) { 162 $this->cacheEnabled = $cacheEnabled; 163 } 164 165 /** 166 * Initializes the caching. 167 * Should be called before the first time anything is added via addCachedHTML. 168 * 169 * @since 1.20 170 * 171 * @param int|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp. 172 * @param bool|null $cacheEnabled Sets if the cache should be enabled or not. 173 */ 174 public function startCache( $cacheExpiry = null, $cacheEnabled = null ) { 175 if ( is_null( $this->hasCached ) ) { 176 if ( !is_null( $cacheExpiry ) ) { 177 $this->cacheExpiry = $cacheExpiry; 178 } 179 180 if ( !is_null( $cacheEnabled ) ) { 181 $this->setCacheEnabled( $cacheEnabled ); 182 } 183 184 $this->initCaching(); 185 } 186 } 187 188 /** 189 * Returns a message that notifies the user he/she is looking at 190 * a cached version of the page, including a refresh link. 191 * 192 * @since 1.20 193 * 194 * @param IContextSource $context 195 * @param bool $includePurgeLink 196 * 197 * @return string 198 */ 199 public function getCachedNotice( IContextSource $context, $includePurgeLink = true ) { 200 if ( $this->cacheExpiry < 86400 * 3650 ) { 201 $message = $context->msg( 202 'cachedspecial-viewing-cached-ttl', 203 $context->getLanguage()->formatDuration( $this->cacheExpiry ) 204 )->escaped(); 205 } else { 206 $message = $context->msg( 207 'cachedspecial-viewing-cached-ts' 208 )->escaped(); 209 } 210 211 if ( $includePurgeLink ) { 212 $refreshArgs = $context->getRequest()->getQueryValues(); 213 unset( $refreshArgs['title'] ); 214 $refreshArgs['action'] = 'purge'; 215 216 $subPage = $context->getTitle()->getFullText(); 217 $subPage = explode( '/', $subPage, 2 ); 218 $subPage = count( $subPage ) > 1 ? $subPage[1] : false; 219 220 $message .= ' ' . Linker::link( 221 $context->getTitle( $subPage ), 222 $context->msg( 'cachedspecial-refresh-now' )->escaped(), 223 array(), 224 $refreshArgs 225 ); 226 } 227 228 return $message; 229 } 230 231 /** 232 * Initializes the caching if not already done so. 233 * Should be called before any of the caching functionality is used. 234 * 235 * @since 1.20 236 */ 237 protected function initCaching() { 238 if ( $this->cacheEnabled && is_null( $this->hasCached ) ) { 239 $cachedChunks = wfGetCache( CACHE_ANYTHING )->get( $this->getCacheKeyString() ); 240 241 $this->hasCached = is_array( $cachedChunks ); 242 $this->cachedChunks = $this->hasCached ? $cachedChunks : array(); 243 244 if ( $this->onInitHandler !== false ) { 245 call_user_func( $this->onInitHandler, $this->hasCached ); 246 } 247 } 248 } 249 250 /** 251 * Get a cached value if available or compute it if not and then cache it if possible. 252 * The provided $computeFunction is only called when the computation needs to happen 253 * and should return a result value. $args are arguments that will be passed to the 254 * compute function when called. 255 * 256 * @since 1.20 257 * 258 * @param callable $computeFunction 259 * @param array|mixed $args 260 * @param string|null $key 261 * 262 * @return mixed 263 */ 264 public function getCachedValue( $computeFunction, $args = array(), $key = null ) { 265 $this->initCaching(); 266 267 if ( $this->cacheEnabled && $this->hasCached ) { 268 $value = null; 269 270 if ( is_null( $key ) ) { 271 $itemKey = array_keys( array_slice( $this->cachedChunks, 0, 1 ) ); 272 $itemKey = array_shift( $itemKey ); 273 274 if ( !is_integer( $itemKey ) ) { 275 wfWarn( "Attempted to get item with non-numeric key while " . 276 "the next item in the queue has a key ($itemKey) in " . __METHOD__ ); 277 } elseif ( is_null( $itemKey ) ) { 278 wfWarn( "Attempted to get an item while the queue is empty in " . __METHOD__ ); 279 } else { 280 $value = array_shift( $this->cachedChunks ); 281 } 282 } else { 283 if ( array_key_exists( $key, $this->cachedChunks ) ) { 284 $value = $this->cachedChunks[$key]; 285 unset( $this->cachedChunks[$key] ); 286 } else { 287 wfWarn( "There is no item with key '$key' in this->cachedChunks in " . __METHOD__ ); 288 } 289 } 290 } else { 291 if ( !is_array( $args ) ) { 292 $args = array( $args ); 293 } 294 295 $value = call_user_func_array( $computeFunction, $args ); 296 297 if ( $this->cacheEnabled ) { 298 if ( is_null( $key ) ) { 299 $this->cachedChunks[] = $value; 300 } else { 301 $this->cachedChunks[$key] = $value; 302 } 303 } 304 } 305 306 return $value; 307 } 308 309 /** 310 * Saves the HTML to the cache in case it got recomputed. 311 * Should be called after the last time anything is added via addCachedHTML. 312 * 313 * @since 1.20 314 */ 315 public function saveCache() { 316 if ( $this->cacheEnabled && $this->hasCached === false && !empty( $this->cachedChunks ) ) { 317 wfGetCache( CACHE_ANYTHING )->set( 318 $this->getCacheKeyString(), 319 $this->cachedChunks, 320 $this->cacheExpiry 321 ); 322 } 323 } 324 325 /** 326 * Sets the time to live for the cache, in seconds or a unix timestamp 327 * indicating the point of expiry... 328 * 329 * @since 1.20 330 * 331 * @param int $cacheExpiry 332 */ 333 public function setExpiry( $cacheExpiry ) { 334 $this->cacheExpiry = $cacheExpiry; 335 } 336 337 /** 338 * Returns the cache key to use to cache this page's HTML output. 339 * Is constructed from the special page name and language code. 340 * 341 * @since 1.20 342 * 343 * @return string 344 * @throws MWException 345 */ 346 protected function getCacheKeyString() { 347 if ( $this->cacheKey === array() ) { 348 throw new MWException( 'No cache key set, so cannot obtain or save the CacheHelper values.' ); 349 } 350 351 return call_user_func_array( 'wfMemcKey', $this->cacheKey ); 352 } 353 354 /** 355 * Sets the cache key that should be used. 356 * 357 * @since 1.20 358 * 359 * @param array $cacheKey 360 */ 361 public function setCacheKey( array $cacheKey ) { 362 $this->cacheKey = $cacheKey; 363 } 364 365 /** 366 * Rebuild the content, even if it's already cached. 367 * This effectively has the same effect as purging the cache, 368 * since it will be overridden with the new value on the next request. 369 * 370 * @since 1.20 371 */ 372 public function rebuildOnDemand() { 373 $this->hasCached = false; 374 } 375 376 /** 377 * Sets a function that gets called when initialization of the cache is done. 378 * 379 * @since 1.20 380 * 381 * @param callable $handlerFunction 382 */ 383 public function setOnInitializedHandler( $handlerFunction ) { 384 $this->onInitHandler = $handlerFunction; 385 } 386 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |