MediaWiki REL1_39
RepoGroup.php
Go to the documentation of this file.
1<?php
23
29class RepoGroup {
31 protected $localRepo;
32
34 protected $foreignRepos;
35
37 protected $wanCache;
38
40 protected $reposInitialised = false;
41
43 protected $localInfo;
44
46 protected $foreignInfo;
47
49 protected $cache;
50
52 private const MAX_CACHE_SIZE = 500;
53
55 private $mimeAnalyzer;
56
69 public function __construct(
70 $localInfo,
71 $foreignInfo,
72 WANObjectCache $wanCache,
73 MimeAnalyzer $mimeAnalyzer
74 ) {
75 $this->localInfo = $localInfo;
76 $this->foreignInfo = $foreignInfo;
77 $this->cache = new MapCacheLRU( self::MAX_CACHE_SIZE );
78 $this->wanCache = $wanCache;
79 $this->mimeAnalyzer = $mimeAnalyzer;
80 }
81
100 public function findFile( $title, $options = [] ) {
101 if ( !is_array( $options ) ) {
102 // MW 1.15 compat
103 $options = [ 'time' => $options ];
104 }
105 if ( isset( $options['bypassCache'] ) ) {
106 $options['latest'] = $options['bypassCache']; // b/c
107 }
108 if ( isset( $options['time'] ) && $options['time'] !== false ) {
109 $options['time'] = wfTimestamp( TS_MW, $options['time'] );
110 } else {
111 $options['time'] = false;
112 }
113
114 if ( !$this->reposInitialised ) {
115 $this->initialiseRepos();
116 }
117
118 $title = File::normalizeTitle( $title );
119 if ( !$title ) {
120 return false;
121 }
122
123 # Check the cache
124 $dbkey = $title->getDBkey();
125 $timeKey = is_string( $options['time'] ) ? $options['time'] : '';
126 if ( empty( $options['ignoreRedirect'] )
127 && empty( $options['private'] )
128 && empty( $options['latest'] )
129 ) {
130 if ( $this->cache->hasField( $dbkey, $timeKey, 60 ) ) {
131 return $this->cache->getField( $dbkey, $timeKey );
132 }
133 $useCache = true;
134 } else {
135 $useCache = false;
136 }
137
138 # Check the local repo
139 $image = $this->localRepo->findFile( $title, $options );
140
141 # Check the foreign repos
142 if ( !$image ) {
143 foreach ( $this->foreignRepos as $repo ) {
144 $image = $repo->findFile( $title, $options );
145 if ( $image ) {
146 break;
147 }
148 }
149 }
150
151 $image = $image instanceof File ? $image : false; // type check
152 # Cache file existence or non-existence
153 if ( $useCache && ( !$image || $image->isCacheable() ) ) {
154 $this->cache->setField( $dbkey, $timeKey, $image );
155 }
156
157 return $image;
158 }
159
177 public function findFiles( array $inputItems, $flags = 0 ) {
178 if ( !$this->reposInitialised ) {
179 $this->initialiseRepos();
180 }
181
182 $items = [];
183 foreach ( $inputItems as $item ) {
184 if ( !is_array( $item ) ) {
185 $item = [ 'title' => $item ];
186 }
187 $item['title'] = File::normalizeTitle( $item['title'] );
188 if ( $item['title'] ) {
189 $items[$item['title']->getDBkey()] = $item;
190 }
191 }
192
193 $images = $this->localRepo->findFiles( $items, $flags );
194
195 foreach ( $this->foreignRepos as $repo ) {
196 // Remove found files from $items
197 foreach ( $images as $name => $image ) {
198 unset( $items[$name] );
199 }
200
201 $images = array_merge( $images, $repo->findFiles( $items, $flags ) );
202 }
203
204 return $images;
205 }
206
212 public function checkRedirect( $title ) {
213 if ( !$this->reposInitialised ) {
214 $this->initialiseRepos();
215 }
216
217 $title = File::normalizeTitle( $title );
218
219 $redir = $this->localRepo->checkRedirect( $title );
220 if ( $redir ) {
221 return $redir;
222 }
223
224 foreach ( $this->foreignRepos as $repo ) {
225 $redir = $repo->checkRedirect( $title );
226 if ( $redir ) {
227 return $redir;
228 }
229 }
230
231 return false;
232 }
233
242 public function findFileFromKey( $hash, $options = [] ) {
243 if ( !$this->reposInitialised ) {
244 $this->initialiseRepos();
245 }
246
247 $file = $this->localRepo->findFileFromKey( $hash, $options );
248 if ( !$file ) {
249 foreach ( $this->foreignRepos as $repo ) {
250 $file = $repo->findFileFromKey( $hash, $options );
251 if ( $file ) {
252 break;
253 }
254 }
255 }
256
257 return $file;
258 }
259
266 public function findBySha1( $hash ) {
267 if ( !$this->reposInitialised ) {
268 $this->initialiseRepos();
269 }
270
271 $result = $this->localRepo->findBySha1( $hash );
272 foreach ( $this->foreignRepos as $repo ) {
273 $result = array_merge( $result, $repo->findBySha1( $hash ) );
274 }
275 usort( $result, [ File::class, 'compare' ] );
276
277 return $result;
278 }
279
286 public function findBySha1s( array $hashes ) {
287 if ( !$this->reposInitialised ) {
288 $this->initialiseRepos();
289 }
290
291 $result = $this->localRepo->findBySha1s( $hashes );
292 foreach ( $this->foreignRepos as $repo ) {
293 $result = array_merge_recursive( $result, $repo->findBySha1s( $hashes ) );
294 }
295 // sort the merged (and presorted) sublist of each hash
296 foreach ( $result as $hash => $files ) {
297 usort( $result[$hash], [ File::class, 'compare' ] );
298 }
299
300 return $result;
301 }
302
308 public function getRepo( $index ) {
309 if ( !$this->reposInitialised ) {
310 $this->initialiseRepos();
311 }
312 if ( $index === 'local' ) {
313 return $this->localRepo;
314 }
315 return $this->foreignRepos[$index] ?? false;
316 }
317
323 public function getRepoByName( $name ) {
324 if ( !$this->reposInitialised ) {
325 $this->initialiseRepos();
326 }
327 foreach ( $this->foreignRepos as $repo ) {
328 if ( $repo->name == $name ) {
329 return $repo;
330 }
331 }
332
333 return false;
334 }
335
342 public function getLocalRepo() {
343 // @phan-suppress-next-line PhanTypeMismatchReturnSuperType
344 return $this->getRepo( 'local' );
345 }
346
355 public function forEachForeignRepo( $callback, $params = [] ) {
356 if ( !$this->reposInitialised ) {
357 $this->initialiseRepos();
358 }
359 foreach ( $this->foreignRepos as $repo ) {
360 if ( $callback( $repo, ...$params ) ) {
361 return true;
362 }
363 }
364
365 return false;
366 }
367
372 public function hasForeignRepos() {
373 if ( !$this->reposInitialised ) {
374 $this->initialiseRepos();
375 }
376 return (bool)$this->foreignRepos;
377 }
378
382 public function initialiseRepos() {
383 if ( $this->reposInitialised ) {
384 return;
385 }
386 $this->reposInitialised = true;
387
388 $this->localRepo = $this->newRepo( $this->localInfo );
389 $this->foreignRepos = [];
390 foreach ( $this->foreignInfo as $key => $info ) {
391 $this->foreignRepos[$key] = $this->newRepo( $info );
392 }
393 }
394
401 public function newCustomLocalRepo( $info = [] ) {
402 // @phan-suppress-next-line PhanTypeMismatchReturnSuperType
403 return $this->newRepo( $info + $this->localInfo );
404 }
405
411 protected function newRepo( $info ) {
412 $class = $info['class'];
413
414 $info['wanCache'] = $this->wanCache;
415
416 return new $class( $info );
417 }
418
425 private function splitVirtualUrl( $url ) {
426 if ( substr( $url, 0, 9 ) != 'mwrepo://' ) {
427 throw new MWException( __METHOD__ . ': unknown protocol' );
428 }
429
430 $bits = explode( '/', substr( $url, 9 ), 3 );
431 if ( count( $bits ) != 3 ) {
432 throw new MWException( __METHOD__ . ": invalid mwrepo URL: $url" );
433 }
434
435 return $bits;
436 }
437
442 public function getFileProps( $fileName ) {
443 if ( FileRepo::isVirtualUrl( $fileName ) ) {
444 list( $repoName, /* $zone */, /* $rel */ ) = $this->splitVirtualUrl( $fileName );
445 if ( $repoName === '' ) {
446 $repoName = 'local';
447 }
448 $repo = $this->getRepo( $repoName );
449
450 return $repo->getFileProps( $fileName );
451 } else {
452 $mwProps = new MWFileProps( $this->mimeAnalyzer );
453
454 return $mwProps->getPropsFromPath( $fileName, true );
455 }
456 }
457
462 public function clearCache( $title = null ) {
463 if ( $title == null ) {
464 $this->cache->clear();
465 } elseif ( is_string( $title ) ) {
466 $this->cache->clear( $title );
467 } else {
468 $this->cache->clear( $title->getDBkey() );
469 }
470 }
471}
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Base class for file repositories.
Definition FileRepo.php:47
static isVirtualUrl( $url)
Determine if a string is an mwrepo:// URL.
Definition FileRepo.php:285
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition File.php:67
Local repository that stores files in the local filesystem and registers them in the wiki's own datab...
Definition LocalRepo.php:39
MediaWiki exception.
MimeMagic helper wrapper.
Handles a simple LRU key/value map with a maximum number of entries.
Prioritized list of file repositories.
Definition RepoGroup.php:29
WANObjectCache $wanCache
Definition RepoGroup.php:37
newCustomLocalRepo( $info=[])
Create a local repo with the specified option overrides.
initialiseRepos()
Initialise the $repos array.
checkRedirect( $title)
Interface for FileRepo::checkRedirect()
getRepoByName( $name)
Get the repo instance by its name.
array $foreignInfo
Definition RepoGroup.php:46
__construct( $localInfo, $foreignInfo, WANObjectCache $wanCache, MimeAnalyzer $mimeAnalyzer)
Construct a group of file repositories.
Definition RepoGroup.php:69
hasForeignRepos()
Does the installation have any foreign repos set up?
findFileFromKey( $hash, $options=[])
Find an instance of the file with this key, created at the specified time Returns false if the file d...
bool $reposInitialised
Definition RepoGroup.php:40
MapCacheLRU $cache
Definition RepoGroup.php:49
findFile( $title, $options=[])
Search repositories for an image.
getLocalRepo()
Get the local repository, i.e.
FileRepo[] $foreignRepos
Definition RepoGroup.php:34
findBySha1s(array $hashes)
Find all instances of files with this keys.
clearCache( $title=null)
Clear RepoGroup process cache used for finding a file.
getRepo( $index)
Get the repo instance with a given key.
LocalRepo $localRepo
Definition RepoGroup.php:31
findBySha1( $hash)
Find all instances of files with this key.
findFiles(array $inputItems, $flags=0)
Search repositories for many files at once.
newRepo( $info)
Create a repo class based on an info structure.
array $localInfo
Definition RepoGroup.php:43
getFileProps( $fileName)
forEachForeignRepo( $callback, $params=[])
Call a function for each foreign repo, with the repo object as the first parameter.
Multi-datacenter aware caching interface.
Interface for objects (potentially) representing an editable wiki page.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition router.php:42