MediaWiki master
ForeignAPIFile.php
Go to the documentation of this file.
1<?php
8
17use Wikimedia\Timestamp\TimestampFormat as TS;
18
24class ForeignAPIFile extends File {
26 private $mExists;
28 private $mInfo;
29
31 protected $repoClass = ForeignAPIRepo::class;
32
39 public function __construct( $title, $repo, $info, $exists = false ) {
40 parent::__construct( $title, $repo );
41
42 $this->mInfo = $info;
43 $this->mExists = $exists;
44
45 $this->assertRepoDefined();
46 }
47
53 public static function newFromTitle( Title $title, $repo ) {
54 $data = $repo->fetchImageQuery( [
55 'titles' => 'File:' . $title->getDBkey(),
56 'iiprop' => self::getProps(),
57 'prop' => 'imageinfo',
58 'iimetadataversion' => MediaHandler::getMetadataVersion(),
59 // extmetadata is language-dependent, accessing the current language here
60 // would be problematic, so we just get them all
61 'iiextmetadatamultilang' => 1,
62 ] );
63
64 $info = $repo->getImageInfo( $data );
65
66 if ( $info ) {
67 $lastRedirect = count( $data['query']['redirects'] ?? [] ) - 1;
68 if ( $lastRedirect >= 0 ) {
69 // @phan-suppress-next-line PhanTypeArraySuspiciousNullable
70 $newtitle = Title::newFromText( $data['query']['redirects'][$lastRedirect]['to'] );
71 $img = new self( $newtitle, $repo, $info, true );
72 $img->redirectedFrom( $title->getDBkey() );
73 } else {
74 $img = new self( $title, $repo, $info, true );
75 }
76
77 return $img;
78 } else {
79 return null;
80 }
81 }
82
87 public static function getProps() {
88 return 'timestamp|user|comment|url|size|sha1|metadata|mime|mediatype|extmetadata';
89 }
90
94 public function getRepo() {
95 return $this->repo;
96 }
97
98 // Dummy functions...
99
103 public function exists() {
104 return $this->mExists;
105 }
106
110 public function getPath() {
111 return false;
112 }
113
119 public function transform( $params, $flags = 0 ) {
120 if ( !$this->canRender() ) {
121 // show icon
122 return parent::transform( $params, $flags );
123 }
124
125 // Note, the this->canRender() check above implies
126 // that we have a handler, and it can do makeParamString.
127 $otherParams = $this->handler->makeParamString( $params );
128 $width = $params['width'] ?? -1;
129 $height = $params['height'] ?? -1;
130 $thumbUrl = false;
131
132 if ( $width > 0 || $height > 0 ) {
133 // Only query the remote if there are dimensions
134 $thumbUrl = $this->repo->getThumbUrlFromCache(
135 $this->getName(),
136 $width,
137 $height,
138 $otherParams
139 );
140 } elseif ( $this->getMediaType() === MEDIATYPE_AUDIO ) {
141 // This has no dimensions, but we still need to pass a value to getTransform()
142 $thumbUrl = '/';
143 }
144 if ( $thumbUrl === false ) {
145 global $wgLang;
146
147 return $this->repo->getThumbError(
148 $this->getName(),
149 $width,
150 $height,
151 $otherParams,
152 $wgLang->getCode()
153 );
154 }
155
156 return $this->handler->getTransform( $this, 'bogus', $thumbUrl, $params );
157 }
158
159 // Info we can get from API...
160
165 public function getWidth( $page = 1 ) {
166 return (int)( $this->mInfo['width'] ?? 0 );
167 }
168
173 public function getHeight( $page = 1 ) {
174 return (int)( $this->mInfo['height'] ?? 0 );
175 }
176
180 public function getMetadata() {
181 if ( isset( $this->mInfo['metadata'] ) ) {
182 return serialize( self::parseMetadata( $this->mInfo['metadata'] ) );
183 }
184
185 return false;
186 }
187
188 public function getMetadataArray(): array {
189 if ( isset( $this->mInfo['metadata'] ) ) {
190 return self::parseMetadata( $this->mInfo['metadata'] );
191 }
192
193 return [];
194 }
195
200 public function getExtendedMetadata() {
201 return $this->mInfo['extmetadata'] ?? null;
202 }
203
208 public static function parseMetadata( $metadata ) {
209 if ( !is_array( $metadata ) ) {
210 return [ '_error' => $metadata ];
211 }
212 '@phan-var array[] $metadata';
213 $ret = [];
214 foreach ( $metadata as $meta ) {
215 $ret[$meta['name']] = self::parseMetadataValue( $meta['value'] );
216 }
217
218 return $ret;
219 }
220
225 private static function parseMetadataValue( $metadata ) {
226 if ( !is_array( $metadata ) ) {
227 return $metadata;
228 }
229 '@phan-var array[] $metadata';
230 $ret = [];
231 foreach ( $metadata as $meta ) {
232 $ret[$meta['name']] = self::parseMetadataValue( $meta['value'] );
233 }
234
235 return $ret;
236 }
237
241 public function getSize() {
242 return isset( $this->mInfo['size'] ) ? intval( $this->mInfo['size'] ) : null;
243 }
244
248 public function getUrl() {
249 return isset( $this->mInfo['url'] ) ? strval( $this->mInfo['url'] ) : null;
250 }
251
259 public function getDescriptionShortUrl() {
260 if ( isset( $this->mInfo['descriptionshorturl'] ) ) {
261 return $this->mInfo['descriptionshorturl'];
262 } elseif ( isset( $this->mInfo['pageid'] ) ) {
263 $url = $this->repo->makeUrl( [ 'curid' => $this->mInfo['pageid'] ] );
264 if ( $url !== false ) {
265 return $url;
266 }
267 }
268 return null;
269 }
270
271 public function getUploader( int $audience = self::FOR_PUBLIC, ?Authority $performer = null ): ?UserIdentity {
272 if ( isset( $this->mInfo['user'] ) ) {
273 return UserIdentityValue::newExternal( $this->getRepoName(), $this->mInfo['user'] );
274 }
275 return null;
276 }
277
283 public function getDescription( $audience = self::FOR_PUBLIC, ?Authority $performer = null ) {
284 return isset( $this->mInfo['comment'] ) ? strval( $this->mInfo['comment'] ) : null;
285 }
286
290 public function getSha1() {
291 return isset( $this->mInfo['sha1'] )
292 ? \Wikimedia\base_convert( strval( $this->mInfo['sha1'] ), 16, 36, 31 )
293 : null;
294 }
295
299 public function getTimestamp() {
300 return wfTimestamp( TS::MW,
301 isset( $this->mInfo['timestamp'] )
302 ? strval( $this->mInfo['timestamp'] )
303 : null
304 );
305 }
306
310 public function getMimeType() {
311 if ( !isset( $this->mInfo['mime'] ) ) {
312 $magic = MediaWikiServices::getInstance()->getMimeAnalyzer();
313 $this->mInfo['mime'] = $magic->getMimeTypeFromExtensionOrNull( $this->getExtension() ) ?? 'unknown/unknown';
314 }
315
316 return $this->mInfo['mime'];
317 }
318
322 public function getMediaType() {
323 if ( isset( $this->mInfo['mediatype'] ) ) {
324 return $this->mInfo['mediatype'];
325 }
326 $magic = MediaWikiServices::getInstance()->getMimeAnalyzer();
327
328 return $magic->getMediaType( null, $this->getMimeType() );
329 }
330
334 public function getDescriptionUrl() {
335 return $this->mInfo['descriptionurl'] ?? false;
336 }
337
343 public function getThumbPath( $suffix = '' ) {
344 if ( !$this->repo->canCacheThumbs() ) {
345 return null;
346 }
347
348 $path = $this->repo->getZonePath( 'thumb' ) . '/' . $this->getHashPath();
349 if ( $suffix ) {
350 $path .= $suffix . '/';
351 }
352 return $path;
353 }
354
358 protected function getThumbnails() {
359 $dir = $this->getThumbPath( $this->getName() );
360 $iter = $this->repo->getBackend()->getFileList( [ 'dir' => $dir ] );
361
362 $files = [];
363 if ( $iter ) {
364 foreach ( $iter as $file ) {
365 $files[] = $file;
366 }
367 }
368
369 return $files;
370 }
371
373 public function purgeCache( $options = [] ) {
374 $this->purgeThumbnails( $options );
375 $this->purgeDescriptionPage();
376 }
377
378 private function purgeDescriptionPage() {
379 $services = MediaWikiServices::getInstance();
380 $langCode = $services->getContentLanguageCode()->toString();
381
382 // Key must match File::getDescriptionText
383 $key = $this->repo->getLocalCacheKey( 'file-remote-description', $langCode, md5( $this->getName() ) );
384 $services->getMainWANObjectCache()->delete( $key );
385 }
386
390 public function purgeThumbnails( $options = [] ) {
391 $key = $this->repo->getLocalCacheKey( 'file-thumb-url', sha1( $this->getName() ) );
392 MediaWikiServices::getInstance()->getMainWANObjectCache()->delete( $key );
393
394 $files = $this->getThumbnails();
395 // Give media handler a chance to filter the purge list
396 $handler = $this->getHandler();
397 if ( $handler ) {
398 $handler->filterThumbnailPurgeList( $files, $options );
399 }
400
401 $dir = $this->getThumbPath( $this->getName() );
402 $purgeList = [];
403 foreach ( $files as $file ) {
404 $purgeList[] = "{$dir}{$file}";
405 }
406
407 # Delete the thumbnails
408 $this->repo->quickPurgeBatch( $purgeList );
409 # Clear out the thumbnail directory if empty
410 $this->repo->quickCleanDir( $dir );
411 }
412
418 public function isTransformedLocally() {
419 return false;
420 }
421}
422
424class_alias( ForeignAPIFile::class, 'ForeignAPIFile' );
wfTimestamp( $outputtype=TS::UNIX, $ts=0)
Get a timestamp string in one of various formats.
const MEDIATYPE_AUDIO
Definition defines.php:19
if(MW_ENTRY_POINT==='index') if(!defined( 'MW_NO_SESSION') &&MW_ENTRY_POINT !=='cli' $wgLang
Definition Setup.php:551
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:69
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition File.php:79
FileRepo LocalRepo ForeignAPIRepo false $repo
Some member variables can be lazy-initialised using __get().
Definition File.php:126
canRender()
Checks if the output of transform() for this file is likely to be valid.
Definition File.php:890
assertRepoDefined()
Assert that $this->repo is set to a valid FileRepo instance.
Definition File.php:2548
Title string false $title
Definition File.php:129
getName()
Return the name of this file.
Definition File.php:347
Foreign file accessible through api.php requests.
__construct( $title, $repo, $info, $exists=false)
getDescription( $audience=self::FOR_PUBLIC, ?Authority $performer=null)
isTransformedLocally()
The thumbnail is created on the foreign server and fetched over internet.
getDescriptionShortUrl()
Get short description URL for a file based on the foreign API response, or if unavailable,...
static newFromTitle(Title $title, $repo)
getThumbPath( $suffix='')
Only useful if we're locally caching thumbs anyway...
getMetadataArray()
Get the unserialized handler-specific metadata STUB.
purgeCache( $options=[])
Purge shared caches such as thumbnails and DB data caching STUB Overridden by LocalFile....
static getProps()
Get the property string for iiprop and aiprop.
getUploader(int $audience=self::FOR_PUBLIC, ?Authority $performer=null)
Get the identity of the file uploader.
A foreign repository for a remote MediaWiki accessible through api.php requests.
Service locator for MediaWiki core services.
Base media handler class.
Base class for the output of MediaHandler::doTransform() and File::transform().
Represents a title within MediaWiki.
Definition Title.php:69
getDBkey()
Get the main part with underscores.
Definition Title.php:1028
Value object representing a user's identity.
This interface represents the authority associated with the current execution context,...
Definition Authority.php:23
Interface for objects representing user identity.