MediaWiki
REL1_22
|
00001 <?php 00030 class DependencyWrapper { 00031 var $value; 00032 var $deps; 00033 00040 function __construct( $value = false, $deps = array() ) { 00041 $this->value = $value; 00042 00043 if ( !is_array( $deps ) ) { 00044 $deps = array( $deps ); 00045 } 00046 00047 $this->deps = $deps; 00048 } 00049 00055 function isExpired() { 00056 foreach ( $this->deps as $dep ) { 00057 if ( $dep->isExpired() ) { 00058 return true; 00059 } 00060 } 00061 00062 return false; 00063 } 00064 00069 function initialiseDeps() { 00070 foreach ( $this->deps as $dep ) { 00071 $dep->loadDependencyValues(); 00072 } 00073 } 00074 00079 function getValue() { 00080 return $this->value; 00081 } 00082 00090 function storeToCache( $cache, $key, $expiry = 0 ) { 00091 $this->initialiseDeps(); 00092 $cache->set( $key, $this, $expiry ); 00093 } 00094 00112 static function getValueFromCache( $cache, $key, $expiry = 0, $callback = false, 00113 $callbackParams = array(), $deps = array() ) 00114 { 00115 $obj = $cache->get( $key ); 00116 00117 if ( is_object( $obj ) && $obj instanceof DependencyWrapper && !$obj->isExpired() ) { 00118 $value = $obj->value; 00119 } elseif ( $callback ) { 00120 $value = call_user_func_array( $callback, $callbackParams ); 00121 # Cache the newly-generated value 00122 $wrapper = new DependencyWrapper( $value, $deps ); 00123 $wrapper->storeToCache( $cache, $key, $expiry ); 00124 } else { 00125 $value = null; 00126 } 00127 00128 return $value; 00129 } 00130 } 00131 00135 abstract class CacheDependency { 00139 abstract function isExpired(); 00140 00144 function loadDependencyValues() { } 00145 } 00146 00150 class FileDependency extends CacheDependency { 00151 var $filename, $timestamp; 00152 00165 function __construct( $filename, $timestamp = null ) { 00166 $this->filename = $filename; 00167 $this->timestamp = $timestamp; 00168 } 00169 00173 function __sleep() { 00174 $this->loadDependencyValues(); 00175 return array( 'filename', 'timestamp' ); 00176 } 00177 00178 function loadDependencyValues() { 00179 if ( is_null( $this->timestamp ) ) { 00180 if ( !file_exists( $this->filename ) ) { 00181 # Dependency on a non-existent file 00182 # This is a valid concept! 00183 $this->timestamp = false; 00184 } else { 00185 $this->timestamp = filemtime( $this->filename ); 00186 } 00187 } 00188 } 00189 00193 function isExpired() { 00194 if ( !file_exists( $this->filename ) ) { 00195 if ( $this->timestamp === false ) { 00196 # Still nonexistent 00197 return false; 00198 } else { 00199 # Deleted 00200 wfDebug( "Dependency triggered: {$this->filename} deleted.\n" ); 00201 return true; 00202 } 00203 } else { 00204 $lastmod = filemtime( $this->filename ); 00205 if ( $lastmod > $this->timestamp ) { 00206 # Modified or created 00207 wfDebug( "Dependency triggered: {$this->filename} changed.\n" ); 00208 return true; 00209 } else { 00210 # Not modified 00211 return false; 00212 } 00213 } 00214 } 00215 } 00216 00220 class TitleDependency extends CacheDependency { 00221 var $titleObj; 00222 var $ns, $dbk; 00223 var $touched; 00224 00229 function __construct( Title $title ) { 00230 $this->titleObj = $title; 00231 $this->ns = $title->getNamespace(); 00232 $this->dbk = $title->getDBkey(); 00233 } 00234 00235 function loadDependencyValues() { 00236 $this->touched = $this->getTitle()->getTouched(); 00237 } 00238 00244 function __sleep() { 00245 return array( 'ns', 'dbk', 'touched' ); 00246 } 00247 00251 function getTitle() { 00252 if ( !isset( $this->titleObj ) ) { 00253 $this->titleObj = Title::makeTitle( $this->ns, $this->dbk ); 00254 } 00255 00256 return $this->titleObj; 00257 } 00258 00262 function isExpired() { 00263 $touched = $this->getTitle()->getTouched(); 00264 00265 if ( $this->touched === false ) { 00266 if ( $touched === false ) { 00267 # Still missing 00268 return false; 00269 } else { 00270 # Created 00271 return true; 00272 } 00273 } elseif ( $touched === false ) { 00274 # Deleted 00275 return true; 00276 } elseif ( $touched > $this->touched ) { 00277 # Updated 00278 return true; 00279 } else { 00280 # Unmodified 00281 return false; 00282 } 00283 } 00284 } 00285 00289 class TitleListDependency extends CacheDependency { 00290 var $linkBatch; 00291 var $timestamps; 00292 00297 function __construct( LinkBatch $linkBatch ) { 00298 $this->linkBatch = $linkBatch; 00299 } 00300 00304 function calculateTimestamps() { 00305 # Initialise values to false 00306 $timestamps = array(); 00307 00308 foreach ( $this->getLinkBatch()->data as $ns => $dbks ) { 00309 if ( count( $dbks ) > 0 ) { 00310 $timestamps[$ns] = array(); 00311 00312 foreach ( $dbks as $dbk => $value ) { 00313 $timestamps[$ns][$dbk] = false; 00314 } 00315 } 00316 } 00317 00318 # Do the query 00319 if ( count( $timestamps ) ) { 00320 $dbr = wfGetDB( DB_SLAVE ); 00321 $where = $this->getLinkBatch()->constructSet( 'page', $dbr ); 00322 $res = $dbr->select( 00323 'page', 00324 array( 'page_namespace', 'page_title', 'page_touched' ), 00325 $where, 00326 __METHOD__ 00327 ); 00328 00329 foreach ( $res as $row ) { 00330 $timestamps[$row->page_namespace][$row->page_title] = $row->page_touched; 00331 } 00332 } 00333 00334 return $timestamps; 00335 } 00336 00337 function loadDependencyValues() { 00338 $this->timestamps = $this->calculateTimestamps(); 00339 } 00340 00344 function __sleep() { 00345 return array( 'timestamps' ); 00346 } 00347 00351 function getLinkBatch() { 00352 if ( !isset( $this->linkBatch ) ) { 00353 $this->linkBatch = new LinkBatch; 00354 $this->linkBatch->setArray( $this->timestamps ); 00355 } 00356 return $this->linkBatch; 00357 } 00358 00362 function isExpired() { 00363 $newTimestamps = $this->calculateTimestamps(); 00364 00365 foreach ( $this->timestamps as $ns => $dbks ) { 00366 foreach ( $dbks as $dbk => $oldTimestamp ) { 00367 $newTimestamp = $newTimestamps[$ns][$dbk]; 00368 00369 if ( $oldTimestamp === false ) { 00370 if ( $newTimestamp === false ) { 00371 # Still missing 00372 } else { 00373 # Created 00374 return true; 00375 } 00376 } elseif ( $newTimestamp === false ) { 00377 # Deleted 00378 return true; 00379 } elseif ( $newTimestamp > $oldTimestamp ) { 00380 # Updated 00381 return true; 00382 } else { 00383 # Unmodified 00384 } 00385 } 00386 } 00387 00388 return false; 00389 } 00390 } 00391 00395 class GlobalDependency extends CacheDependency { 00396 var $name, $value; 00397 00398 function __construct( $name ) { 00399 $this->name = $name; 00400 $this->value = $GLOBALS[$name]; 00401 } 00402 00406 function isExpired() { 00407 if ( !isset( $GLOBALS[$this->name] ) ) { 00408 return true; 00409 } 00410 return $GLOBALS[$this->name] != $this->value; 00411 } 00412 } 00413 00417 class ConstantDependency extends CacheDependency { 00418 var $name, $value; 00419 00420 function __construct( $name ) { 00421 $this->name = $name; 00422 $this->value = constant( $name ); 00423 } 00424 00428 function isExpired() { 00429 return constant( $this->name ) != $this->value; 00430 } 00431 }