MediaWiki master
ForeignAPIFile.php
Go to the documentation of this file.
1<?php
26
32class ForeignAPIFile extends File {
34 private $mExists;
36 private $mInfo;
37
38 protected $repoClass = ForeignAPIRepo::class;
39
46 public function __construct( $title, $repo, $info, $exists = false ) {
47 parent::__construct( $title, $repo );
48
49 $this->mInfo = $info;
50 $this->mExists = $exists;
51
52 $this->assertRepoDefined();
53 }
54
60 public static function newFromTitle( Title $title, $repo ) {
61 $data = $repo->fetchImageQuery( [
62 'titles' => 'File:' . $title->getDBkey(),
63 'iiprop' => self::getProps(),
64 'prop' => 'imageinfo',
65 'iimetadataversion' => MediaHandler::getMetadataVersion(),
66 // extmetadata is language-dependent, accessing the current language here
67 // would be problematic, so we just get them all
68 'iiextmetadatamultilang' => 1,
69 ] );
70
71 $info = $repo->getImageInfo( $data );
72
73 if ( $info ) {
74 $lastRedirect = count( $data['query']['redirects'] ?? [] ) - 1;
75 if ( $lastRedirect >= 0 ) {
76 // @phan-suppress-next-line PhanTypeArraySuspiciousNullable
77 $newtitle = Title::newFromText( $data['query']['redirects'][$lastRedirect]['to'] );
78 $img = new self( $newtitle, $repo, $info, true );
79 $img->redirectedFrom( $title->getDBkey() );
80 } else {
81 $img = new self( $title, $repo, $info, true );
82 }
83
84 return $img;
85 } else {
86 return null;
87 }
88 }
89
94 public static function getProps() {
95 return 'timestamp|user|comment|url|size|sha1|metadata|mime|mediatype|extmetadata';
96 }
97
101 public function getRepo() {
102 return $this->repo;
103 }
104
105 // Dummy functions...
106
110 public function exists() {
111 return $this->mExists;
112 }
113
117 public function getPath() {
118 return false;
119 }
120
126 public function transform( $params, $flags = 0 ) {
127 if ( !$this->canRender() ) {
128 // show icon
129 return parent::transform( $params, $flags );
130 }
131
132 // Note, the this->canRender() check above implies
133 // that we have a handler, and it can do makeParamString.
134 $otherParams = $this->handler->makeParamString( $params );
135 $width = $params['width'] ?? -1;
136 $height = $params['height'] ?? -1;
137 $thumbUrl = false;
138
139 if ( $width > 0 || $height > 0 ) {
140 // Only query the remote if there are dimensions
141 $thumbUrl = $this->repo->getThumbUrlFromCache(
142 $this->getName(),
143 $width,
144 $height,
145 $otherParams
146 );
147 } elseif ( $this->getMediaType() === MEDIATYPE_AUDIO ) {
148 // This has no dimensions, but we still need to pass a value to getTransform()
149 $thumbUrl = '/';
150 }
151 if ( $thumbUrl === false ) {
152 global $wgLang;
153
154 return $this->repo->getThumbError(
155 $this->getName(),
156 $width,
157 $height,
158 $otherParams,
159 $wgLang->getCode()
160 );
161 }
162
163 return $this->handler->getTransform( $this, 'bogus', $thumbUrl, $params );
164 }
165
166 // Info we can get from API...
167
172 public function getWidth( $page = 1 ) {
173 return (int)( $this->mInfo['width'] ?? 0 );
174 }
175
180 public function getHeight( $page = 1 ) {
181 return (int)( $this->mInfo['height'] ?? 0 );
182 }
183
187 public function getMetadata() {
188 if ( isset( $this->mInfo['metadata'] ) ) {
189 return serialize( self::parseMetadata( $this->mInfo['metadata'] ) );
190 }
191
192 return false;
193 }
194
198 public function getMetadataArray(): array {
199 if ( isset( $this->mInfo['metadata'] ) ) {
200 return self::parseMetadata( $this->mInfo['metadata'] );
201 }
202
203 return [];
204 }
205
210 public function getExtendedMetadata() {
211 return $this->mInfo['extmetadata'] ?? null;
212 }
213
218 public static function parseMetadata( $metadata ) {
219 if ( !is_array( $metadata ) ) {
220 return [ '_error' => $metadata ];
221 }
222 '@phan-var array[] $metadata';
223 $ret = [];
224 foreach ( $metadata as $meta ) {
225 $ret[$meta['name']] = self::parseMetadataValue( $meta['value'] );
226 }
227
228 return $ret;
229 }
230
235 private static function parseMetadataValue( $metadata ) {
236 if ( !is_array( $metadata ) ) {
237 return $metadata;
238 }
239 '@phan-var array[] $metadata';
240 $ret = [];
241 foreach ( $metadata as $meta ) {
242 $ret[$meta['name']] = self::parseMetadataValue( $meta['value'] );
243 }
244
245 return $ret;
246 }
247
251 public function getSize() {
252 return isset( $this->mInfo['size'] ) ? intval( $this->mInfo['size'] ) : null;
253 }
254
258 public function getUrl() {
259 return isset( $this->mInfo['url'] ) ? strval( $this->mInfo['url'] ) : null;
260 }
261
269 public function getDescriptionShortUrl() {
270 if ( isset( $this->mInfo['descriptionshorturl'] ) ) {
271 return $this->mInfo['descriptionshorturl'];
272 } elseif ( isset( $this->mInfo['pageid'] ) ) {
273 $url = $this->repo->makeUrl( [ 'curid' => $this->mInfo['pageid'] ] );
274 if ( $url !== false ) {
275 return $url;
276 }
277 }
278 return null;
279 }
280
281 public function getUploader( int $audience = self::FOR_PUBLIC, Authority $performer = null ): ?UserIdentity {
282 if ( isset( $this->mInfo['user'] ) ) {
283 // We don't know if the foreign repo will have a real interwiki prefix,
284 // treat this user as a foreign imported user. Maybe we can do better?
285 return UserIdentityValue::newExternal( $this->getRepoName(), $this->mInfo['user'] );
286 }
287 return null;
288 }
289
295 public function getDescription( $audience = self::FOR_PUBLIC, Authority $performer = null ) {
296 return isset( $this->mInfo['comment'] ) ? strval( $this->mInfo['comment'] ) : null;
297 }
298
302 public function getSha1() {
303 return isset( $this->mInfo['sha1'] )
304 ? Wikimedia\base_convert( strval( $this->mInfo['sha1'] ), 16, 36, 31 )
305 : null;
306 }
307
311 public function getTimestamp() {
312 return wfTimestamp( TS_MW,
313 isset( $this->mInfo['timestamp'] )
314 ? strval( $this->mInfo['timestamp'] )
315 : null
316 );
317 }
318
322 public function getMimeType() {
323 if ( !isset( $this->mInfo['mime'] ) ) {
324 $magic = MediaWikiServices::getInstance()->getMimeAnalyzer();
325 $this->mInfo['mime'] = $magic->getMimeTypeFromExtensionOrNull( $this->getExtension() );
326 }
327
328 return $this->mInfo['mime'];
329 }
330
334 public function getMediaType() {
335 if ( isset( $this->mInfo['mediatype'] ) ) {
336 return $this->mInfo['mediatype'];
337 }
338 $magic = MediaWikiServices::getInstance()->getMimeAnalyzer();
339
340 return $magic->getMediaType( null, $this->getMimeType() );
341 }
342
346 public function getDescriptionUrl() {
347 return $this->mInfo['descriptionurl'] ?? false;
348 }
349
355 public function getThumbPath( $suffix = '' ) {
356 if ( !$this->repo->canCacheThumbs() ) {
357 return null;
358 }
359
360 $path = $this->repo->getZonePath( 'thumb' ) . '/' . $this->getHashPath();
361 if ( $suffix ) {
362 $path .= $suffix . '/';
363 }
364 return $path;
365 }
366
370 protected function getThumbnails() {
371 $dir = $this->getThumbPath( $this->getName() );
372 $iter = $this->repo->getBackend()->getFileList( [ 'dir' => $dir ] );
373
374 $files = [];
375 if ( $iter ) {
376 foreach ( $iter as $file ) {
377 $files[] = $file;
378 }
379 }
380
381 return $files;
382 }
383
384 public function purgeCache( $options = [] ) {
385 $this->purgeThumbnails( $options );
386 $this->purgeDescriptionPage();
387 }
388
389 private function purgeDescriptionPage() {
390 $services = MediaWikiServices::getInstance();
391 $langCode = $services->getContentLanguage()->getCode();
392
393 // Key must match File::getDescriptionText
394 $key = $this->repo->getLocalCacheKey( 'file-remote-description', $langCode, md5( $this->getName() ) );
395 $services->getMainWANObjectCache()->delete( $key );
396 }
397
401 public function purgeThumbnails( $options = [] ) {
402 $key = $this->repo->getLocalCacheKey( 'file-thumb-url', sha1( $this->getName() ) );
403 MediaWikiServices::getInstance()->getMainWANObjectCache()->delete( $key );
404
405 $files = $this->getThumbnails();
406 // Give media handler a chance to filter the purge list
407 $handler = $this->getHandler();
408 if ( $handler ) {
409 $handler->filterThumbnailPurgeList( $files, $options );
410 }
411
412 $dir = $this->getThumbPath( $this->getName() );
413 $purgeList = [];
414 foreach ( $files as $file ) {
415 $purgeList[] = "{$dir}{$file}";
416 }
417
418 # Delete the thumbnails
419 $this->repo->quickPurgeBatch( $purgeList );
420 # Clear out the thumbnail directory if empty
421 $this->repo->quickCleanDir( $dir );
422 }
423
429 public function isTransformedLocally() {
430 return false;
431 }
432}
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
if(!defined( 'MW_NO_SESSION') &&MW_ENTRY_POINT !=='cli') $wgLang
Definition Setup.php:536
array $params
The job parameters.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:81
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition File.php:73
assertRepoDefined()
Assert that $this->repo is set to a valid FileRepo instance.
Definition File.php:2466
getName()
Return the name of this file.
Definition File.php:341
FileRepo LocalRepo ForeignAPIRepo false $repo
Some member variables can be lazy-initialised using __get().
Definition File.php:120
canRender()
Checks if the output of transform() for this file is likely to be valid.
Definition File.php:869
Title string false $title
Definition File.php:123
Foreign file accessible through api.php requests.
getThumbPath( $suffix='')
Only useful if we're locally caching thumbs anyway...
getDescription( $audience=self::FOR_PUBLIC, Authority $performer=null)
__construct( $title, $repo, $info, $exists=false)
getUploader(int $audience=self::FOR_PUBLIC, Authority $performer=null)
Get the identity of the file uploader.
purgeCache( $options=[])
Purge shared caches such as thumbnails and DB data caching STUB Overridden by LocalFile.
isTransformedLocally()
The thumbnail is created on the foreign server and fetched over internet.
static parseMetadata( $metadata)
static newFromTitle(Title $title, $repo)
purgeThumbnails( $options=[])
transform( $params, $flags=0)
getDescriptionShortUrl()
Get short description URL for a file based on the foreign API response, or if unavailable,...
static getProps()
Get the property string for iiprop and aiprop.
Service locator for MediaWiki core services.
Represents a title within MediaWiki.
Definition Title.php:78
getDBkey()
Get the main part with underscores.
Definition Title.php:1035
Value object representing a user's identity.
This interface represents the authority associated with the current execution context,...
Definition Authority.php:37
Interface for objects representing user identity.
const MEDIATYPE_AUDIO
Definition defines.php:33