MediaWiki  master
File.php
Go to the documentation of this file.
1 <?php
9 use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
15 
38 // @phan-file-suppress PhanTypeMissingReturn false positives
67 abstract class File implements IDBAccessObject, MediaHandlerState {
68  use ProtectedHookAccessorTrait;
69 
70  // Bitfield values akin to the revision deletion constants
71  public const DELETED_FILE = 1;
72  public const DELETED_COMMENT = 2;
73  public const DELETED_USER = 4;
74  public const DELETED_RESTRICTED = 8;
75 
77  public const RENDER_NOW = 1;
82  public const RENDER_FORCE = 2;
83 
84  public const DELETE_SOURCE = 1;
85 
86  // Audience options for File::getDescription()
87  public const FOR_PUBLIC = 1;
88  public const FOR_THIS_USER = 2;
89  public const RAW = 3;
90 
91  // Options for File::thumbName()
92  public const THUMB_FULL_NAME = 1;
93 
114  public $repo;
115 
117  protected $title;
118 
120  protected $lastError;
121 
123  protected $redirected;
124 
126  protected $redirectedTitle;
127 
129  protected $fsFile;
130 
132  protected $handler;
133 
135  protected $url;
136 
138  protected $extension;
139 
141  protected $name;
142 
144  protected $path;
145 
147  protected $hashPath;
148 
152  protected $pageCount;
153 
155  protected $transformScript;
156 
158  protected $redirectTitle;
159 
161  protected $canRender;
162 
166  protected $isSafeFile;
167 
169  protected $repoClass = FileRepo::class;
170 
172  protected $tmpBucketedThumbCache = [];
173 
175  private $handlerState = [];
176 
188  public function __construct( $title, $repo ) {
189  // Some subclasses do not use $title, but set name/title some other way
190  if ( $title !== false ) {
191  $title = self::normalizeTitle( $title, 'exception' );
192  }
193  $this->title = $title;
194  $this->repo = $repo;
195  }
196 
206  public static function normalizeTitle( $title, $exception = false ) {
207  $ret = $title;
208 
209  if ( !$ret instanceof Title ) {
210  if ( $ret instanceof PageIdentity ) {
211  $ret = Title::castFromPageIdentity( $ret );
212  } elseif ( $ret instanceof LinkTarget ) {
213  $ret = Title::castFromLinkTarget( $ret );
214  }
215  }
216 
217  if ( $ret instanceof Title ) {
218  # Normalize NS_MEDIA -> NS_FILE
219  if ( $ret->getNamespace() === NS_MEDIA ) {
220  $ret = Title::makeTitleSafe( NS_FILE, $ret->getDBkey() );
221  # Double check the titles namespace
222  } elseif ( $ret->getNamespace() !== NS_FILE ) {
223  $ret = null;
224  }
225  } else {
226  # Convert strings to Title objects
227  $ret = Title::makeTitleSafe( NS_FILE, (string)$ret );
228  }
229  if ( !$ret && $exception !== false ) {
230  throw new MWException( "`$title` is not a valid file title." );
231  }
232 
233  return $ret;
234  }
235 
236  public function __get( $name ) {
237  $function = [ $this, 'get' . ucfirst( $name ) ];
238  if ( !is_callable( $function ) ) {
239  return null;
240  } else {
241  $this->$name = $function();
242 
243  return $this->$name;
244  }
245  }
246 
255  public static function normalizeExtension( $extension ) {
256  $lower = strtolower( $extension );
257  $squish = [
258  'htm' => 'html',
259  'jpeg' => 'jpg',
260  'mpeg' => 'mpg',
261  'tiff' => 'tif',
262  'ogv' => 'ogg' ];
263  if ( isset( $squish[$lower] ) ) {
264  return $squish[$lower];
265  } elseif ( preg_match( '/^[0-9a-z]+$/', $lower ) ) {
266  return $lower;
267  } else {
268  return '';
269  }
270  }
271 
280  public static function checkExtensionCompatibility( File $old, $new ) {
281  $oldMime = $old->getMimeType();
282  $n = strrpos( $new, '.' );
283  $newExt = self::normalizeExtension( $n ? substr( $new, $n + 1 ) : '' );
284  $mimeMagic = MediaWiki\MediaWikiServices::getInstance()->getMimeAnalyzer();
285 
286  return $mimeMagic->isMatchingExtension( $newExt, $oldMime );
287  }
288 
296  public function upgradeRow() {
297  }
298 
306  public static function splitMime( $mime ) {
307  if ( strpos( $mime, '/' ) !== false ) {
308  return explode( '/', $mime, 2 );
309  } else {
310  return [ $mime, 'unknown' ];
311  }
312  }
313 
321  public static function compare( File $a, File $b ) {
322  return strcmp( $a->getName(), $b->getName() );
323  }
324 
331  public function getName() {
332  if ( $this->name === null ) {
333  $this->assertRepoDefined();
334  $this->name = $this->repo->getNameFromTitle( $this->title );
335  }
336 
337  return $this->name;
338  }
339 
346  public function getExtension() {
347  if ( !isset( $this->extension ) ) {
348  $n = strrpos( $this->getName(), '.' );
349  $this->extension = self::normalizeExtension(
350  $n ? substr( $this->getName(), $n + 1 ) : '' );
351  }
352 
353  return $this->extension;
354  }
355 
361  public function getTitle() {
362  return $this->title;
363  }
364 
370  public function getOriginalTitle() {
371  if ( $this->redirected ) {
372  return $this->getRedirectedTitle();
373  }
374 
375  return $this->title;
376  }
377 
384  public function getUrl() {
385  if ( !isset( $this->url ) ) {
386  $this->assertRepoDefined();
387  $ext = $this->getExtension();
388  $this->url = $this->repo->getZoneUrl( 'public', $ext ) . '/' . $this->getUrlRel();
389  }
390 
391  return $this->url;
392  }
393 
401  public function getDescriptionShortUrl() {
402  return null;
403  }
404 
413  public function getFullUrl() {
414  return wfExpandUrl( $this->getUrl(), PROTO_RELATIVE );
415  }
416 
421  public function getCanonicalUrl() {
422  return wfExpandUrl( $this->getUrl(), PROTO_CANONICAL );
423  }
424 
428  public function getViewURL() {
429  if ( $this->mustRender() ) {
430  if ( $this->canRender() ) {
431  return $this->createThumb( $this->getWidth() );
432  } else {
433  wfDebug( __METHOD__ . ': supposed to render ' . $this->getName() .
434  ' (' . $this->getMimeType() . "), but can't!" );
435 
436  return $this->getUrl(); # hm... return NULL?
437  }
438  } else {
439  return $this->getUrl();
440  }
441  }
442 
457  public function getPath() {
458  if ( !isset( $this->path ) ) {
459  $this->assertRepoDefined();
460  $this->path = $this->repo->getZonePath( 'public' ) . '/' . $this->getRel();
461  }
462 
463  return $this->path;
464  }
465 
473  public function getLocalRefPath() {
474  $this->assertRepoDefined();
475  if ( !isset( $this->fsFile ) ) {
476  $starttime = microtime( true );
477  $this->fsFile = $this->repo->getLocalReference( $this->getPath() );
478 
479  $statTiming = microtime( true ) - $starttime;
480  MediaWikiServices::getInstance()->getStatsdDataFactory()->timing(
481  'media.thumbnail.generate.fetchoriginal', 1000 * $statTiming );
482 
483  if ( !$this->fsFile ) {
484  $this->fsFile = false; // null => false; cache negative hits
485  }
486  }
487 
488  return ( $this->fsFile )
489  ? $this->fsFile->getPath()
490  : false;
491  }
492 
504  public function getWidth( $page = 1 ) {
505  return false;
506  }
507 
519  public function getHeight( $page = 1 ) {
520  return false;
521  }
522 
532  public function getThumbnailBucket( $desiredWidth, $page = 1 ) {
534 
535  $imageWidth = $this->getWidth( $page );
536 
537  if ( $imageWidth === false ) {
538  return false;
539  }
540 
541  if ( $desiredWidth > $imageWidth ) {
542  return false;
543  }
544 
545  if ( !$wgThumbnailBuckets ) {
546  return false;
547  }
548 
549  $sortedBuckets = $wgThumbnailBuckets;
550 
551  sort( $sortedBuckets );
552 
553  foreach ( $sortedBuckets as $bucket ) {
554  if ( $bucket >= $imageWidth ) {
555  return false;
556  }
557 
558  if ( $bucket - $wgThumbnailMinimumBucketDistance > $desiredWidth ) {
559  return $bucket;
560  }
561  }
562 
563  // Image is bigger than any available bucket
564  return false;
565  }
566 
577  public function getDisplayWidthHeight( $maxWidth, $maxHeight, $page = 1 ) {
578  if ( !$maxWidth || !$maxHeight ) {
579  // should never happen
580  throw new MWException( 'Using a choice from $wgImageLimits that is 0x0' );
581  }
582 
583  $width = $this->getWidth( $page );
584  $height = $this->getHeight( $page );
585  if ( !$width || !$height ) {
586  return [ 0, 0 ];
587  }
588 
589  // Calculate the thumbnail size.
590  if ( $width <= $maxWidth && $height <= $maxHeight ) {
591  // Vectorized image, do nothing.
592  } elseif ( $width / $height >= $maxWidth / $maxHeight ) {
593  # The limiting factor is the width, not the height.
594  $height = round( $height * $maxWidth / $width );
595  $width = $maxWidth;
596  // Note that $height <= $maxHeight now.
597  } else {
598  $newwidth = floor( $width * $maxHeight / $height );
599  $height = round( $height * $newwidth / $width );
600  $width = $newwidth;
601  // Note that $height <= $maxHeight now, but might not be identical
602  // because of rounding.
603  }
604  return [ $width, $height ];
605  }
606 
613  public function getLength() {
614  $handler = $this->getHandler();
615  if ( $handler ) {
616  return $handler->getLength( $this );
617  } else {
618  return 0;
619  }
620  }
621 
627  public function isVectorized() {
628  $handler = $this->getHandler();
629  if ( $handler ) {
630  return $handler->isVectorized( $this );
631  } else {
632  return false;
633  }
634  }
635 
647  public function getAvailableLanguages() {
648  $handler = $this->getHandler();
649  if ( $handler ) {
650  return $handler->getAvailableLanguages( $this );
651  } else {
652  return [];
653  }
654  }
655 
663  public function getMatchedLanguage( $userPreferredLanguage ) {
664  $handler = $this->getHandler();
665  if ( $handler ) {
667  $userPreferredLanguage,
669  );
670  }
671 
672  return null;
673  }
674 
682  public function getDefaultRenderLanguage() {
683  $handler = $this->getHandler();
684  if ( $handler ) {
685  return $handler->getDefaultRenderLanguage( $this );
686  } else {
687  return null;
688  }
689  }
690 
701  public function canAnimateThumbIfAppropriate() {
702  $handler = $this->getHandler();
703  if ( !$handler ) {
704  // We cannot handle image whatsoever, thus
705  // one would not expect it to be animated
706  // so true.
707  return true;
708  }
709 
710  return !$this->allowInlineDisplay()
711  // Image is not animated, so one would
712  // not expect thumb to be
713  || !$handler->isAnimatedImage( $this )
714  // Image is animated, but thumbnail isn't.
715  // This is unexpected to the user.
716  || $handler->canAnimateThumbnail( $this );
717  }
718 
726  public function getMetadata() {
727  return false;
728  }
729 
730  public function getHandlerState( string $key ) {
731  return $this->handlerState[$key] ?? null;
732  }
733 
734  public function setHandlerState( string $key, $value ) {
735  $this->handlerState[$key] = $value;
736  }
737 
744  public function getMetadataArray(): array {
745  return [];
746  }
747 
755  public function getMetadataItem( string $itemName ) {
756  $items = $this->getMetadataItems( [ $itemName ] );
757  return $items[$itemName] ?? null;
758  }
759 
767  public function getMetadataItems( array $itemNames ): array {
768  return array_intersect_key(
769  $this->getMetadataArray(),
770  array_fill_keys( $itemNames, true ) );
771  }
772 
779  public function getCommonMetaArray() {
780  $handler = $this->getHandler();
781 
782  if ( !$handler ) {
783  return false;
784  }
785 
786  return $handler->getCommonMetaArray( $this );
787  }
788 
796  public function convertMetadataVersion( $metadata, $version ) {
797  $handler = $this->getHandler();
798  if ( $handler ) {
799  return $handler->convertMetadataVersion( $metadata, $version );
800  } else {
801  return $metadata;
802  }
803  }
804 
812  public function getBitDepth() {
813  return 0;
814  }
815 
823  public function getSize() {
824  return false;
825  }
826 
835  public function getMimeType() {
836  return 'unknown/unknown';
837  }
838 
847  public function getMediaType() {
848  return MEDIATYPE_UNKNOWN;
849  }
850 
863  public function canRender() {
864  if ( !isset( $this->canRender ) ) {
865  $this->canRender = $this->getHandler() && $this->handler->canRender( $this ) && $this->exists();
866  }
867 
868  return $this->canRender;
869  }
870 
875  protected function getCanRender() {
876  return $this->canRender();
877  }
878 
890  public function mustRender() {
891  return $this->getHandler() && $this->handler->mustRender( $this );
892  }
893 
899  public function allowInlineDisplay() {
900  return $this->canRender();
901  }
902 
916  public function isSafeFile() {
917  if ( !isset( $this->isSafeFile ) ) {
918  $this->isSafeFile = $this->getIsSafeFileUncached();
919  }
920 
921  return $this->isSafeFile;
922  }
923 
929  protected function getIsSafeFile() {
930  return $this->isSafeFile();
931  }
932 
938  protected function getIsSafeFileUncached() {
939  global $wgTrustedMediaFormats;
940 
941  if ( $this->allowInlineDisplay() ) {
942  return true;
943  }
944  if ( $this->isTrustedFile() ) {
945  return true;
946  }
947 
948  $type = $this->getMediaType();
949  $mime = $this->getMimeType();
950 
951  if ( !$type || $type === MEDIATYPE_UNKNOWN ) {
952  return false; # unknown type, not trusted
953  }
954  if ( in_array( $type, $wgTrustedMediaFormats ) ) {
955  return true;
956  }
957 
958  if ( $mime === "unknown/unknown" ) {
959  return false; # unknown type, not trusted
960  }
961  if ( in_array( $mime, $wgTrustedMediaFormats ) ) {
962  return true;
963  }
964 
965  return false;
966  }
967 
981  protected function isTrustedFile() {
982  # this could be implemented to check a flag in the database,
983  # look for signatures, etc
984  return false;
985  }
986 
997  public function load( $flags = 0 ) {
998  }
999 
1008  public function exists() {
1009  return $this->getPath() && $this->repo->fileExists( $this->path );
1010  }
1011 
1019  public function isVisible() {
1020  return $this->exists();
1021  }
1022 
1026  private function getTransformScript() {
1027  if ( !isset( $this->transformScript ) ) {
1028  $this->transformScript = false;
1029  if ( $this->repo ) {
1030  $script = $this->repo->getThumbScriptUrl();
1031  if ( $script ) {
1032  $this->transformScript = wfAppendQuery( $script, [ 'f' => $this->getName() ] );
1033  }
1034  }
1035  }
1036 
1037  return $this->transformScript;
1038  }
1039 
1047  public function getUnscaledThumb( $handlerParams = [] ) {
1048  $hp =& $handlerParams;
1049  $page = $hp['page'] ?? false;
1050  $width = $this->getWidth( $page );
1051  if ( !$width ) {
1052  return $this->iconThumb();
1053  }
1054  $hp['width'] = $width;
1055  // be sure to ignore any height specification as well (T64258)
1056  unset( $hp['height'] );
1057 
1058  return $this->transform( $hp );
1059  }
1060 
1071  public function thumbName( $params, $flags = 0 ) {
1072  $name = ( $this->repo && !( $flags & self::THUMB_FULL_NAME ) )
1073  ? $this->repo->nameForThumb( $this->getName() )
1074  : $this->getName();
1075 
1076  return $this->generateThumbName( $name, $params );
1077  }
1078 
1087  public function generateThumbName( $name, $params ) {
1088  if ( !$this->getHandler() ) {
1089  return null;
1090  }
1091  $extension = $this->getExtension();
1092  list( $thumbExt, ) = $this->getHandler()->getThumbType(
1093  $extension, $this->getMimeType(), $params );
1094  $thumbName = $this->getHandler()->makeParamString( $params );
1095 
1096  if ( $this->repo->supportsSha1URLs() ) {
1097  $thumbName .= '-' . $this->getSha1() . '.' . $thumbExt;
1098  } else {
1099  $thumbName .= '-' . $name;
1100 
1101  if ( $thumbExt != $extension ) {
1102  $thumbName .= ".$thumbExt";
1103  }
1104  }
1105 
1106  return $thumbName;
1107  }
1108 
1126  public function createThumb( $width, $height = -1 ) {
1127  $params = [ 'width' => $width ];
1128  if ( $height != -1 ) {
1129  $params['height'] = $height;
1130  }
1131  $thumb = $this->transform( $params );
1132  if ( !$thumb || $thumb->isError() ) {
1133  return '';
1134  }
1135 
1136  return $thumb->getUrl();
1137  }
1138 
1148  protected function transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags ) {
1149  global $wgIgnoreImageErrors;
1150 
1151  $handler = $this->getHandler();
1152  if ( $handler && $wgIgnoreImageErrors && !( $flags & self::RENDER_NOW ) ) {
1153  return $handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
1154  } else {
1155  return new MediaTransformError( 'thumbnail_error',
1156  $params['width'], 0, wfMessage( 'thumbnail-dest-create' ) );
1157  }
1158  }
1159 
1169  public function transform( $params, $flags = 0 ) {
1170  global $wgThumbnailEpoch;
1171 
1172  do {
1173  if ( !$this->canRender() ) {
1174  $thumb = $this->iconThumb();
1175  break; // not a bitmap or renderable image, don't try
1176  }
1177 
1178  // Get the descriptionUrl to embed it as comment into the thumbnail. T21791.
1179  $descriptionUrl = $this->getDescriptionUrl();
1180  if ( $descriptionUrl ) {
1181  $params['descriptionUrl'] = wfExpandUrl( $descriptionUrl, PROTO_CANONICAL );
1182  }
1183 
1184  $handler = $this->getHandler();
1185  $script = $this->getTransformScript();
1186  if ( $script && !( $flags & self::RENDER_NOW ) ) {
1187  // Use a script to transform on client request, if possible
1188  $thumb = $handler->getScriptedTransform( $this, $script, $params );
1189  if ( $thumb ) {
1190  break;
1191  }
1192  }
1193 
1194  $normalisedParams = $params;
1195  $handler->normaliseParams( $this, $normalisedParams );
1196 
1197  $thumbName = $this->thumbName( $normalisedParams );
1198  $thumbUrl = $this->getThumbUrl( $thumbName );
1199  $thumbPath = $this->getThumbPath( $thumbName ); // final thumb path
1200 
1201  if ( $this->repo ) {
1202  // Defer rendering if a 404 handler is set up...
1203  if ( $this->repo->canTransformVia404() && !( $flags & self::RENDER_NOW ) ) {
1204  // XXX: Pass in the storage path even though we are not rendering anything
1205  // and the path is supposed to be an FS path. This is due to getScalerType()
1206  // getting called on the path and clobbering $thumb->getUrl() if it's false.
1207  $thumb = $handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
1208  break;
1209  }
1210  // Check if an up-to-date thumbnail already exists...
1211  wfDebug( __METHOD__ . ": Doing stat for $thumbPath" );
1212  if ( !( $flags & self::RENDER_FORCE ) && $this->repo->fileExists( $thumbPath ) ) {
1213  $timestamp = $this->repo->getFileTimestamp( $thumbPath );
1214  if ( $timestamp !== false && $timestamp >= $wgThumbnailEpoch ) {
1215  // XXX: Pass in the storage path even though we are not rendering anything
1216  // and the path is supposed to be an FS path. This is due to getScalerType()
1217  // getting called on the path and clobbering $thumb->getUrl() if it's false.
1218  $thumb = $handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
1219  $thumb->setStoragePath( $thumbPath );
1220  break;
1221  }
1222  } elseif ( $flags & self::RENDER_FORCE ) {
1223  wfDebug( __METHOD__ . " forcing rendering per flag File::RENDER_FORCE" );
1224  }
1225 
1226  // If the backend is ready-only, don't keep generating thumbnails
1227  // only to return transformation errors, just return the error now.
1228  if ( $this->repo->getReadOnlyReason() !== false ) {
1229  $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags );
1230  break;
1231  }
1232 
1233  // Check to see if local transformation is disabled.
1234  if ( !$this->repo->canTransformLocally() ) {
1235  $thumb = new MediaTransformError(
1236  wfMessage(
1237  'thumbnail_error',
1238  'MediaWiki is configured to disallow local image scaling'
1239  ),
1240  $params['width'],
1241  0
1242  );
1243  break;
1244  }
1245  }
1246 
1247  $tmpFile = $this->makeTransformTmpFile( $thumbPath );
1248 
1249  if ( !$tmpFile ) {
1250  $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags );
1251  } else {
1252  $thumb = $this->generateAndSaveThumb( $tmpFile, $params, $flags );
1253  }
1254  } while ( false );
1255 
1256  return is_object( $thumb ) ? $thumb : false;
1257  }
1258 
1266  public function generateAndSaveThumb( $tmpFile, $transformParams, $flags ) {
1267  global $wgIgnoreImageErrors;
1268 
1269  if ( !$this->repo->canTransformLocally() ) {
1270  return new MediaTransformError(
1271  wfMessage(
1272  'thumbnail_error',
1273  'MediaWiki is configured to disallow local image scaling'
1274  ),
1275  $transformParams['width'],
1276  0
1277  );
1278  }
1279 
1280  $stats = MediaWikiServices::getInstance()->getStatsdDataFactory();
1281 
1282  $handler = $this->getHandler();
1283 
1284  $normalisedParams = $transformParams;
1285  $handler->normaliseParams( $this, $normalisedParams );
1286 
1287  $thumbName = $this->thumbName( $normalisedParams );
1288  $thumbUrl = $this->getThumbUrl( $thumbName );
1289  $thumbPath = $this->getThumbPath( $thumbName ); // final thumb path
1290 
1291  $tmpThumbPath = $tmpFile->getPath();
1292 
1293  if ( $handler->supportsBucketing() ) {
1294  $this->generateBucketsIfNeeded( $normalisedParams, $flags );
1295  }
1296 
1297  $starttime = microtime( true );
1298 
1299  // Actually render the thumbnail...
1300  $thumb = $handler->doTransform( $this, $tmpThumbPath, $thumbUrl, $transformParams );
1301  $tmpFile->bind( $thumb ); // keep alive with $thumb
1302 
1303  $statTiming = microtime( true ) - $starttime;
1304  $stats->timing( 'media.thumbnail.generate.transform', 1000 * $statTiming );
1305 
1306  if ( !$thumb ) { // bad params?
1307  $thumb = false;
1308  } elseif ( $thumb->isError() ) { // transform error
1310  '@phan-var MediaTransformError $thumb';
1311  $this->lastError = $thumb->toText();
1312  // Ignore errors if requested
1313  if ( $wgIgnoreImageErrors && !( $flags & self::RENDER_NOW ) ) {
1314  $thumb = $handler->getTransform( $this, $tmpThumbPath, $thumbUrl, $transformParams );
1315  }
1316  } elseif ( $this->repo && $thumb->hasFile() && !$thumb->fileIsSource() ) {
1317  // Copy the thumbnail from the file system into storage...
1318 
1319  $starttime = microtime( true );
1320 
1321  $disposition = $this->getThumbDisposition( $thumbName );
1322  $status = $this->repo->quickImport( $tmpThumbPath, $thumbPath, $disposition );
1323  if ( $status->isOK() ) {
1324  $thumb->setStoragePath( $thumbPath );
1325  } else {
1326  $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $transformParams, $flags );
1327  }
1328 
1329  $statTiming = microtime( true ) - $starttime;
1330  $stats->timing( 'media.thumbnail.generate.store', 1000 * $statTiming );
1331 
1332  // Give extensions a chance to do something with this thumbnail...
1333  $this->getHookRunner()->onFileTransformed( $this, $thumb, $tmpThumbPath, $thumbPath );
1334  }
1335 
1336  return $thumb;
1337  }
1338 
1345  protected function generateBucketsIfNeeded( $params, $flags = 0 ) {
1346  if ( !$this->repo
1347  || !isset( $params['physicalWidth'] )
1348  || !isset( $params['physicalHeight'] )
1349  ) {
1350  return false;
1351  }
1352 
1353  $bucket = $this->getThumbnailBucket( $params['physicalWidth'] );
1354 
1355  if ( !$bucket || $bucket == $params['physicalWidth'] ) {
1356  return false;
1357  }
1358 
1359  $bucketPath = $this->getBucketThumbPath( $bucket );
1360 
1361  if ( $this->repo->fileExists( $bucketPath ) ) {
1362  return false;
1363  }
1364 
1365  $starttime = microtime( true );
1366 
1367  $params['physicalWidth'] = $bucket;
1368  $params['width'] = $bucket;
1369 
1370  $params = $this->getHandler()->sanitizeParamsForBucketing( $params );
1371 
1372  $tmpFile = $this->makeTransformTmpFile( $bucketPath );
1373 
1374  if ( !$tmpFile ) {
1375  return false;
1376  }
1377 
1378  $thumb = $this->generateAndSaveThumb( $tmpFile, $params, $flags );
1379 
1380  $buckettime = microtime( true ) - $starttime;
1381 
1382  if ( !$thumb || $thumb->isError() ) {
1383  return false;
1384  }
1385 
1386  $this->tmpBucketedThumbCache[$bucket] = $tmpFile->getPath();
1387  // For the caching to work, we need to make the tmp file survive as long as
1388  // this object exists
1389  $tmpFile->bind( $this );
1390 
1391  MediaWikiServices::getInstance()->getStatsdDataFactory()->timing(
1392  'media.thumbnail.generate.bucket', 1000 * $buckettime );
1393 
1394  return true;
1395  }
1396 
1402  public function getThumbnailSource( $params ) {
1403  if ( $this->repo
1404  && $this->getHandler()->supportsBucketing()
1405  && isset( $params['physicalWidth'] )
1406  && $bucket = $this->getThumbnailBucket( $params['physicalWidth'] )
1407  ) {
1408  if ( $this->getWidth() != 0 ) {
1409  $bucketHeight = round( $this->getHeight() * ( $bucket / $this->getWidth() ) );
1410  } else {
1411  $bucketHeight = 0;
1412  }
1413 
1414  // Try to avoid reading from storage if the file was generated by this script
1415  if ( isset( $this->tmpBucketedThumbCache[$bucket] ) ) {
1416  $tmpPath = $this->tmpBucketedThumbCache[$bucket];
1417 
1418  if ( file_exists( $tmpPath ) ) {
1419  return [
1420  'path' => $tmpPath,
1421  'width' => $bucket,
1422  'height' => $bucketHeight
1423  ];
1424  }
1425  }
1426 
1427  $bucketPath = $this->getBucketThumbPath( $bucket );
1428 
1429  if ( $this->repo->fileExists( $bucketPath ) ) {
1430  $fsFile = $this->repo->getLocalReference( $bucketPath );
1431 
1432  if ( $fsFile ) {
1433  return [
1434  'path' => $fsFile->getPath(),
1435  'width' => $bucket,
1436  'height' => $bucketHeight
1437  ];
1438  }
1439  }
1440  }
1441 
1442  // Thumbnailing a very large file could result in network saturation if
1443  // everyone does it at once.
1444  if ( $this->getSize() >= 1e7 ) { // 10 MB
1445  $work = new PoolCounterWorkViaCallback( 'GetLocalFileCopy', sha1( $this->getName() ),
1446  [
1447  'doWork' => function () {
1448  return $this->getLocalRefPath();
1449  }
1450  ]
1451  );
1452  $srcPath = $work->execute();
1453  } else {
1454  $srcPath = $this->getLocalRefPath();
1455  }
1456 
1457  // Original file
1458  return [
1459  'path' => $srcPath,
1460  'width' => $this->getWidth(),
1461  'height' => $this->getHeight()
1462  ];
1463  }
1464 
1470  protected function getBucketThumbPath( $bucket ) {
1471  $thumbName = $this->getBucketThumbName( $bucket );
1472  return $this->getThumbPath( $thumbName );
1473  }
1474 
1480  protected function getBucketThumbName( $bucket ) {
1481  return $this->thumbName( [ 'physicalWidth' => $bucket ] );
1482  }
1483 
1489  protected function makeTransformTmpFile( $thumbPath ) {
1490  $thumbExt = FileBackend::extensionFromPath( $thumbPath );
1491  return MediaWikiServices::getInstance()->getTempFSFileFactory()
1492  ->newTempFSFile( 'transform_', $thumbExt );
1493  }
1494 
1500  public function getThumbDisposition( $thumbName, $dispositionType = 'inline' ) {
1501  $fileName = $this->name; // file name to suggest
1502  $thumbExt = FileBackend::extensionFromPath( $thumbName );
1503  if ( $thumbExt != '' && $thumbExt !== $this->getExtension() ) {
1504  $fileName .= ".$thumbExt";
1505  }
1506 
1507  return FileBackend::makeContentDisposition( $dispositionType, $fileName );
1508  }
1509 
1516  protected function migrateThumbFile( $thumbName ) {
1517  }
1518 
1525  public function getHandler() {
1526  if ( !isset( $this->handler ) ) {
1527  $this->handler = MediaHandler::getHandler( $this->getMimeType() );
1528  }
1529 
1530  return $this->handler;
1531  }
1532 
1538  public function iconThumb() {
1539  global $wgResourceBasePath, $IP;
1540  $assetsPath = "$wgResourceBasePath/resources/assets/file-type-icons/";
1541  $assetsDirectory = "$IP/resources/assets/file-type-icons/";
1542 
1543  $try = [ 'fileicon-' . $this->getExtension() . '.png', 'fileicon.png' ];
1544  foreach ( $try as $icon ) {
1545  if ( file_exists( $assetsDirectory . $icon ) ) { // always FS
1546  $params = [ 'width' => 120, 'height' => 120 ];
1547 
1548  return new ThumbnailImage( $this, $assetsPath . $icon, false, $params );
1549  }
1550  }
1551 
1552  return null;
1553  }
1554 
1560  public function getLastError() {
1561  return $this->lastError;
1562  }
1563 
1571  protected function getThumbnails() {
1572  return [];
1573  }
1574 
1583  public function purgeCache( $options = [] ) {
1584  }
1585 
1591  public function purgeDescription() {
1592  $title = $this->getTitle();
1593  if ( $title ) {
1595  $hcu = MediaWikiServices::getInstance()->getHtmlCacheUpdater();
1596  $hcu->purgeTitleUrls( $title, $hcu::PURGE_INTENT_TXROUND_REFLECTED );
1597  }
1598  }
1599 
1604  public function purgeEverything() {
1605  // Delete thumbnails and refresh file metadata cache
1606  $this->purgeCache();
1607  $this->purgeDescription();
1608  // Purge cache of all pages using this file
1609  $title = $this->getTitle();
1610  if ( $title ) {
1612  $title,
1613  'imagelinks',
1614  [ 'causeAction' => 'file-purge' ]
1615  );
1616  JobQueueGroup::singleton()->lazyPush( $job );
1617  }
1618  }
1619 
1632  public function getHistory( $limit = null, $start = null, $end = null, $inc = true ) {
1633  return [];
1634  }
1635 
1646  public function nextHistoryLine() {
1647  return false;
1648  }
1649 
1657  public function resetHistory() {
1658  }
1659 
1667  public function getHashPath() {
1668  if ( $this->hashPath === null ) {
1669  $this->assertRepoDefined();
1670  $this->hashPath = $this->repo->getHashPath( $this->getName() );
1671  }
1672 
1673  return $this->hashPath;
1674  }
1675 
1683  public function getRel() {
1684  return $this->getHashPath() . $this->getName();
1685  }
1686 
1695  public function getArchiveRel( $suffix = false ) {
1696  $path = 'archive/' . $this->getHashPath();
1697  if ( $suffix === false ) {
1698  $path = rtrim( $path, '/' );
1699  } else {
1700  $path .= $suffix;
1701  }
1702 
1703  return $path;
1704  }
1705 
1714  public function getThumbRel( $suffix = false ) {
1715  $path = $this->getRel();
1716  if ( $suffix !== false ) {
1717  $path .= '/' . $suffix;
1718  }
1719 
1720  return $path;
1721  }
1722 
1730  public function getUrlRel() {
1731  return $this->getHashPath() . rawurlencode( $this->getName() );
1732  }
1733 
1742  private function getArchiveThumbRel( $archiveName, $suffix = false ) {
1743  $path = $this->getArchiveRel( $archiveName );
1744  if ( $suffix !== false ) {
1745  $path .= '/' . $suffix;
1746  }
1747 
1748  return $path;
1749  }
1750 
1757  public function getArchivePath( $suffix = false ) {
1758  $this->assertRepoDefined();
1759 
1760  return $this->repo->getZonePath( 'public' ) . '/' . $this->getArchiveRel( $suffix );
1761  }
1762 
1770  public function getArchiveThumbPath( $archiveName, $suffix = false ) {
1771  $this->assertRepoDefined();
1772 
1773  return $this->repo->getZonePath( 'thumb' ) . '/' .
1774  $this->getArchiveThumbRel( $archiveName, $suffix );
1775  }
1776 
1784  public function getThumbPath( $suffix = false ) {
1785  $this->assertRepoDefined();
1786 
1787  return $this->repo->getZonePath( 'thumb' ) . '/' . $this->getThumbRel( $suffix );
1788  }
1789 
1796  public function getTranscodedPath( $suffix = false ) {
1797  $this->assertRepoDefined();
1798 
1799  return $this->repo->getZonePath( 'transcoded' ) . '/' . $this->getThumbRel( $suffix );
1800  }
1801 
1809  public function getArchiveUrl( $suffix = false ) {
1810  $this->assertRepoDefined();
1811  $ext = $this->getExtension();
1812  $path = $this->repo->getZoneUrl( 'public', $ext ) . '/archive/' . $this->getHashPath();
1813  if ( $suffix === false ) {
1814  $path = rtrim( $path, '/' );
1815  } else {
1816  $path .= rawurlencode( $suffix );
1817  }
1818 
1819  return $path;
1820  }
1821 
1830  public function getArchiveThumbUrl( $archiveName, $suffix = false ) {
1831  $this->assertRepoDefined();
1832  $ext = $this->getExtension();
1833  $path = $this->repo->getZoneUrl( 'thumb', $ext ) . '/archive/' .
1834  $this->getHashPath() . rawurlencode( $archiveName );
1835  if ( $suffix !== false ) {
1836  $path .= '/' . rawurlencode( $suffix );
1837  }
1838 
1839  return $path;
1840  }
1841 
1849  private function getZoneUrl( $zone, $suffix = false ) {
1850  $this->assertRepoDefined();
1851  $ext = $this->getExtension();
1852  $path = $this->repo->getZoneUrl( $zone, $ext ) . '/' . $this->getUrlRel();
1853  if ( $suffix !== false ) {
1854  $path .= '/' . rawurlencode( $suffix );
1855  }
1856 
1857  return $path;
1858  }
1859 
1867  public function getThumbUrl( $suffix = false ) {
1868  return $this->getZoneUrl( 'thumb', $suffix );
1869  }
1870 
1877  public function getTranscodedUrl( $suffix = false ) {
1878  return $this->getZoneUrl( 'transcoded', $suffix );
1879  }
1880 
1888  public function getVirtualUrl( $suffix = false ) {
1889  $this->assertRepoDefined();
1890  $path = $this->repo->getVirtualUrl() . '/public/' . $this->getUrlRel();
1891  if ( $suffix !== false ) {
1892  $path .= '/' . rawurlencode( $suffix );
1893  }
1894 
1895  return $path;
1896  }
1897 
1905  public function getArchiveVirtualUrl( $suffix = false ) {
1906  $this->assertRepoDefined();
1907  $path = $this->repo->getVirtualUrl() . '/public/archive/' . $this->getHashPath();
1908  if ( $suffix === false ) {
1909  $path = rtrim( $path, '/' );
1910  } else {
1911  $path .= rawurlencode( $suffix );
1912  }
1913 
1914  return $path;
1915  }
1916 
1924  public function getThumbVirtualUrl( $suffix = false ) {
1925  $this->assertRepoDefined();
1926  $path = $this->repo->getVirtualUrl() . '/thumb/' . $this->getUrlRel();
1927  if ( $suffix !== false ) {
1928  $path .= '/' . rawurlencode( $suffix );
1929  }
1930 
1931  return $path;
1932  }
1933 
1937  protected function isHashed() {
1938  $this->assertRepoDefined();
1939 
1940  return (bool)$this->repo->getHashLevels();
1941  }
1942 
1947  protected function readOnlyError() {
1948  throw new MWException( static::class . ': write operations are not supported' );
1949  }
1950 
1973  public function publish( $src, $flags = 0, array $options = [] ) {
1974  $this->readOnlyError();
1975  }
1976 
1981  public function formatMetadata( $context = false ) {
1982  if ( !$this->getHandler() ) {
1983  return false;
1984  }
1985 
1986  return $this->getHandler()->formatMetadata( $this, $context );
1987  }
1988 
1994  public function isLocal() {
1995  return $this->repo && $this->repo->isLocal();
1996  }
1997 
2003  public function getRepoName() {
2004  return $this->repo ? $this->repo->getName() : 'unknown';
2005  }
2006 
2013  public function getRepo() {
2014  return $this->repo;
2015  }
2016 
2024  public function isOld() {
2025  return false;
2026  }
2027 
2036  public function isDeleted( $field ) {
2037  return false;
2038  }
2039 
2046  public function getVisibility() {
2047  return 0;
2048  }
2049 
2055  public function wasDeleted() {
2056  $title = $this->getTitle();
2057 
2058  return $title && $title->hasDeletedEdits();
2059  }
2060 
2074  public function move( $target ) {
2075  $this->readOnlyError();
2076  }
2077 
2096  public function deleteFile( $reason, UserIdentity $user, $suppress = false ) {
2097  $this->readOnlyError();
2098  }
2099 
2114  public function restore( $versions = [], $unsuppress = false ) {
2115  $this->readOnlyError();
2116  }
2117 
2126  public function isMultipage() {
2127  return $this->getHandler() && $this->handler->isMultiPage( $this );
2128  }
2129 
2137  public function pageCount() {
2138  if ( !isset( $this->pageCount ) ) {
2139  if ( $this->getHandler() && $this->handler->isMultiPage( $this ) ) {
2140  $this->pageCount = $this->handler->pageCount( $this );
2141  } else {
2142  $this->pageCount = false;
2143  }
2144  }
2145 
2146  return $this->pageCount;
2147  }
2148 
2158  public static function scaleHeight( $srcWidth, $srcHeight, $dstWidth ) {
2159  // Exact integer multiply followed by division
2160  if ( $srcWidth == 0 ) {
2161  return 0;
2162  } else {
2163  return (int)round( $srcHeight * $dstWidth / $srcWidth );
2164  }
2165  }
2166 
2174  public function getDescriptionUrl() {
2175  if ( $this->repo ) {
2176  return $this->repo->getDescriptionUrl( $this->getName() );
2177  } else {
2178  return false;
2179  }
2180  }
2181 
2190  public function getDescriptionText( Language $lang = null ) {
2191  global $wgLang;
2192 
2193  if ( !$this->repo || !$this->repo->fetchDescription ) {
2194  return false;
2195  }
2196 
2197  $lang = $lang ?? $wgLang;
2198 
2199  $renderUrl = $this->repo->getDescriptionRenderUrl( $this->getName(), $lang->getCode() );
2200  if ( $renderUrl ) {
2201  $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
2202  $key = $this->repo->getLocalCacheKey(
2203  'file-remote-description',
2204  $lang->getCode(),
2205  md5( $this->getName() )
2206  );
2207  $fname = __METHOD__;
2208 
2209  return $cache->getWithSetCallback(
2210  $key,
2211  $this->repo->descriptionCacheExpiry ?: $cache::TTL_UNCACHEABLE,
2212  static function ( $oldValue, &$ttl, array &$setOpts ) use ( $renderUrl, $fname ) {
2213  wfDebug( "Fetching shared description from $renderUrl" );
2214  $res = MediaWikiServices::getInstance()->getHttpRequestFactory()->
2215  get( $renderUrl, [], $fname );
2216  if ( !$res ) {
2217  $ttl = WANObjectCache::TTL_UNCACHEABLE;
2218  }
2219 
2220  return $res;
2221  }
2222  );
2223  }
2224 
2225  return false;
2226  }
2227 
2243  public function getUploader( int $audience = self::FOR_PUBLIC, Authority $performer = null ): ?UserIdentity {
2244  return null;
2245  }
2246 
2260  public function getDescription( $audience = self::FOR_PUBLIC, Authority $performer = null ) {
2261  return null;
2262  }
2263 
2270  public function getTimestamp() {
2271  $this->assertRepoDefined();
2272 
2273  return $this->repo->getFileTimestamp( $this->getPath() );
2274  }
2275 
2284  public function getDescriptionTouched() {
2285  return false;
2286  }
2287 
2294  public function getSha1() {
2295  $this->assertRepoDefined();
2296 
2297  return $this->repo->getFileSha1( $this->getPath() );
2298  }
2299 
2305  public function getStorageKey() {
2306  $hash = $this->getSha1();
2307  if ( !$hash ) {
2308  return false;
2309  }
2310  $ext = $this->getExtension();
2311  $dotExt = $ext === '' ? '' : ".$ext";
2312 
2313  return $hash . $dotExt;
2314  }
2315 
2325  public function userCan( $field, Authority $performer ) {
2326  return true;
2327  }
2328 
2333  public function getContentHeaders() {
2334  $handler = $this->getHandler();
2335  if ( $handler ) {
2336  return $handler->getContentHeaders( $this->getMetadataArray() );
2337  }
2338 
2339  return [];
2340  }
2341 
2345  public function getLongDesc() {
2346  $handler = $this->getHandler();
2347  if ( $handler ) {
2348  return $handler->getLongDesc( $this );
2349  } else {
2350  return MediaHandler::getGeneralLongDesc( $this );
2351  }
2352  }
2353 
2357  public function getShortDesc() {
2358  $handler = $this->getHandler();
2359  if ( $handler ) {
2360  return $handler->getShortDesc( $this );
2361  } else {
2362  return MediaHandler::getGeneralShortDesc( $this );
2363  }
2364  }
2365 
2369  public function getDimensionsString() {
2370  $handler = $this->getHandler();
2371  if ( $handler ) {
2372  return $handler->getDimensionsString( $this );
2373  } else {
2374  return '';
2375  }
2376  }
2377 
2381  public function getRedirected() {
2382  return $this->redirected;
2383  }
2384 
2388  protected function getRedirectedTitle() {
2389  if ( $this->redirected ) {
2390  if ( !$this->redirectTitle ) {
2391  $this->redirectTitle = Title::makeTitle( NS_FILE, $this->redirected );
2392  }
2393 
2394  return $this->redirectTitle;
2395  }
2396 
2397  return null;
2398  }
2399 
2404  public function redirectedFrom( $from ) {
2405  $this->redirected = $from;
2406  }
2407 
2412  public function isMissing() {
2413  return false;
2414  }
2415 
2421  public function isCacheable() {
2422  return true;
2423  }
2424 
2429  protected function assertRepoDefined() {
2430  if ( !( $this->repo instanceof $this->repoClass ) ) {
2431  throw new MWException( "A {$this->repoClass} object is not set for this File.\n" );
2432  }
2433  }
2434 
2439  protected function assertTitleDefined() {
2440  if ( !( $this->title instanceof Title ) ) {
2441  throw new MWException( "A Title object is not set for this File.\n" );
2442  }
2443  }
2444 
2449  public function isExpensiveToThumbnail() {
2450  $handler = $this->getHandler();
2451  return $handler ? $handler->isExpensiveToThumbnail( $this ) : false;
2452  }
2453 
2460  public function isTransformedLocally() {
2461  return true;
2462  }
2463 }
File\getExtension
getExtension()
Get the file extension, e.g.
Definition: File.php:346
File\getContentHeaders
getContentHeaders()
Definition: File.php:2333
File\THUMB_FULL_NAME
const THUMB_FULL_NAME
Definition: File.php:92
Page\PageIdentity
Interface for objects (potentially) representing an editable wiki page.
Definition: PageIdentity.php:64
File\getDisplayWidthHeight
getDisplayWidthHeight( $maxWidth, $maxHeight, $page=1)
Get the width and height to display image at.
Definition: File.php:577
File\wasDeleted
wasDeleted()
Was this file ever deleted from the wiki?
Definition: File.php:2055
File\redirectedFrom
redirectedFrom( $from)
Definition: File.php:2404
File\getDescriptionTouched
getDescriptionTouched()
Returns the timestamp (in TS_MW format) of the last change of the description page.
Definition: File.php:2284
File\getPath
getPath()
Return the storage path to the file.
Definition: File.php:457
MediaTransformError
Basic media transform error class.
Definition: MediaTransformError.php:31
ThumbnailImage
Media transform output for images.
Definition: ThumbnailImage.php:29
File\checkExtensionCompatibility
static checkExtensionCompatibility(File $old, $new)
Checks if file extensions are compatible.
Definition: File.php:280
File\$repo
FileRepo LocalRepo ForeignAPIRepo bool $repo
Some member variables can be lazy-initialised using __get().
Definition: File.php:114
MediaHandler\getCommonMetaArray
getCommonMetaArray(File $file)
Get an array of standard (FormatMetadata type) metadata values.
Definition: MediaHandler.php:409
File\canAnimateThumbIfAppropriate
canAnimateThumbIfAppropriate()
Will the thumbnail be animated if one would expect it to be.
Definition: File.php:701
MediaHandler\normaliseParams
normaliseParams( $image, &$params)
Changes the parameter array as necessary, ready for transformation.
File\getArchiveThumbPath
getArchiveThumbPath( $archiveName, $suffix=false)
Get the path of an archived file's thumbs, or a particular thumb if $suffix is specified.
Definition: File.php:1770
File\$hashPath
string null $hashPath
Relative path including trailing slash.
Definition: File.php:147
File\getHeight
getHeight( $page=1)
Return the height of the image.
Definition: File.php:519
File\DELETED_USER
const DELETED_USER
Definition: File.php:73
File\$tmpBucketedThumbCache
array $tmpBucketedThumbCache
Cache of tmp filepaths pointing to generated bucket thumbnails, keyed by width.
Definition: File.php:172
File\getDescriptionShortUrl
getDescriptionShortUrl()
Get short description URL for a files based on the page ID.
Definition: File.php:401
File\getBitDepth
getBitDepth()
Return the bit depth of the file Overridden by LocalFile STUB.
Definition: File.php:812
File\getUrlRel
getUrlRel()
Get urlencoded path of the file relative to the public zone root.
Definition: File.php:1730
File\migrateThumbFile
migrateThumbFile( $thumbName)
Hook into transform() to allow migration of thumbnail files STUB.
Definition: File.php:1516
File\isMultipage
isMultipage()
Returns 'true' if this file is a type which supports multiple pages, e.g.
Definition: File.php:2126
File\getFullUrl
getFullUrl()
Return a fully-qualified URL to the file.
Definition: File.php:413
File\getZoneUrl
getZoneUrl( $zone, $suffix=false)
Get the URL of the zone directory, or a particular file if $suffix is specified.
Definition: File.php:1849
File\DELETED_RESTRICTED
const DELETED_RESTRICTED
Definition: File.php:74
File\getMetadata
getMetadata()
Get handler-specific metadata Overridden by LocalFile, UnregisteredLocalFile STUB.
Definition: File.php:726
File\RAW
const RAW
Definition: File.php:89
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:202
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
File\getIsSafeFileUncached
getIsSafeFileUncached()
Uncached accessor.
Definition: File.php:938
File\getRel
getRel()
Get the path of the file relative to the public zone root.
Definition: File.php:1683
File\isExpensiveToThumbnail
isExpensiveToThumbnail()
True if creating thumbnails from the file is large or otherwise resource-intensive.
Definition: File.php:2449
File\isMissing
isMissing()
Definition: File.php:2412
File\getOriginalTitle
getOriginalTitle()
Return the title used to find this file.
Definition: File.php:370
File\getUploader
getUploader(int $audience=self::FOR_PUBLIC, Authority $performer=null)
Get the identity of the file uploader.
Definition: File.php:2243
File\$redirectTitle
Title $redirectTitle
Definition: File.php:158
MediaHandler\getShortDesc
getShortDesc( $file)
Short description.
Definition: MediaHandler.php:814
File\getLastError
getLastError()
Get last thumbnailing error.
Definition: File.php:1560
File\getTimestamp
getTimestamp()
Get the 14-character timestamp of the file upload.
Definition: File.php:2270
File\getSha1
getSha1()
Get the SHA-1 base 36 hash of the file.
Definition: File.php:2294
File\convertMetadataVersion
convertMetadataVersion( $metadata, $version)
get versioned metadata
Definition: File.php:796
FileBackend\extensionFromPath
static extensionFromPath( $path, $case='lowercase')
Get the final extension from a storage or FS path.
Definition: FileBackend.php:1583
File\RENDER_FORCE
const RENDER_FORCE
Force rendering even if thumbnail already exist and using RENDER_NOW I.e.
Definition: File.php:82
File\getUrl
getUrl()
Return the URL of the file.
Definition: File.php:384
File\compare
static compare(File $a, File $b)
Callback for usort() to do file sorts by name.
Definition: File.php:321
MediaHandler\getMatchedLanguage
getMatchedLanguage( $userPreferredLanguage, array $availableLanguages)
When overridden in a descendant class, returns a language code most suiting.
Definition: MediaHandler.php:1040
File\getTranscodedUrl
getTranscodedUrl( $suffix=false)
Get the URL of the transcoded directory, or a particular file if $suffix is specified.
Definition: File.php:1877
File\getThumbnailSource
getThumbnailSource( $params)
Returns the most appropriate source image for the thumbnail, given a target thumbnail size.
Definition: File.php:1402
MEDIATYPE_UNKNOWN
const MEDIATYPE_UNKNOWN
Definition: defines.php:26
File\getWidth
getWidth( $page=1)
Return the width of the image.
Definition: File.php:504
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1183
File\getMediaType
getMediaType()
Return the type of the media in the file.
Definition: File.php:847
File\restore
restore( $versions=[], $unsuppress=false)
Restore all or specified deleted revisions to the given file.
Definition: File.php:2114
File\getCanonicalUrl
getCanonicalUrl()
Definition: File.php:421
File\splitMime
static splitMime( $mime)
Split an internet media type into its two components; if not a two-part name, set the minor type to '...
Definition: File.php:306
File\isVisible
isVisible()
Returns true if file exists in the repository and can be included in a page.
Definition: File.php:1019
PoolCounterWorkViaCallback
Convenience class for dealing with PoolCounters using callbacks.
Definition: PoolCounterWorkViaCallback.php:31
$wgThumbnailBuckets
$wgThumbnailBuckets
When defined, is an array of image widths used as buckets for thumbnail generation.
Definition: DefaultSettings.php:1675
MediaHandler\getLongDesc
getLongDesc( $file)
Long description.
Definition: MediaHandler.php:826
$res
$res
Definition: testCompression.php:57
File\getMetadataArray
getMetadataArray()
Get the unserialized handler-specific metadata STUB.
Definition: File.php:744
IDBAccessObject
Interface for database access objects.
Definition: IDBAccessObject.php:57
File\$repoClass
string $repoClass
Required Repository class type.
Definition: File.php:169
File\getArchiveRel
getArchiveRel( $suffix=false)
Get the path of an archived file relative to the public zone root.
Definition: File.php:1695
$wgLang
$wgLang
Definition: Setup.php:857
File\isDeleted
isDeleted( $field)
Is this file a "deleted" file in a private archive? STUB.
Definition: File.php:2036
MediaWiki\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:39
File\setHandlerState
setHandlerState(string $key, $value)
Set a value.
Definition: File.php:734
File\getVisibility
getVisibility()
Return the deletion bitfield STUB.
Definition: File.php:2046
$wgThumbnailMinimumBucketDistance
$wgThumbnailMinimumBucketDistance
When using thumbnail buckets as defined above, this sets the minimum distance to the bucket above the...
Definition: DefaultSettings.php:1692
MediaHandler\supportsBucketing
supportsBucketing()
Returns whether or not this handler supports the chained generation of thumbnails according to bucket...
Definition: MediaHandler.php:1097
File\FOR_PUBLIC
const FOR_PUBLIC
Definition: File.php:87
File\normalizeTitle
static normalizeTitle( $title, $exception=false)
Given a string or Title object return either a valid Title object with namespace NS_FILE or null.
Definition: File.php:206
MediaHandler\getAvailableLanguages
getAvailableLanguages(File $file)
Get list of languages file can be viewed in.
Definition: MediaHandler.php:1025
File\exists
exists()
Returns true if file exists in the repository.
Definition: File.php:1008
File\getThumbVirtualUrl
getThumbVirtualUrl( $suffix=false)
Get the virtual URL for a thumbnail file or directory.
Definition: File.php:1924
$wgThumbnailEpoch
$wgThumbnailEpoch
If rendered thumbnail files are older than this timestamp, they will be rerendered on demand as if th...
Definition: DefaultSettings.php:1451
File\upgradeRow
upgradeRow()
Upgrade the database row if there is one Called by ImagePage STUB.
Definition: File.php:296
Title\castFromPageIdentity
static castFromPageIdentity(?PageIdentity $pageIdentity)
Return a Title for a given PageIdentity.
Definition: Title.php:344
FileRepo
Base class for file repositories.
Definition: FileRepo.php:45
wfAppendQuery
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
Definition: GlobalFunctions.php:422
File\$path
string $path
The storage path corresponding to one of the zones.
Definition: File.php:144
MediaWiki\MediaWikiServices\getInstance
static getInstance()
Returns the global default instance of the top level service locator.
Definition: MediaWikiServices.php:263
File\isCacheable
isCacheable()
Check if this file object is small and can be cached.
Definition: File.php:2421
File\$canRender
bool $canRender
Whether the output of transform() for this file is likely to be valid.
Definition: File.php:161
File\getBucketThumbName
getBucketThumbName( $bucket)
Returns the name of the thumb for a given bucket.
Definition: File.php:1480
PROTO_RELATIVE
const PROTO_RELATIVE
Definition: Defines.php:194
File
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition: File.php:67
MediaHandler\isExpensiveToThumbnail
isExpensiveToThumbnail( $file)
True if creating thumbnails from the file is large or otherwise resource-intensive.
Definition: MediaHandler.php:1085
File\getMimeType
getMimeType()
Returns the MIME type of the file.
Definition: File.php:835
File\getDefaultRenderLanguage
getDefaultRenderLanguage()
In files that support multiple language, what is the default language to use if none specified.
Definition: File.php:682
File\$url
string $url
The URL corresponding to one of the four basic zones.
Definition: File.php:135
MWException
MediaWiki exception.
Definition: MWException.php:29
File\getLocalRefPath
getLocalRefPath()
Get an FS copy or original of this file and return the path.
Definition: File.php:473
File\DELETED_COMMENT
const DELETED_COMMENT
Definition: File.php:72
File\transformErrorOutput
transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags)
Return either a MediaTransformError or placeholder thumbnail (if $wgIgnoreImageErrors)
Definition: File.php:1148
File\getIsSafeFile
getIsSafeFile()
Accessor for __get()
Definition: File.php:929
File\$redirectedTitle
Title $redirectedTitle
Definition: File.php:126
File\getThumbPath
getThumbPath( $suffix=false)
Get the path of the thumbnail directory, or a particular file if $suffix is specified.
Definition: File.php:1784
File\pageCount
pageCount()
Returns the number of pages of a multipage document, or false for documents which aren't multipage do...
Definition: File.php:2137
File\nextHistoryLine
nextHistoryLine()
Return the history of this file, line by line.
Definition: File.php:1646
File\normalizeExtension
static normalizeExtension( $extension)
Normalize a file extension to the common form, making it lowercase and checking some synonyms,...
Definition: File.php:255
PoolCounterWork\execute
execute( $skipcache=false)
Get the result of the work (whatever it is), or the result of the error() function.
Definition: PoolCounterWork.php:127
File\getMetadataItem
getMetadataItem(string $itemName)
Get a specific element of the unserialized handler-specific metadata.
Definition: File.php:755
File\getArchiveVirtualUrl
getArchiveVirtualUrl( $suffix=false)
Get the public zone virtual URL for an archived version source file.
Definition: File.php:1905
MediaHandler\canAnimateThumbnail
canAnimateThumbnail( $file)
If the material is animated, we can animate the thumbnail.
Definition: MediaHandler.php:574
File\purgeCache
purgeCache( $options=[])
Purge shared caches such as thumbnails and DB data caching STUB Overridden by LocalFile.
Definition: File.php:1583
File\getTransformScript
getTransformScript()
Definition: File.php:1026
File\userCan
userCan( $field, Authority $performer)
Determine if the current user is allowed to view a particular field of this file, if it's marked as d...
Definition: File.php:2325
File\FOR_THIS_USER
const FOR_THIS_USER
Definition: File.php:88
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:666
File\getArchiveThumbRel
getArchiveThumbRel( $archiveName, $suffix=false)
Get the path, relative to the thumbnail zone root, for an archived file's thumbs directory or a speci...
Definition: File.php:1742
PROTO_CANONICAL
const PROTO_CANONICAL
Definition: Defines.php:196
File\getStorageKey
getStorageKey()
Get the deletion archive key, "<sha1>.<ext>".
Definition: File.php:2305
File\__construct
__construct( $title, $repo)
Call this constructor from child classes.
Definition: File.php:188
File\isHashed
isHashed()
Definition: File.php:1937
File\generateAndSaveThumb
generateAndSaveThumb( $tmpFile, $transformParams, $flags)
Generates a thumbnail according to the given parameters and saves it to storage.
Definition: File.php:1266
File\getHandlerState
getHandlerState(string $key)
Get a value, or null if it does not exist.
Definition: File.php:730
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:894
File\getCommonMetaArray
getCommonMetaArray()
Like getMetadata but returns a handler independent array of common values.
Definition: File.php:779
File\getThumbRel
getThumbRel( $suffix=false)
Get the path, relative to the thumbnail zone root, of the thumbnail directory or a particular file if...
Definition: File.php:1714
File\isTransformedLocally
isTransformedLocally()
Whether the thumbnails created on the same server as this code is running.
Definition: File.php:2460
MediaHandler\getDimensionsString
getDimensionsString( $file)
Shown in file history box on image description page.
Definition: MediaHandler.php:879
MediaWiki\Permissions\Authority
This interface represents the authority associated the current execution context, such as a web reque...
Definition: Authority.php:37
File\canRender
canRender()
Checks if the output of transform() for this file is likely to be valid.
Definition: File.php:863
File\$fsFile
FSFile bool $fsFile
False if undefined.
Definition: File.php:129
File\getRedirectedTitle
getRedirectedTitle()
Definition: File.php:2388
MediaHandler\convertMetadataVersion
convertMetadataVersion( $metadata, $version=1)
Convert metadata version.
Definition: MediaHandler.php:308
MediaHandler\getGeneralShortDesc
static getGeneralShortDesc( $file)
Used instead of getShortDesc if there is no handler registered for file.
Definition: MediaHandler.php:836
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:692
File\getAvailableLanguages
getAvailableLanguages()
Gives a (possibly empty) list of languages to render the file in.
Definition: File.php:647
File\iconThumb
iconThumb()
Get a ThumbnailImage representing a file type icon.
Definition: File.php:1538
File\purgeDescription
purgeDescription()
Purge the file description page, but don't go after pages using the file.
Definition: File.php:1591
NS_MEDIA
const NS_MEDIA
Definition: Defines.php:52
File\getMetadataItems
getMetadataItems(array $itemNames)
Get multiple elements of the unserialized handler-specific metadata.
Definition: File.php:767
File\isOld
isOld()
Returns true if the image is an old version STUB.
Definition: File.php:2024
File\$handler
MediaHandler $handler
Definition: File.php:132
File\assertTitleDefined
assertTitleDefined()
Assert that $this->title is set to a Title.
Definition: File.php:2439
$wgIgnoreImageErrors
$wgIgnoreImageErrors
If set, inline scaled images will still produce "<img>" tags ready for output instead of showing an e...
Definition: DefaultSettings.php:1472
MediaHandler\getTransform
getTransform( $image, $dstPath, $dstUrl, $params)
Get a MediaTransformOutput object representing the transformed output.
Definition: MediaHandler.php:444
File\getHistory
getHistory( $limit=null, $start=null, $end=null, $inc=true)
Return a fragment of the history of file.
Definition: File.php:1632
Title\hasDeletedEdits
hasDeletedEdits()
Is there a version of this page in the deletion archive?
Definition: Title.php:2856
File\generateThumbName
generateThumbName( $name, $params)
Generate a thumbnail file name from a name and specified parameters.
Definition: File.php:1087
HTMLCacheUpdateJob\newForBacklinks
static newForBacklinks(PageReference $page, $table, $params=[])
Definition: HTMLCacheUpdateJob.php:61
File\formatMetadata
formatMetadata( $context=false)
Definition: File.php:1981
File\getDescription
getDescription( $audience=self::FOR_PUBLIC, Authority $performer=null)
Get description of file revision STUB.
Definition: File.php:2260
File\createThumb
createThumb( $width, $height=-1)
Create a thumbnail of the image having the specified width/height.
Definition: File.php:1126
File\$title
Title string bool $title
Definition: File.php:117
File\getDescriptionUrl
getDescriptionUrl()
Get the URL of the image description page.
Definition: File.php:2174
File\getArchiveThumbUrl
getArchiveThumbUrl( $archiveName, $suffix=false)
Get the URL of the archived file's thumbs, or a particular thumb if $suffix is specified.
Definition: File.php:1830
File\$transformScript
string false $transformScript
URL of transformscript (for example thumb.php)
Definition: File.php:155
File\getName
getName()
Return the name of this file.
Definition: File.php:331
File\getArchiveUrl
getArchiveUrl( $suffix=false)
Get the URL of the archive directory, or a particular file if $suffix is specified.
Definition: File.php:1809
File\getThumbDisposition
getThumbDisposition( $thumbName, $dispositionType='inline')
Definition: File.php:1500
FSFile
Class representing a non-directory file on the file system.
Definition: FSFile.php:32
MediaHandler\doTransform
doTransform( $image, $dstPath, $dstUrl, $params, $flags=0)
Get a MediaTransformOutput object representing the transformed output.
File\isSafeFile
isSafeFile()
Determines if this media file is in a format that is unlikely to contain viruses or malicious content...
Definition: File.php:916
File\$pageCount
int false $pageCount
Number of pages of a multipage document, or false for documents which aren't multipage documents.
Definition: File.php:152
File\getRepoName
getRepoName()
Returns the name of the repository.
Definition: File.php:2003
File\DELETE_SOURCE
const DELETE_SOURCE
Definition: File.php:84
File\$handlerState
array $handlerState
Definition: File.php:175
$wgResourceBasePath
$wgResourceBasePath
The default 'remoteBasePath' value for instances of ResourceLoaderFileModule.
Definition: DefaultSettings.php:4412
File\publish
publish( $src, $flags=0, array $options=[])
Move or copy a file to its public location.
Definition: File.php:1973
File\$extension
string $extension
File extension.
Definition: File.php:138
File\getBucketThumbPath
getBucketThumbPath( $bucket)
Returns the repo path of the thumb for a given bucket.
Definition: File.php:1470
File\scaleHeight
static scaleHeight( $srcWidth, $srcHeight, $dstWidth)
Calculate the height of a thumbnail using the source and destination width.
Definition: File.php:2158
File\RENDER_NOW
const RENDER_NOW
Force rendering in the current process.
Definition: File.php:77
File\transform
transform( $params, $flags=0)
Transform a media file.
Definition: File.php:1169
File\getTitle
getTitle()
Return the associated title object.
Definition: File.php:361
File\readOnlyError
readOnlyError()
Definition: File.php:1947
Title
Represents a title within MediaWiki.
Definition: Title.php:47
ForeignAPIRepo
A foreign repository for a remote MediaWiki accessible through api.php requests.
Definition: ForeignAPIRepo.php:42
File\$isSafeFile
bool $isSafeFile
Whether this media file is in a format that is unlikely to contain viruses or malicious content.
Definition: File.php:166
JobQueueGroup\singleton
static singleton( $domain=false)
Definition: JobQueueGroup.php:114
File\getThumbnailBucket
getThumbnailBucket( $desiredWidth, $page=1)
Return the smallest bucket from $wgThumbnailBuckets which is at least $wgThumbnailMinimumBucketDistan...
Definition: File.php:532
MediaHandler\getContentHeaders
getContentHeaders( $metadata)
Get useful response headers for GET/HEAD requests for a file with the given metadata.
Definition: MediaHandler.php:1197
$cache
$cache
Definition: mcc.php:33
File\move
move( $target)
Move file to the new title.
Definition: File.php:2074
File\assertRepoDefined
assertRepoDefined()
Assert that $this->repo is set to a valid FileRepo instance.
Definition: File.php:2429
File\getShortDesc
getShortDesc()
Definition: File.php:2357
$job
if(count( $args)< 1) $job
Definition: recompressTracked.php:49
File\getLength
getLength()
Get the duration of a media file in seconds.
Definition: File.php:613
File\getLongDesc
getLongDesc()
Definition: File.php:2345
File\isLocal
isLocal()
Returns true if the file comes from the local file repository.
Definition: File.php:1994
File\getDescriptionText
getDescriptionText(Language $lang=null)
Get the HTML text of the description page, if available.
Definition: File.php:2190
MediaHandler\getHandler
static getHandler( $type)
Get a MediaHandler for a given MIME type from the instance cache.
Definition: MediaHandler.php:53
File\getCanRender
getCanRender()
Accessor for __get()
Definition: File.php:875
MediaHandler\isAnimatedImage
isAnimatedImage( $file)
The material is an image, and is animated.
Definition: MediaHandler.php:561
MediaHandler\isVectorized
isVectorized( $file)
The material is vectorized and thus scaling is lossless.
Definition: MediaHandler.php:547
File\mustRender
mustRender()
Return true if the file is of a type that can't be directly rendered by typical browsers and needs to...
Definition: File.php:890
File\load
load( $flags=0)
Load any lazy-loaded file object fields from source.
Definition: File.php:997
File\resetHistory
resetHistory()
Reset the history pointer to the first element of the history.
Definition: File.php:1657
MediaHandler\getScriptedTransform
getScriptedTransform( $image, $script, $params)
Get a MediaTransformOutput object representing an alternate of the transformed output which will call...
Definition: MediaHandler.php:428
$ext
if(!is_readable( $file)) $ext
Definition: router.php:48
File\getRedirected
getRedirected()
Definition: File.php:2381
File\DELETED_FILE
const DELETED_FILE
Definition: File.php:71
File\getMatchedLanguage
getMatchedLanguage( $userPreferredLanguage)
Get the language code from the available languages for this file that matches the language requested ...
Definition: File.php:663
MediaHandler\getGeneralLongDesc
static getGeneralLongDesc( $file)
Used instead of getLongDesc if there is no handler registered for file.
Definition: MediaHandler.php:848
Title\castFromLinkTarget
static castFromLinkTarget( $linkTarget)
Same as newFromLinkTarget, but if passed null, returns null.
Definition: Title.php:331
File\getRepo
getRepo()
Returns the repository.
Definition: File.php:2013
File\deleteFile
deleteFile( $reason, UserIdentity $user, $suppress=false)
Delete all versions of the file.
Definition: File.php:2096
File\allowInlineDisplay
allowInlineDisplay()
Alias for canRender()
Definition: File.php:899
Title\invalidateCache
invalidateCache( $purgeTime=null)
Updates page_touched for this page; called from LinksUpdate.php.
Definition: Title.php:3681
$mime
$mime
Definition: router.php:60
NS_FILE
const NS_FILE
Definition: Defines.php:70
MediaWiki\Linker\LinkTarget
Definition: LinkTarget.php:26
File\getThumbUrl
getThumbUrl( $suffix=false)
Get the URL of the thumbnail directory, or a particular file if $suffix is specified.
Definition: File.php:1867
File\isVectorized
isVectorized()
Return true if the file is vectorized.
Definition: File.php:627
File\getDimensionsString
getDimensionsString()
Definition: File.php:2369
File\getHandler
getHandler()
Get a MediaHandler instance for this file.
Definition: File.php:1525
File\__get
__get( $name)
Definition: File.php:236
$wgTrustedMediaFormats
$wgTrustedMediaFormats
list of trusted media-types and MIME types.
Definition: DefaultSettings.php:1196
$IP
$IP
Definition: WebStart.php:49
File\generateBucketsIfNeeded
generateBucketsIfNeeded( $params, $flags=0)
Generates chained bucketed thumbnails if needed.
Definition: File.php:1345
File\thumbName
thumbName( $params, $flags=0)
Return the file name of a thumbnail with the specified parameters.
Definition: File.php:1071
File\$lastError
string $lastError
Text of last error.
Definition: File.php:120
File\$redirected
string $redirected
Main part of the title, with underscores (Title::getDBkey)
Definition: File.php:123
File\$name
string null $name
The name of a file from its title object.
Definition: File.php:141
MediaHandlerState
An interface to support process-local caching of handler data associated with a given file.
Definition: MediaHandlerState.php:10
FSFile\getPath
getPath()
Returns the file system path.
Definition: FSFile.php:53
File\makeTransformTmpFile
makeTransformTmpFile( $thumbPath)
Creates a temp FS file with the same extension and the thumbnail.
Definition: File.php:1489
File\getArchivePath
getArchivePath( $suffix=false)
Get the path of the archived file.
Definition: File.php:1757
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:42
File\purgeEverything
purgeEverything()
Purge metadata and all affected pages when the file is created, deleted, or majorly updated.
Definition: File.php:1604
File\getUnscaledThumb
getUnscaledThumb( $handlerParams=[])
Get a ThumbnailImage which is the same size as the source.
Definition: File.php:1047
File\getHashPath
getHashPath()
Get the filename hash component of the directory including trailing slash, e.g.
Definition: File.php:1667
File\isTrustedFile
isTrustedFile()
Returns true if the file is flagged as trusted.
Definition: File.php:981
LocalRepo
A repository that stores files in the local filesystem and registers them in the wiki's own database.
Definition: LocalRepo.php:41
File\getSize
getSize()
Return the size of the image file, in bytes Overridden by LocalFile, UnregisteredLocalFile STUB.
Definition: File.php:823
MediaHandler
Base media handler class.
Definition: MediaHandler.php:37
MediaHandler\getLength
getLength( $file)
If its an audio file, return the length of the file.
Definition: MediaHandler.php:1074
wfExpandUrl
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
Definition: GlobalFunctions.php:474
File\getThumbnails
getThumbnails()
Get all thumbnail names previously generated for this file STUB Overridden by LocalFile.
Definition: File.php:1571
MediaHandler\getDefaultRenderLanguage
getDefaultRenderLanguage(File $file)
On file types that support renderings in multiple languages, which language is used by default if uns...
Definition: MediaHandler.php:1058
File\getTranscodedPath
getTranscodedPath( $suffix=false)
Get the path of the transcoded directory, or a particular file if $suffix is specified.
Definition: File.php:1796
File\getViewURL
getViewURL()
Definition: File.php:428
File\getVirtualUrl
getVirtualUrl( $suffix=false)
Get the public zone virtual URL for a current version source file.
Definition: File.php:1888
$type
$type
Definition: testCompression.php:52
FileBackend\makeContentDisposition
static makeContentDisposition( $type, $filename='')
Build a Content-Disposition header value per RFC 6266.
Definition: FileBackend.php:1618