MediaWiki
REL1_24
|
00001 <?php 00029 class RepoGroup { 00031 protected $localRepo; 00032 00034 protected $foreignRepos; 00035 00037 protected $reposInitialised = false; 00038 00040 protected $localInfo; 00041 00043 protected $foreignInfo; 00044 00046 protected $cache; 00047 00049 protected static $instance; 00050 00052 const MAX_CACHE_SIZE = 500; 00053 00059 static function singleton() { 00060 if ( self::$instance ) { 00061 return self::$instance; 00062 } 00063 global $wgLocalFileRepo, $wgForeignFileRepos; 00064 self::$instance = new RepoGroup( $wgLocalFileRepo, $wgForeignFileRepos ); 00065 00066 return self::$instance; 00067 } 00068 00073 static function destroySingleton() { 00074 self::$instance = null; 00075 } 00076 00085 static function setSingleton( $instance ) { 00086 self::$instance = $instance; 00087 } 00088 00098 function __construct( $localInfo, $foreignInfo ) { 00099 $this->localInfo = $localInfo; 00100 $this->foreignInfo = $foreignInfo; 00101 $this->cache = new ProcessCacheLRU( self::MAX_CACHE_SIZE ); 00102 } 00103 00120 function findFile( $title, $options = array() ) { 00121 if ( !is_array( $options ) ) { 00122 // MW 1.15 compat 00123 $options = array( 'time' => $options ); 00124 } 00125 if ( !$this->reposInitialised ) { 00126 $this->initialiseRepos(); 00127 } 00128 $title = File::normalizeTitle( $title ); 00129 if ( !$title ) { 00130 return false; 00131 } 00132 00133 # Check the cache 00134 if ( empty( $options['ignoreRedirect'] ) 00135 && empty( $options['private'] ) 00136 && empty( $options['bypassCache'] ) 00137 ) { 00138 $time = isset( $options['time'] ) ? $options['time'] : ''; 00139 $dbkey = $title->getDBkey(); 00140 if ( $this->cache->has( $dbkey, $time, 60 ) ) { 00141 return $this->cache->get( $dbkey, $time ); 00142 } 00143 $useCache = true; 00144 } else { 00145 $useCache = false; 00146 } 00147 00148 # Check the local repo 00149 $image = $this->localRepo->findFile( $title, $options ); 00150 00151 # Check the foreign repos 00152 if ( !$image ) { 00153 foreach ( $this->foreignRepos as $repo ) { 00154 $image = $repo->findFile( $title, $options ); 00155 if ( $image ) { 00156 break; 00157 } 00158 } 00159 } 00160 00161 $image = $image ? $image : false; // type sanity 00162 # Cache file existence or non-existence 00163 if ( $useCache && ( !$image || $image->isCacheable() ) ) { 00164 $this->cache->set( $dbkey, $time, $image ); 00165 } 00166 00167 return $image; 00168 } 00169 00187 function findFiles( array $inputItems, $flags = 0 ) { 00188 if ( !$this->reposInitialised ) { 00189 $this->initialiseRepos(); 00190 } 00191 00192 $items = array(); 00193 foreach ( $inputItems as $item ) { 00194 if ( !is_array( $item ) ) { 00195 $item = array( 'title' => $item ); 00196 } 00197 $item['title'] = File::normalizeTitle( $item['title'] ); 00198 if ( $item['title'] ) { 00199 $items[$item['title']->getDBkey()] = $item; 00200 } 00201 } 00202 00203 $images = $this->localRepo->findFiles( $items, $flags ); 00204 00205 foreach ( $this->foreignRepos as $repo ) { 00206 // Remove found files from $items 00207 foreach ( $images as $name => $image ) { 00208 unset( $items[$name] ); 00209 } 00210 00211 $images = array_merge( $images, $repo->findFiles( $items, $flags ) ); 00212 } 00213 00214 return $images; 00215 } 00216 00222 function checkRedirect( Title $title ) { 00223 if ( !$this->reposInitialised ) { 00224 $this->initialiseRepos(); 00225 } 00226 00227 $redir = $this->localRepo->checkRedirect( $title ); 00228 if ( $redir ) { 00229 return $redir; 00230 } 00231 00232 foreach ( $this->foreignRepos as $repo ) { 00233 $redir = $repo->checkRedirect( $title ); 00234 if ( $redir ) { 00235 return $redir; 00236 } 00237 } 00238 00239 return false; 00240 } 00241 00250 function findFileFromKey( $hash, $options = array() ) { 00251 if ( !$this->reposInitialised ) { 00252 $this->initialiseRepos(); 00253 } 00254 00255 $file = $this->localRepo->findFileFromKey( $hash, $options ); 00256 if ( !$file ) { 00257 foreach ( $this->foreignRepos as $repo ) { 00258 $file = $repo->findFileFromKey( $hash, $options ); 00259 if ( $file ) { 00260 break; 00261 } 00262 } 00263 } 00264 00265 return $file; 00266 } 00267 00274 function findBySha1( $hash ) { 00275 if ( !$this->reposInitialised ) { 00276 $this->initialiseRepos(); 00277 } 00278 00279 $result = $this->localRepo->findBySha1( $hash ); 00280 foreach ( $this->foreignRepos as $repo ) { 00281 $result = array_merge( $result, $repo->findBySha1( $hash ) ); 00282 } 00283 usort( $result, 'File::compare' ); 00284 00285 return $result; 00286 } 00287 00294 function findBySha1s( array $hashes ) { 00295 if ( !$this->reposInitialised ) { 00296 $this->initialiseRepos(); 00297 } 00298 00299 $result = $this->localRepo->findBySha1s( $hashes ); 00300 foreach ( $this->foreignRepos as $repo ) { 00301 $result = array_merge_recursive( $result, $repo->findBySha1s( $hashes ) ); 00302 } 00303 //sort the merged (and presorted) sublist of each hash 00304 foreach ( $result as $hash => $files ) { 00305 usort( $result[$hash], 'File::compare' ); 00306 } 00307 00308 return $result; 00309 } 00310 00316 function getRepo( $index ) { 00317 if ( !$this->reposInitialised ) { 00318 $this->initialiseRepos(); 00319 } 00320 if ( $index === 'local' ) { 00321 return $this->localRepo; 00322 } elseif ( isset( $this->foreignRepos[$index] ) ) { 00323 return $this->foreignRepos[$index]; 00324 } else { 00325 return false; 00326 } 00327 } 00328 00334 function getRepoByName( $name ) { 00335 if ( !$this->reposInitialised ) { 00336 $this->initialiseRepos(); 00337 } 00338 foreach ( $this->foreignRepos as $repo ) { 00339 if ( $repo->name == $name ) { 00340 return $repo; 00341 } 00342 } 00343 00344 return false; 00345 } 00346 00353 function getLocalRepo() { 00354 return $this->getRepo( 'local' ); 00355 } 00356 00365 function forEachForeignRepo( $callback, $params = array() ) { 00366 if ( !$this->reposInitialised ) { 00367 $this->initialiseRepos(); 00368 } 00369 foreach ( $this->foreignRepos as $repo ) { 00370 $args = array_merge( array( $repo ), $params ); 00371 if ( call_user_func_array( $callback, $args ) ) { 00372 return true; 00373 } 00374 } 00375 00376 return false; 00377 } 00378 00383 function hasForeignRepos() { 00384 if ( !$this->reposInitialised ) { 00385 $this->initialiseRepos(); 00386 } 00387 return (bool)$this->foreignRepos; 00388 } 00389 00393 function initialiseRepos() { 00394 if ( $this->reposInitialised ) { 00395 return; 00396 } 00397 $this->reposInitialised = true; 00398 00399 $this->localRepo = $this->newRepo( $this->localInfo ); 00400 $this->foreignRepos = array(); 00401 foreach ( $this->foreignInfo as $key => $info ) { 00402 $this->foreignRepos[$key] = $this->newRepo( $info ); 00403 } 00404 } 00405 00411 protected function newRepo( $info ) { 00412 $class = $info['class']; 00413 00414 return new $class( $info ); 00415 } 00416 00423 function splitVirtualUrl( $url ) { 00424 if ( substr( $url, 0, 9 ) != 'mwrepo://' ) { 00425 throw new MWException( __METHOD__ . ': unknown protocol' ); 00426 } 00427 00428 $bits = explode( '/', substr( $url, 9 ), 3 ); 00429 if ( count( $bits ) != 3 ) { 00430 throw new MWException( __METHOD__ . ": invalid mwrepo URL: $url" ); 00431 } 00432 00433 return $bits; 00434 } 00435 00440 function getFileProps( $fileName ) { 00441 if ( FileRepo::isVirtualUrl( $fileName ) ) { 00442 list( $repoName, /* $zone */, /* $rel */ ) = $this->splitVirtualUrl( $fileName ); 00443 if ( $repoName === '' ) { 00444 $repoName = 'local'; 00445 } 00446 $repo = $this->getRepo( $repoName ); 00447 00448 return $repo->getFileProps( $fileName ); 00449 } else { 00450 return FSFile::getPropsFromPath( $fileName ); 00451 } 00452 } 00453 00458 public function clearCache( Title $title = null ) { 00459 if ( $title == null ) { 00460 $this->cache->clear(); 00461 } else { 00462 $this->cache->clear( $title->getDBkey() ); 00463 } 00464 } 00465 }