]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/filerepo/RepoGroup.php
MediaWiki 1.15.0
[autoinstalls/mediawiki.git] / includes / filerepo / RepoGroup.php
1 <?php
2 /**
3  * @defgroup FileRepo FileRepo
4  *
5  * @file
6  * @ingroup FileRepo
7  */
8
9 /**
10  * @ingroup FileRepo
11  * Prioritized list of file repositories
12  */
13 class RepoGroup {
14         var $localRepo, $foreignRepos, $reposInitialised = false;
15         var $localInfo, $foreignInfo;
16
17         protected static $instance;
18
19         /**
20          * Get a RepoGroup instance. At present only one instance of RepoGroup is
21          * needed in a MediaWiki invocation, this may change in the future.
22          */
23         static function singleton() {
24                 if ( self::$instance ) {
25                         return self::$instance;
26                 }
27                 global $wgLocalFileRepo, $wgForeignFileRepos;
28                 self::$instance = new RepoGroup( $wgLocalFileRepo, $wgForeignFileRepos );
29                 return self::$instance;
30         }
31
32         /**
33          * Destroy the singleton instance, so that a new one will be created next
34          * time singleton() is called.
35          */
36         static function destroySingleton() {
37                 self::$instance = null;
38         }
39
40         /**
41          * Set the singleton instance to a given object
42          */
43         static function setSingleton( $instance ) {
44                 self::$instance = $instance;
45         }
46
47         /**
48          * Construct a group of file repositories.
49          * @param array $data Array of repository info arrays.
50          *     Each info array is an associative array with the 'class' member
51          *     giving the class name. The entire array is passed to the repository
52          *     constructor as the first parameter.
53          */
54         function __construct( $localInfo, $foreignInfo ) {
55                 $this->localInfo = $localInfo;
56                 $this->foreignInfo = $foreignInfo;
57         }
58
59         /**
60          * Search repositories for an image.
61          * You can also use wfGetFile() to do this.
62          * @param mixed $title Title object or string
63          * @param mixed $time The 14-char timestamp the file should have
64          *                    been uploaded, or false for the current version
65          * @param mixed $flags FileRepo::FIND_ flags
66          * @return File object or false if it is not found
67          */
68         function findFile( $title, $time = false, $flags = 0 ) {
69                 if ( !$this->reposInitialised ) {
70                         $this->initialiseRepos();
71                 }
72
73                 $image = $this->localRepo->findFile( $title, $time, $flags );
74                 if ( $image ) {
75                         return $image;
76                 }
77                 foreach ( $this->foreignRepos as $repo ) {
78                         $image = $repo->findFile( $title, $time, $flags );
79                         if ( $image ) {
80                                 return $image;
81                         }
82                 }
83                 return false;
84         }
85         function findFiles( $titles ) {
86                 if ( !$this->reposInitialised ) {
87                         $this->initialiseRepos();
88                 }
89
90                 $titleObjs = array();
91                 foreach ( $titles as $title ) {
92                         if ( !( $title instanceof Title ) )
93                                 $title = Title::makeTitleSafe( NS_FILE, $title );
94                         if ( $title )
95                                 $titleObjs[$title->getDBkey()] = $title;
96                 }
97
98                 $images = $this->localRepo->findFiles( $titleObjs );
99
100                 foreach ( $this->foreignRepos as $repo ) {
101                         // Remove found files from $titleObjs
102                         foreach ( $images as $name => $image )
103                                 if ( isset( $titleObjs[$name] ) )
104                                         unset( $titleObjs[$name] );
105                         
106                         $images = array_merge( $images, $repo->findFiles( $titleObjs ) );
107                 }
108                 return $images;
109         }
110
111         /**
112          * Interface for FileRepo::checkRedirect()
113          */
114         function checkRedirect( $title ) {
115                 if ( !$this->reposInitialised ) {
116                         $this->initialiseRepos();
117                 }
118
119                 $redir = $this->localRepo->checkRedirect( $title );
120                 if( $redir ) {
121                         return $redir;
122                 }
123                 foreach ( $this->foreignRepos as $repo ) {
124                         $redir = $repo->checkRedirect( $title );
125                         if ( $redir ) {
126                                 return $redir;
127                         }
128                 }
129                 return false;
130         }
131         
132         function findBySha1( $hash ) {
133                 if ( !$this->reposInitialised ) {
134                         $this->initialiseRepos();
135                 }
136                 
137                 $result = $this->localRepo->findBySha1( $hash );
138                 foreach ( $this->foreignRepos as $repo )
139                         $result = array_merge( $result, $repo->findBySha1( $hash ) );
140                 return $result;         
141         }
142
143         /**
144          * Get the repo instance with a given key.
145          */
146         function getRepo( $index ) {
147                 if ( !$this->reposInitialised ) {
148                         $this->initialiseRepos();
149                 }
150                 if ( $index === 'local' ) {
151                         return $this->localRepo;
152                 } elseif ( isset( $this->foreignRepos[$index] ) ) {
153                         return $this->foreignRepos[$index];
154                 } else {
155                         return false;
156                 }
157         }
158         /**
159          * Get the repo instance by its name
160          */
161         function getRepoByName( $name ) {
162                 if ( !$this->reposInitialised ) {
163                         $this->initialiseRepos();
164                 }
165                 foreach ( $this->foreignRepos as $key => $repo ) {
166                         if ( $repo->name == $name)
167                                 return $repo;
168                 }
169                 return false;
170         }
171
172         /**
173          * Get the local repository, i.e. the one corresponding to the local image
174          * table. Files are typically uploaded to the local repository.
175          */
176         function getLocalRepo() {
177                 return $this->getRepo( 'local' );
178         }
179
180         /**
181          * Call a function for each foreign repo, with the repo object as the 
182          * first parameter.
183          *
184          * @param $callback callback The function to call
185          * @param $params array Optional additional parameters to pass to the function
186          */
187         function forEachForeignRepo( $callback, $params = array() ) {
188                 foreach( $this->foreignRepos as $repo ) {
189                         $args = array_merge( array( $repo ), $params );
190                         if( call_user_func_array( $callback, $args ) ) {
191                                 return true;
192                         }
193                 }
194                 return false;
195         }
196
197         /**
198          * Does the installation have any foreign repos set up?
199          * @return bool
200          */
201         function hasForeignRepos() {
202                 return (bool)$this->foreignRepos;
203         }
204
205         /**
206          * Initialise the $repos array
207          */
208         function initialiseRepos() {
209                 if ( $this->reposInitialised ) {
210                         return;
211                 }
212                 $this->reposInitialised = true;
213
214                 $this->localRepo = $this->newRepo( $this->localInfo );
215                 $this->foreignRepos = array();
216                 foreach ( $this->foreignInfo as $key => $info ) {
217                         $this->foreignRepos[$key] = $this->newRepo( $info );
218                 }
219         }
220
221         /**
222          * Create a repo class based on an info structure
223          */
224         protected function newRepo( $info ) {
225                 $class = $info['class'];
226                 return new $class( $info );
227         }
228
229         /**
230          * Split a virtual URL into repo, zone and rel parts
231          * @return an array containing repo, zone and rel
232          */
233         function splitVirtualUrl( $url ) {
234                 if ( substr( $url, 0, 9 ) != 'mwrepo://' ) {
235                         throw new MWException( __METHOD__.': unknown protoocl' );
236                 }
237
238                 $bits = explode( '/', substr( $url, 9 ), 3 );
239                 if ( count( $bits ) != 3 ) {
240                         throw new MWException( __METHOD__.": invalid mwrepo URL: $url" );
241                 }
242                 return $bits;
243         }
244
245         function getFileProps( $fileName ) {
246                 if ( FileRepo::isVirtualUrl( $fileName ) ) {
247                         list( $repoName, /* $zone */, /* $rel */ ) = $this->splitVirtualUrl( $fileName );
248                         if ( $repoName === '' ) {
249                                 $repoName = 'local';
250                         }
251                         $repo = $this->getRepo( $repoName );
252                         return $repo->getFileProps( $fileName );
253                 } else {
254                         return File::getPropsFromPath( $fileName );
255                 }
256         }
257 }