MediaWiki
REL1_19
|
00001 <?php 00014 class RepoGroup { 00015 00019 var $localRepo; 00020 00021 var $foreignRepos, $reposInitialised = false; 00022 var $localInfo, $foreignInfo; 00023 var $cache; 00024 00028 protected static $instance; 00029 const MAX_CACHE_SIZE = 1000; 00030 00036 static function singleton() { 00037 if ( self::$instance ) { 00038 return self::$instance; 00039 } 00040 global $wgLocalFileRepo, $wgForeignFileRepos; 00041 self::$instance = new RepoGroup( $wgLocalFileRepo, $wgForeignFileRepos ); 00042 return self::$instance; 00043 } 00044 00049 static function destroySingleton() { 00050 self::$instance = null; 00051 } 00052 00061 static function setSingleton( $instance ) { 00062 self::$instance = $instance; 00063 } 00064 00074 function __construct( $localInfo, $foreignInfo ) { 00075 $this->localInfo = $localInfo; 00076 $this->foreignInfo = $foreignInfo; 00077 $this->cache = array(); 00078 } 00079 00099 function findFile( $title, $options = array() ) { 00100 if ( !is_array( $options ) ) { 00101 // MW 1.15 compat 00102 $options = array( 'time' => $options ); 00103 } 00104 if ( !$this->reposInitialised ) { 00105 $this->initialiseRepos(); 00106 } 00107 $title = File::normalizeTitle( $title ); 00108 if ( !$title ) { 00109 return false; 00110 } 00111 00112 # Check the cache 00113 if ( empty( $options['ignoreRedirect'] ) 00114 && empty( $options['private'] ) 00115 && empty( $options['bypassCache'] ) ) 00116 { 00117 $useCache = true; 00118 $time = isset( $options['time'] ) ? $options['time'] : ''; 00119 $dbkey = $title->getDBkey(); 00120 if ( isset( $this->cache[$dbkey][$time] ) ) { 00121 wfDebug( __METHOD__.": got File:$dbkey from process cache\n" ); 00122 # Move it to the end of the list so that we can delete the LRU entry later 00123 $tmp = $this->cache[$dbkey]; 00124 unset( $this->cache[$dbkey] ); 00125 $this->cache[$dbkey] = $tmp; 00126 # Return the entry 00127 return $this->cache[$dbkey][$time]; 00128 } else { 00129 # Add a negative cache entry, may be overridden 00130 $this->trimCache(); 00131 $this->cache[$dbkey][$time] = false; 00132 $cacheEntry =& $this->cache[$dbkey][$time]; 00133 } 00134 } else { 00135 $useCache = false; 00136 } 00137 00138 # Check the local repo 00139 $image = $this->localRepo->findFile( $title, $options ); 00140 if ( $image ) { 00141 if ( $useCache ) { 00142 $cacheEntry = $image; 00143 } 00144 return $image; 00145 } 00146 00147 # Check the foreign repos 00148 foreach ( $this->foreignRepos as $repo ) { 00149 $image = $repo->findFile( $title, $options ); 00150 if ( $image ) { 00151 if ( $useCache ) { 00152 $cacheEntry = $image; 00153 } 00154 return $image; 00155 } 00156 } 00157 # Not found, do not override negative cache 00158 return false; 00159 } 00160 00161 function findFiles( $inputItems ) { 00162 if ( !$this->reposInitialised ) { 00163 $this->initialiseRepos(); 00164 } 00165 00166 $items = array(); 00167 foreach ( $inputItems as $item ) { 00168 if ( !is_array( $item ) ) { 00169 $item = array( 'title' => $item ); 00170 } 00171 $item['title'] = File::normalizeTitle( $item['title'] ); 00172 if ( $item['title'] ) { 00173 $items[$item['title']->getDBkey()] = $item; 00174 } 00175 } 00176 00177 $images = $this->localRepo->findFiles( $items ); 00178 00179 foreach ( $this->foreignRepos as $repo ) { 00180 // Remove found files from $items 00181 foreach ( $images as $name => $image ) { 00182 unset( $items[$name] ); 00183 } 00184 00185 $images = array_merge( $images, $repo->findFiles( $items ) ); 00186 } 00187 return $images; 00188 } 00189 00193 function checkRedirect( Title $title ) { 00194 if ( !$this->reposInitialised ) { 00195 $this->initialiseRepos(); 00196 } 00197 00198 $redir = $this->localRepo->checkRedirect( $title ); 00199 if( $redir ) { 00200 return $redir; 00201 } 00202 foreach ( $this->foreignRepos as $repo ) { 00203 $redir = $repo->checkRedirect( $title ); 00204 if ( $redir ) { 00205 return $redir; 00206 } 00207 } 00208 return false; 00209 } 00210 00219 function findFileFromKey( $hash, $options = array() ) { 00220 if ( !$this->reposInitialised ) { 00221 $this->initialiseRepos(); 00222 } 00223 00224 $file = $this->localRepo->findFileFromKey( $hash, $options ); 00225 if ( !$file ) { 00226 foreach ( $this->foreignRepos as $repo ) { 00227 $file = $repo->findFileFromKey( $hash, $options ); 00228 if ( $file ) break; 00229 } 00230 } 00231 return $file; 00232 } 00233 00240 function findBySha1( $hash ) { 00241 if ( !$this->reposInitialised ) { 00242 $this->initialiseRepos(); 00243 } 00244 00245 $result = $this->localRepo->findBySha1( $hash ); 00246 foreach ( $this->foreignRepos as $repo ) { 00247 $result = array_merge( $result, $repo->findBySha1( $hash ) ); 00248 } 00249 return $result; 00250 } 00251 00255 function getRepo( $index ) { 00256 if ( !$this->reposInitialised ) { 00257 $this->initialiseRepos(); 00258 } 00259 if ( $index === 'local' ) { 00260 return $this->localRepo; 00261 } elseif ( isset( $this->foreignRepos[$index] ) ) { 00262 return $this->foreignRepos[$index]; 00263 } else { 00264 return false; 00265 } 00266 } 00270 function getRepoByName( $name ) { 00271 if ( !$this->reposInitialised ) { 00272 $this->initialiseRepos(); 00273 } 00274 foreach ( $this->foreignRepos as $repo ) { 00275 if ( $repo->name == $name) 00276 return $repo; 00277 } 00278 return false; 00279 } 00280 00287 function getLocalRepo() { 00288 return $this->getRepo( 'local' ); 00289 } 00290 00298 function forEachForeignRepo( $callback, $params = array() ) { 00299 foreach( $this->foreignRepos as $repo ) { 00300 $args = array_merge( array( $repo ), $params ); 00301 if( call_user_func_array( $callback, $args ) ) { 00302 return true; 00303 } 00304 } 00305 return false; 00306 } 00307 00312 function hasForeignRepos() { 00313 return (bool)$this->foreignRepos; 00314 } 00315 00319 function initialiseRepos() { 00320 if ( $this->reposInitialised ) { 00321 return; 00322 } 00323 $this->reposInitialised = true; 00324 00325 $this->localRepo = $this->newRepo( $this->localInfo ); 00326 $this->foreignRepos = array(); 00327 foreach ( $this->foreignInfo as $key => $info ) { 00328 $this->foreignRepos[$key] = $this->newRepo( $info ); 00329 } 00330 } 00331 00335 protected function newRepo( $info ) { 00336 $class = $info['class']; 00337 return new $class( $info ); 00338 } 00339 00344 function splitVirtualUrl( $url ) { 00345 if ( substr( $url, 0, 9 ) != 'mwrepo://' ) { 00346 throw new MWException( __METHOD__.': unknown protocol' ); 00347 } 00348 00349 $bits = explode( '/', substr( $url, 9 ), 3 ); 00350 if ( count( $bits ) != 3 ) { 00351 throw new MWException( __METHOD__.": invalid mwrepo URL: $url" ); 00352 } 00353 return $bits; 00354 } 00355 00356 function getFileProps( $fileName ) { 00357 if ( FileRepo::isVirtualUrl( $fileName ) ) { 00358 list( $repoName, /* $zone */, /* $rel */ ) = $this->splitVirtualUrl( $fileName ); 00359 if ( $repoName === '' ) { 00360 $repoName = 'local'; 00361 } 00362 $repo = $this->getRepo( $repoName ); 00363 return $repo->getFileProps( $fileName ); 00364 } else { 00365 return FSFile::getPropsFromPath( $fileName ); 00366 } 00367 } 00368 00372 protected function trimCache() { 00373 while ( count( $this->cache ) >= self::MAX_CACHE_SIZE ) { 00374 reset( $this->cache ); 00375 $key = key( $this->cache ); 00376 wfDebug( __METHOD__.": evicting $key\n" ); 00377 unset( $this->cache[$key] ); 00378 } 00379 } 00380 00385 public function clearCache( Title $title = null ) { 00386 if ( $title == null ) { 00387 $this->cache = array(); 00388 } else { 00389 $dbKey = $title->getDBkey(); 00390 if ( isset( $this->cache[$dbKey] ) ) { 00391 unset( $this->cache[$dbKey] ); 00392 } 00393 } 00394 } 00395 }