MediaWiki
REL1_22
|
00001 <?php 00029 class RepoGroup { 00033 var $localRepo; 00034 00035 var $foreignRepos, $reposInitialised = false; 00036 var $localInfo, $foreignInfo; 00037 var $cache; 00038 00042 protected static $instance; 00043 const MAX_CACHE_SIZE = 500; 00044 00050 static function singleton() { 00051 if ( self::$instance ) { 00052 return self::$instance; 00053 } 00054 global $wgLocalFileRepo, $wgForeignFileRepos; 00055 self::$instance = new RepoGroup( $wgLocalFileRepo, $wgForeignFileRepos ); 00056 return self::$instance; 00057 } 00058 00063 static function destroySingleton() { 00064 self::$instance = null; 00065 } 00066 00075 static function setSingleton( $instance ) { 00076 self::$instance = $instance; 00077 } 00078 00088 function __construct( $localInfo, $foreignInfo ) { 00089 $this->localInfo = $localInfo; 00090 $this->foreignInfo = $foreignInfo; 00091 $this->cache = array(); 00092 } 00093 00113 function findFile( $title, $options = array() ) { 00114 if ( !is_array( $options ) ) { 00115 // MW 1.15 compat 00116 $options = array( 'time' => $options ); 00117 } 00118 if ( !$this->reposInitialised ) { 00119 $this->initialiseRepos(); 00120 } 00121 $title = File::normalizeTitle( $title ); 00122 if ( !$title ) { 00123 return false; 00124 } 00125 00126 # Check the cache 00127 if ( empty( $options['ignoreRedirect'] ) 00128 && empty( $options['private'] ) 00129 && empty( $options['bypassCache'] ) ) 00130 { 00131 $time = isset( $options['time'] ) ? $options['time'] : ''; 00132 $dbkey = $title->getDBkey(); 00133 if ( isset( $this->cache[$dbkey][$time] ) ) { 00134 wfDebug( __METHOD__ . ": got File:$dbkey from process cache\n" ); 00135 # Move it to the end of the list so that we can delete the LRU entry later 00136 $this->pingCache( $dbkey ); 00137 # Return the entry 00138 return $this->cache[$dbkey][$time]; 00139 } 00140 $useCache = true; 00141 } else { 00142 $useCache = false; 00143 } 00144 00145 # Check the local repo 00146 $image = $this->localRepo->findFile( $title, $options ); 00147 00148 # Check the foreign repos 00149 if ( !$image ) { 00150 foreach ( $this->foreignRepos as $repo ) { 00151 $image = $repo->findFile( $title, $options ); 00152 if ( $image ) { 00153 break; 00154 } 00155 } 00156 } 00157 00158 $image = $image ? $image : false; // type sanity 00159 # Cache file existence or non-existence 00160 if ( $useCache && ( !$image || $image->isCacheable() ) ) { 00161 $this->trimCache(); 00162 $this->cache[$dbkey][$time] = $image; 00163 } 00164 00165 return $image; 00166 } 00167 00172 function findFiles( $inputItems ) { 00173 if ( !$this->reposInitialised ) { 00174 $this->initialiseRepos(); 00175 } 00176 00177 $items = array(); 00178 foreach ( $inputItems as $item ) { 00179 if ( !is_array( $item ) ) { 00180 $item = array( 'title' => $item ); 00181 } 00182 $item['title'] = File::normalizeTitle( $item['title'] ); 00183 if ( $item['title'] ) { 00184 $items[$item['title']->getDBkey()] = $item; 00185 } 00186 } 00187 00188 $images = $this->localRepo->findFiles( $items ); 00189 00190 foreach ( $this->foreignRepos as $repo ) { 00191 // Remove found files from $items 00192 foreach ( $images as $name => $image ) { 00193 unset( $items[$name] ); 00194 } 00195 00196 $images = array_merge( $images, $repo->findFiles( $items ) ); 00197 } 00198 return $images; 00199 } 00200 00206 function checkRedirect( Title $title ) { 00207 if ( !$this->reposInitialised ) { 00208 $this->initialiseRepos(); 00209 } 00210 00211 $redir = $this->localRepo->checkRedirect( $title ); 00212 if ( $redir ) { 00213 return $redir; 00214 } 00215 foreach ( $this->foreignRepos as $repo ) { 00216 $redir = $repo->checkRedirect( $title ); 00217 if ( $redir ) { 00218 return $redir; 00219 } 00220 } 00221 return false; 00222 } 00223 00232 function findFileFromKey( $hash, $options = array() ) { 00233 if ( !$this->reposInitialised ) { 00234 $this->initialiseRepos(); 00235 } 00236 00237 $file = $this->localRepo->findFileFromKey( $hash, $options ); 00238 if ( !$file ) { 00239 foreach ( $this->foreignRepos as $repo ) { 00240 $file = $repo->findFileFromKey( $hash, $options ); 00241 if ( $file ) { 00242 break; 00243 } 00244 } 00245 } 00246 return $file; 00247 } 00248 00255 function findBySha1( $hash ) { 00256 if ( !$this->reposInitialised ) { 00257 $this->initialiseRepos(); 00258 } 00259 00260 $result = $this->localRepo->findBySha1( $hash ); 00261 foreach ( $this->foreignRepos as $repo ) { 00262 $result = array_merge( $result, $repo->findBySha1( $hash ) ); 00263 } 00264 usort( $result, 'File::compare' ); 00265 return $result; 00266 } 00267 00274 function findBySha1s( array $hashes ) { 00275 if ( !$this->reposInitialised ) { 00276 $this->initialiseRepos(); 00277 } 00278 00279 $result = $this->localRepo->findBySha1s( $hashes ); 00280 foreach ( $this->foreignRepos as $repo ) { 00281 $result = array_merge_recursive( $result, $repo->findBySha1s( $hashes ) ); 00282 } 00283 //sort the merged (and presorted) sublist of each hash 00284 foreach ( $result as $hash => $files ) { 00285 usort( $result[$hash], 'File::compare' ); 00286 } 00287 return $result; 00288 } 00289 00295 function getRepo( $index ) { 00296 if ( !$this->reposInitialised ) { 00297 $this->initialiseRepos(); 00298 } 00299 if ( $index === 'local' ) { 00300 return $this->localRepo; 00301 } elseif ( isset( $this->foreignRepos[$index] ) ) { 00302 return $this->foreignRepos[$index]; 00303 } else { 00304 return false; 00305 } 00306 } 00307 00313 function getRepoByName( $name ) { 00314 if ( !$this->reposInitialised ) { 00315 $this->initialiseRepos(); 00316 } 00317 foreach ( $this->foreignRepos as $repo ) { 00318 if ( $repo->name == $name ) { 00319 return $repo; 00320 } 00321 } 00322 return false; 00323 } 00324 00331 function getLocalRepo() { 00332 return $this->getRepo( 'local' ); 00333 } 00334 00343 function forEachForeignRepo( $callback, $params = array() ) { 00344 foreach ( $this->foreignRepos as $repo ) { 00345 $args = array_merge( array( $repo ), $params ); 00346 if ( call_user_func_array( $callback, $args ) ) { 00347 return true; 00348 } 00349 } 00350 return false; 00351 } 00352 00357 function hasForeignRepos() { 00358 return (bool)$this->foreignRepos; 00359 } 00360 00364 function initialiseRepos() { 00365 if ( $this->reposInitialised ) { 00366 return; 00367 } 00368 $this->reposInitialised = true; 00369 00370 $this->localRepo = $this->newRepo( $this->localInfo ); 00371 $this->foreignRepos = array(); 00372 foreach ( $this->foreignInfo as $key => $info ) { 00373 $this->foreignRepos[$key] = $this->newRepo( $info ); 00374 } 00375 } 00376 00380 protected function newRepo( $info ) { 00381 $class = $info['class']; 00382 return new $class( $info ); 00383 } 00384 00391 function splitVirtualUrl( $url ) { 00392 if ( substr( $url, 0, 9 ) != 'mwrepo://' ) { 00393 throw new MWException( __METHOD__ . ': unknown protocol' ); 00394 } 00395 00396 $bits = explode( '/', substr( $url, 9 ), 3 ); 00397 if ( count( $bits ) != 3 ) { 00398 throw new MWException( __METHOD__ . ": invalid mwrepo URL: $url" ); 00399 } 00400 return $bits; 00401 } 00402 00407 function getFileProps( $fileName ) { 00408 if ( FileRepo::isVirtualUrl( $fileName ) ) { 00409 list( $repoName, /* $zone */, /* $rel */ ) = $this->splitVirtualUrl( $fileName ); 00410 if ( $repoName === '' ) { 00411 $repoName = 'local'; 00412 } 00413 $repo = $this->getRepo( $repoName ); 00414 return $repo->getFileProps( $fileName ); 00415 } else { 00416 return FSFile::getPropsFromPath( $fileName ); 00417 } 00418 } 00419 00423 protected function pingCache( $key ) { 00424 if ( isset( $this->cache[$key] ) ) { 00425 $tmp = $this->cache[$key]; 00426 unset( $this->cache[$key] ); 00427 $this->cache[$key] = $tmp; 00428 } 00429 } 00430 00434 protected function trimCache() { 00435 while ( count( $this->cache ) >= self::MAX_CACHE_SIZE ) { 00436 reset( $this->cache ); 00437 $key = key( $this->cache ); 00438 wfDebug( __METHOD__ . ": evicting $key\n" ); 00439 unset( $this->cache[$key] ); 00440 } 00441 } 00442 00447 public function clearCache( Title $title = null ) { 00448 if ( $title == null ) { 00449 $this->cache = array(); 00450 } else { 00451 $dbKey = $title->getDBkey(); 00452 if ( isset( $this->cache[$dbKey] ) ) { 00453 unset( $this->cache[$dbKey] ); 00454 } 00455 } 00456 } 00457 }