Slight fix for r47781: remove useless if($index) conditional: $index is always set...
[lhc/web/wiklou.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 }