9use InvalidArgumentException;
17use Wikimedia\Mime\MimeAnalyzer;
19use Wikimedia\Timestamp\TimestampFormat as TS;
56 private const MAX_CACHE_SIZE = 500;
59 private $mimeAnalyzer;
78 MimeAnalyzer $mimeAnalyzer
82 $this->cache =
new MapCacheLRU( self::MAX_CACHE_SIZE );
84 $this->mimeAnalyzer = $mimeAnalyzer;
105 public function findFile( $title, $options = [] ) {
106 if ( !is_array( $options ) ) {
108 $options = [
'time' => $options ];
110 if ( isset( $options[
'bypassCache'] ) ) {
111 $options[
'latest'] = $options[
'bypassCache'];
113 if ( isset( $options[
'time'] ) && $options[
'time'] !==
false ) {
114 $options[
'time'] =
wfTimestamp( TS::MW, $options[
'time'] );
116 $options[
'time'] =
false;
119 if ( !$this->reposInitialised ) {
123 $title = File::normalizeTitle( $title );
129 $dbkey = $title->getDBkey();
130 $timeKey = is_string( $options[
'time'] ) ? $options[
'time'] :
'';
131 if ( empty( $options[
'ignoreRedirect'] )
132 && empty( $options[
'private'] )
133 && empty( $options[
'latest'] )
135 if ( $this->cache->hasField( $dbkey, $timeKey, 60 ) ) {
136 return $this->cache->getField( $dbkey, $timeKey );
143 # Check the local repo
144 $image = $this->localRepo->findFile( $title, $options );
146 # Check the foreign repos
148 foreach ( $this->foreignRepos as $repo ) {
149 $image = $repo->findFile( $title, $options );
156 $image = $image instanceof
File ? $image :
false;
157 # Cache file existence or non-existence
158 if ( $useCache && ( !$image || $image->isCacheable() ) ) {
159 $this->cache->setField( $dbkey, $timeKey, $image );
182 public function findFiles( array $inputItems, $flags = 0 ) {
183 if ( !$this->reposInitialised ) {
188 foreach ( $inputItems as $item ) {
189 if ( !is_array( $item ) ) {
190 $item = [
'title' => $item ];
192 $item[
'title'] = File::normalizeTitle( $item[
'title'] );
193 if ( $item[
'title'] ) {
194 $items[$item[
'title']->getDBkey()] = $item;
198 $images = $this->localRepo->findFiles( $items, $flags );
200 foreach ( $this->foreignRepos as $repo ) {
202 $items = array_diff_key( $items, $images );
203 $images = array_merge( $images, $repo->findFiles( $items, $flags ) );
215 if ( !$this->reposInitialised ) {
219 $title = File::normalizeTitle( $title );
221 $redir = $this->localRepo->checkRedirect( $title );
226 foreach ( $this->foreignRepos as $repo ) {
227 $redir = $repo->checkRedirect( $title );
245 if ( !$this->reposInitialised ) {
249 $file = $this->localRepo->findFileFromKey( $hash, $options );
251 foreach ( $this->foreignRepos as $repo ) {
252 $file = $repo->findFileFromKey( $hash, $options );
269 if ( !$this->reposInitialised ) {
273 $result = $this->localRepo->findBySha1( $hash );
274 foreach ( $this->foreignRepos as $repo ) {
275 $result = array_merge( $result, $repo->findBySha1( $hash ) );
289 if ( !$this->reposInitialised ) {
293 $result = $this->localRepo->findBySha1s( $hashes );
294 foreach ( $this->foreignRepos as $repo ) {
295 $result = array_merge_recursive( $result, $repo->findBySha1s( $hashes ) );
298 foreach ( $result as $hash => $files ) {
311 if ( !$this->reposInitialised ) {
314 if ( $index ===
'local' ) {
317 return $this->foreignRepos[$index] ??
false;
326 if ( !$this->reposInitialised ) {
329 foreach ( $this->foreignRepos as $repo ) {
330 if ( $repo->name == $name ) {
346 return $this->
getRepo(
'local' );
358 if ( !$this->reposInitialised ) {
361 foreach ( $this->foreignRepos as $repo ) {
362 if ( $callback( $repo, ...$params ) ) {
375 if ( !$this->reposInitialised ) {
385 if ( $this->reposInitialised ) {
388 $this->reposInitialised =
true;
390 $this->localRepo = $this->
newRepo( $this->localInfo );
391 $this->foreignRepos = [];
392 foreach ( $this->foreignInfo as $key => $info ) {
393 $this->foreignRepos[$key] = $this->
newRepo( $info );
404 return $this->
newRepo( $info + $this->localInfo );
416 $class = $info[
'class'];
420 return new $class( $info );
428 private function splitVirtualUrl(
$url ) {
429 if ( !str_starts_with(
$url,
'mwrepo://' ) ) {
430 throw new InvalidArgumentException( __METHOD__ .
': unknown protocol' );
433 $bits = explode(
'/', substr(
$url, 9 ), 3 );
434 if ( count( $bits ) != 3 ) {
435 throw new InvalidArgumentException( __METHOD__ .
": invalid mwrepo URL: $url" );
447 [ $repoName, , ] = $this->splitVirtualUrl( $fileName );
448 if ( $repoName ===
'' ) {
451 $repo = $this->
getRepo( $repoName );
453 return $repo->getFileProps( $fileName );
457 return $mwProps->getPropsFromPath( $fileName,
true );
466 if ( $title ==
null ) {
467 $this->cache->clear();
468 } elseif ( is_string( $title ) ) {
469 $this->cache->clear( $title );
471 $this->cache->clear( $title->getDBkey() );
477class_alias( RepoGroup::class,
'RepoGroup' );
wfTimestamp( $outputtype=TS::UNIX, $ts=0)
Get a timestamp string in one of various formats.
MimeMagic helper wrapper.
Interface for objects (potentially) representing an editable wiki page.