MediaWiki  REL1_24
RepoGroup.php
Go to the documentation of this file.
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 }