MediaWiki
REL1_19
|
00001 <?php 00009 class DependencyWrapper { 00010 var $value; 00011 var $deps; 00012 00019 function __construct( $value = false, $deps = array() ) { 00020 $this->value = $value; 00021 00022 if ( !is_array( $deps ) ) { 00023 $deps = array( $deps ); 00024 } 00025 00026 $this->deps = $deps; 00027 } 00028 00034 function isExpired() { 00035 foreach ( $this->deps as $dep ) { 00036 if ( $dep->isExpired() ) { 00037 return true; 00038 } 00039 } 00040 00041 return false; 00042 } 00043 00048 function initialiseDeps() { 00049 foreach ( $this->deps as $dep ) { 00050 $dep->loadDependencyValues(); 00051 } 00052 } 00053 00058 function getValue() { 00059 return $this->value; 00060 } 00061 00069 function storeToCache( $cache, $key, $expiry = 0 ) { 00070 $this->initialiseDeps(); 00071 $cache->set( $key, $this, $expiry ); 00072 } 00073 00091 static function getValueFromCache( $cache, $key, $expiry = 0, $callback = false, 00092 $callbackParams = array(), $deps = array() ) 00093 { 00094 $obj = $cache->get( $key ); 00095 00096 if ( is_object( $obj ) && $obj instanceof DependencyWrapper && !$obj->isExpired() ) { 00097 $value = $obj->value; 00098 } elseif ( $callback ) { 00099 $value = call_user_func_array( $callback, $callbackParams ); 00100 # Cache the newly-generated value 00101 $wrapper = new DependencyWrapper( $value, $deps ); 00102 $wrapper->storeToCache( $cache, $key, $expiry ); 00103 } else { 00104 $value = null; 00105 } 00106 00107 return $value; 00108 } 00109 } 00110 00114 abstract class CacheDependency { 00118 abstract function isExpired(); 00119 00123 function loadDependencyValues() { } 00124 } 00125 00129 class FileDependency extends CacheDependency { 00130 var $filename, $timestamp; 00131 00144 function __construct( $filename, $timestamp = null ) { 00145 $this->filename = $filename; 00146 $this->timestamp = $timestamp; 00147 } 00148 00152 function __sleep() { 00153 $this->loadDependencyValues(); 00154 return array( 'filename', 'timestamp' ); 00155 } 00156 00157 function loadDependencyValues() { 00158 if ( is_null( $this->timestamp ) ) { 00159 if ( !file_exists( $this->filename ) ) { 00160 # Dependency on a non-existent file 00161 # This is a valid concept! 00162 $this->timestamp = false; 00163 } else { 00164 $this->timestamp = filemtime( $this->filename ); 00165 } 00166 } 00167 } 00168 00172 function isExpired() { 00173 if ( !file_exists( $this->filename ) ) { 00174 if ( $this->timestamp === false ) { 00175 # Still nonexistent 00176 return false; 00177 } else { 00178 # Deleted 00179 wfDebug( "Dependency triggered: {$this->filename} deleted.\n" ); 00180 return true; 00181 } 00182 } else { 00183 $lastmod = filemtime( $this->filename ); 00184 if ( $lastmod > $this->timestamp ) { 00185 # Modified or created 00186 wfDebug( "Dependency triggered: {$this->filename} changed.\n" ); 00187 return true; 00188 } else { 00189 # Not modified 00190 return false; 00191 } 00192 } 00193 } 00194 } 00195 00199 class TitleDependency extends CacheDependency { 00200 var $titleObj; 00201 var $ns, $dbk; 00202 var $touched; 00203 00208 function __construct( Title $title ) { 00209 $this->titleObj = $title; 00210 $this->ns = $title->getNamespace(); 00211 $this->dbk = $title->getDBkey(); 00212 } 00213 00214 function loadDependencyValues() { 00215 $this->touched = $this->getTitle()->getTouched(); 00216 } 00217 00223 function __sleep() { 00224 return array( 'ns', 'dbk', 'touched' ); 00225 } 00226 00230 function getTitle() { 00231 if ( !isset( $this->titleObj ) ) { 00232 $this->titleObj = Title::makeTitle( $this->ns, $this->dbk ); 00233 } 00234 00235 return $this->titleObj; 00236 } 00237 00241 function isExpired() { 00242 $touched = $this->getTitle()->getTouched(); 00243 00244 if ( $this->touched === false ) { 00245 if ( $touched === false ) { 00246 # Still missing 00247 return false; 00248 } else { 00249 # Created 00250 return true; 00251 } 00252 } elseif ( $touched === false ) { 00253 # Deleted 00254 return true; 00255 } elseif ( $touched > $this->touched ) { 00256 # Updated 00257 return true; 00258 } else { 00259 # Unmodified 00260 return false; 00261 } 00262 } 00263 } 00264 00268 class TitleListDependency extends CacheDependency { 00269 var $linkBatch; 00270 var $timestamps; 00271 00276 function __construct( LinkBatch $linkBatch ) { 00277 $this->linkBatch = $linkBatch; 00278 } 00279 00283 function calculateTimestamps() { 00284 # Initialise values to false 00285 $timestamps = array(); 00286 00287 foreach ( $this->getLinkBatch()->data as $ns => $dbks ) { 00288 if ( count( $dbks ) > 0 ) { 00289 $timestamps[$ns] = array(); 00290 00291 foreach ( $dbks as $dbk => $value ) { 00292 $timestamps[$ns][$dbk] = false; 00293 } 00294 } 00295 } 00296 00297 # Do the query 00298 if ( count( $timestamps ) ) { 00299 $dbr = wfGetDB( DB_SLAVE ); 00300 $where = $this->getLinkBatch()->constructSet( 'page', $dbr ); 00301 $res = $dbr->select( 00302 'page', 00303 array( 'page_namespace', 'page_title', 'page_touched' ), 00304 $where, 00305 __METHOD__ 00306 ); 00307 00308 foreach ( $res as $row ) { 00309 $timestamps[$row->page_namespace][$row->page_title] = $row->page_touched; 00310 } 00311 } 00312 00313 return $timestamps; 00314 } 00315 00316 function loadDependencyValues() { 00317 $this->timestamps = $this->calculateTimestamps(); 00318 } 00319 00323 function __sleep() { 00324 return array( 'timestamps' ); 00325 } 00326 00330 function getLinkBatch() { 00331 if ( !isset( $this->linkBatch ) ) { 00332 $this->linkBatch = new LinkBatch; 00333 $this->linkBatch->setArray( $this->timestamps ); 00334 } 00335 return $this->linkBatch; 00336 } 00337 00341 function isExpired() { 00342 $newTimestamps = $this->calculateTimestamps(); 00343 00344 foreach ( $this->timestamps as $ns => $dbks ) { 00345 foreach ( $dbks as $dbk => $oldTimestamp ) { 00346 $newTimestamp = $newTimestamps[$ns][$dbk]; 00347 00348 if ( $oldTimestamp === false ) { 00349 if ( $newTimestamp === false ) { 00350 # Still missing 00351 } else { 00352 # Created 00353 return true; 00354 } 00355 } elseif ( $newTimestamp === false ) { 00356 # Deleted 00357 return true; 00358 } elseif ( $newTimestamp > $oldTimestamp ) { 00359 # Updated 00360 return true; 00361 } else { 00362 # Unmodified 00363 } 00364 } 00365 } 00366 00367 return false; 00368 } 00369 } 00370 00374 class GlobalDependency extends CacheDependency { 00375 var $name, $value; 00376 00377 function __construct( $name ) { 00378 $this->name = $name; 00379 $this->value = $GLOBALS[$name]; 00380 } 00381 00385 function isExpired() { 00386 if( !isset($GLOBALS[$this->name]) ) { 00387 return true; 00388 } 00389 return $GLOBALS[$this->name] != $this->value; 00390 } 00391 } 00392 00396 class ConstantDependency extends CacheDependency { 00397 var $name, $value; 00398 00399 function __construct( $name ) { 00400 $this->name = $name; 00401 $this->value = constant( $name ); 00402 } 00403 00407 function isExpired() { 00408 return constant( $this->name ) != $this->value; 00409 } 00410 }