MediaWiki  1.32.0
FileRepo.php
Go to the documentation of this file.
1 <?php
11 
39 class FileRepo {
40  const DELETE_SOURCE = 1;
41  const OVERWRITE = 2;
42  const OVERWRITE_SAME = 4;
43  const SKIP_LOCKING = 8;
44 
45  const NAME_AND_TIME_ONLY = 1;
46 
50 
53 
55  protected $hasSha1Storage = false;
56 
58  protected $supportsSha1URLs = false;
59 
61  protected $backend;
62 
64  protected $zones = [];
65 
67  protected $thumbScriptUrl;
68 
71  protected $transformVia404;
72 
76  protected $descBaseUrl;
77 
81  protected $scriptDirUrl;
82 
84  protected $articleUrl;
85 
91  protected $initialCapital;
92 
98  protected $pathDisclosureProtection = 'simple';
99 
101  protected $url;
102 
104  protected $thumbUrl;
105 
107  protected $hashLevels;
108 
111 
116  protected $abbrvThreshold;
117 
119  protected $favicon;
120 
122  protected $isPrivate;
123 
125  protected $fileFactory = [ UnregisteredLocalFile::class, 'newFromTitle' ];
127  protected $oldFileFactory = false;
129  protected $fileFactoryKey = false;
131  protected $oldFileFactoryKey = false;
132 
136  protected $thumbProxyUrl;
138  protected $thumbProxySecret;
139 
144  public function __construct( array $info = null ) {
145  // Verify required settings presence
146  if (
147  $info === null
148  || !array_key_exists( 'name', $info )
149  || !array_key_exists( 'backend', $info )
150  ) {
151  throw new MWException( __CLASS__ .
152  " requires an array of options having both 'name' and 'backend' keys.\n" );
153  }
154 
155  // Required settings
156  $this->name = $info['name'];
157  if ( $info['backend'] instanceof FileBackend ) {
158  $this->backend = $info['backend']; // useful for testing
159  } else {
160  $this->backend = FileBackendGroup::singleton()->get( $info['backend'] );
161  }
162 
163  // Optional settings that can have no value
164  $optionalSettings = [
165  'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription',
166  'thumbScriptUrl', 'pathDisclosureProtection', 'descriptionCacheExpiry',
167  'favicon', 'thumbProxyUrl', 'thumbProxySecret',
168  ];
169  foreach ( $optionalSettings as $var ) {
170  if ( isset( $info[$var] ) ) {
171  $this->$var = $info[$var];
172  }
173  }
174 
175  // Optional settings that have a default
176  $this->initialCapital = $info['initialCapital'] ?? MWNamespace::isCapitalized( NS_FILE );
177  $this->url = $info['url'] ?? false; // a subclass may set the URL (e.g. ForeignAPIRepo)
178  if ( isset( $info['thumbUrl'] ) ) {
179  $this->thumbUrl = $info['thumbUrl'];
180  } else {
181  $this->thumbUrl = $this->url ? "{$this->url}/thumb" : false;
182  }
183  $this->hashLevels = $info['hashLevels'] ?? 2;
184  $this->deletedHashLevels = $info['deletedHashLevels'] ?? $this->hashLevels;
185  $this->transformVia404 = !empty( $info['transformVia404'] );
186  $this->abbrvThreshold = $info['abbrvThreshold'] ?? 255;
187  $this->isPrivate = !empty( $info['isPrivate'] );
188  // Give defaults for the basic zones...
189  $this->zones = $info['zones'] ?? [];
190  foreach ( [ 'public', 'thumb', 'transcoded', 'temp', 'deleted' ] as $zone ) {
191  if ( !isset( $this->zones[$zone]['container'] ) ) {
192  $this->zones[$zone]['container'] = "{$this->name}-{$zone}";
193  }
194  if ( !isset( $this->zones[$zone]['directory'] ) ) {
195  $this->zones[$zone]['directory'] = '';
196  }
197  if ( !isset( $this->zones[$zone]['urlsByExt'] ) ) {
198  $this->zones[$zone]['urlsByExt'] = [];
199  }
200  }
201 
202  $this->supportsSha1URLs = !empty( $info['supportsSha1URLs'] );
203  }
204 
210  public function getBackend() {
211  return $this->backend;
212  }
213 
220  public function getReadOnlyReason() {
221  return $this->backend->getReadOnlyReason();
222  }
223 
231  protected function initZones( $doZones = [] ) {
232  $status = $this->newGood();
233  foreach ( (array)$doZones as $zone ) {
234  $root = $this->getZonePath( $zone );
235  if ( $root === null ) {
236  throw new MWException( "No '$zone' zone defined in the {$this->name} repo." );
237  }
238  }
239 
240  return $status;
241  }
242 
249  public static function isVirtualUrl( $url ) {
250  return substr( $url, 0, 9 ) == 'mwrepo://';
251  }
252 
261  public function getVirtualUrl( $suffix = false ) {
262  $path = 'mwrepo://' . $this->name;
263  if ( $suffix !== false ) {
264  $path .= '/' . rawurlencode( $suffix );
265  }
266 
267  return $path;
268  }
269 
277  public function getZoneUrl( $zone, $ext = null ) {
278  if ( in_array( $zone, [ 'public', 'thumb', 'transcoded' ] ) ) {
279  // standard public zones
280  if ( $ext !== null && isset( $this->zones[$zone]['urlsByExt'][$ext] ) ) {
281  // custom URL for extension/zone
282  return $this->zones[$zone]['urlsByExt'][$ext];
283  } elseif ( isset( $this->zones[$zone]['url'] ) ) {
284  // custom URL for zone
285  return $this->zones[$zone]['url'];
286  }
287  }
288  switch ( $zone ) {
289  case 'public':
290  return $this->url;
291  case 'temp':
292  case 'deleted':
293  return false; // no public URL
294  case 'thumb':
295  return $this->thumbUrl;
296  case 'transcoded':
297  return "{$this->url}/transcoded";
298  default:
299  return false;
300  }
301  }
302 
306  public function backendSupportsUnicodePaths() {
307  return (bool)( $this->getBackend()->getFeatures() & FileBackend::ATTR_UNICODE_PATHS );
308  }
309 
318  public function resolveVirtualUrl( $url ) {
319  if ( substr( $url, 0, 9 ) != 'mwrepo://' ) {
320  throw new MWException( __METHOD__ . ': unknown protocol' );
321  }
322  $bits = explode( '/', substr( $url, 9 ), 3 );
323  if ( count( $bits ) != 3 ) {
324  throw new MWException( __METHOD__ . ": invalid mwrepo URL: $url" );
325  }
326  list( $repo, $zone, $rel ) = $bits;
327  if ( $repo !== $this->name ) {
328  throw new MWException( __METHOD__ . ": fetching from a foreign repo is not supported" );
329  }
330  $base = $this->getZonePath( $zone );
331  if ( !$base ) {
332  throw new MWException( __METHOD__ . ": invalid zone: $zone" );
333  }
334 
335  return $base . '/' . rawurldecode( $rel );
336  }
337 
344  protected function getZoneLocation( $zone ) {
345  if ( !isset( $this->zones[$zone] ) ) {
346  return [ null, null ]; // bogus
347  }
348 
349  return [ $this->zones[$zone]['container'], $this->zones[$zone]['directory'] ];
350  }
351 
358  public function getZonePath( $zone ) {
359  list( $container, $base ) = $this->getZoneLocation( $zone );
360  if ( $container === null || $base === null ) {
361  return null;
362  }
363  $backendName = $this->backend->getName();
364  if ( $base != '' ) { // may not be set
365  $base = "/{$base}";
366  }
367 
368  return "mwstore://$backendName/{$container}{$base}";
369  }
370 
382  public function newFile( $title, $time = false ) {
384  if ( !$title ) {
385  return null;
386  }
387  if ( $time ) {
388  if ( $this->oldFileFactory ) {
389  return call_user_func( $this->oldFileFactory, $title, $this, $time );
390  } else {
391  return null;
392  }
393  } else {
394  return call_user_func( $this->fileFactory, $title, $this );
395  }
396  }
397 
415  public function findFile( $title, $options = [] ) {
417  if ( !$title ) {
418  return false;
419  }
420  if ( isset( $options['bypassCache'] ) ) {
421  $options['latest'] = $options['bypassCache']; // b/c
422  }
423  $time = $options['time'] ?? false;
424  $flags = !empty( $options['latest'] ) ? File::READ_LATEST : 0;
425  # First try the current version of the file to see if it precedes the timestamp
426  $img = $this->newFile( $title );
427  if ( !$img ) {
428  return false;
429  }
430  $img->load( $flags );
431  if ( $img->exists() && ( !$time || $img->getTimestamp() == $time ) ) {
432  return $img;
433  }
434  # Now try an old version of the file
435  if ( $time !== false ) {
436  $img = $this->newFile( $title, $time );
437  if ( $img ) {
438  $img->load( $flags );
439  if ( $img->exists() ) {
440  if ( !$img->isDeleted( File::DELETED_FILE ) ) {
441  return $img; // always OK
442  } elseif ( !empty( $options['private'] ) &&
443  $img->userCan( File::DELETED_FILE,
444  $options['private'] instanceof User ? $options['private'] : null
445  )
446  ) {
447  return $img;
448  }
449  }
450  }
451  }
452 
453  # Now try redirects
454  if ( !empty( $options['ignoreRedirect'] ) ) {
455  return false;
456  }
457  $redir = $this->checkRedirect( $title );
458  if ( $redir && $title->getNamespace() == NS_FILE ) {
459  $img = $this->newFile( $redir );
460  if ( !$img ) {
461  return false;
462  }
463  $img->load( $flags );
464  if ( $img->exists() ) {
465  $img->redirectedFrom( $title->getDBkey() );
466 
467  return $img;
468  }
469  }
470 
471  return false;
472  }
473 
491  public function findFiles( array $items, $flags = 0 ) {
492  $result = [];
493  foreach ( $items as $item ) {
494  if ( is_array( $item ) ) {
495  $title = $item['title'];
496  $options = $item;
497  unset( $options['title'] );
498  } else {
499  $title = $item;
500  $options = [];
501  }
502  $file = $this->findFile( $title, $options );
503  if ( $file ) {
504  $searchName = File::normalizeTitle( $title )->getDBkey(); // must be valid
505  if ( $flags & self::NAME_AND_TIME_ONLY ) {
506  $result[$searchName] = [
507  'title' => $file->getTitle()->getDBkey(),
508  'timestamp' => $file->getTimestamp()
509  ];
510  } else {
511  $result[$searchName] = $file;
512  }
513  }
514  }
515 
516  return $result;
517  }
518 
528  public function findFileFromKey( $sha1, $options = [] ) {
529  $time = $options['time'] ?? false;
530  # First try to find a matching current version of a file...
531  if ( !$this->fileFactoryKey ) {
532  return false; // find-by-sha1 not supported
533  }
534  $img = call_user_func( $this->fileFactoryKey, $sha1, $this, $time );
535  if ( $img && $img->exists() ) {
536  return $img;
537  }
538  # Now try to find a matching old version of a file...
539  if ( $time !== false && $this->oldFileFactoryKey ) { // find-by-sha1 supported?
540  $img = call_user_func( $this->oldFileFactoryKey, $sha1, $this, $time );
541  if ( $img && $img->exists() ) {
542  if ( !$img->isDeleted( File::DELETED_FILE ) ) {
543  return $img; // always OK
544  } elseif ( !empty( $options['private'] ) &&
545  $img->userCan( File::DELETED_FILE,
546  $options['private'] instanceof User ? $options['private'] : null
547  )
548  ) {
549  return $img;
550  }
551  }
552  }
553 
554  return false;
555  }
556 
565  public function findBySha1( $hash ) {
566  return [];
567  }
568 
576  public function findBySha1s( array $hashes ) {
577  $result = [];
578  foreach ( $hashes as $hash ) {
579  $files = $this->findBySha1( $hash );
580  if ( count( $files ) ) {
581  $result[$hash] = $files;
582  }
583  }
584 
585  return $result;
586  }
587 
596  public function findFilesByPrefix( $prefix, $limit ) {
597  return [];
598  }
599 
605  public function getThumbScriptUrl() {
606  return $this->thumbScriptUrl;
607  }
608 
614  public function getThumbProxyUrl() {
615  return $this->thumbProxyUrl;
616  }
617 
623  public function getThumbProxySecret() {
625  }
626 
632  public function canTransformVia404() {
633  return $this->transformVia404;
634  }
635 
642  public function getNameFromTitle( Title $title ) {
643  if ( $this->initialCapital != MWNamespace::isCapitalized( NS_FILE ) ) {
644  $name = $title->getUserCaseDBKey();
645  if ( $this->initialCapital ) {
646  $name = MediaWikiServices::getInstance()->getContentLanguage()->ucfirst( $name );
647  }
648  } else {
649  $name = $title->getDBkey();
650  }
651 
652  return $name;
653  }
654 
660  public function getRootDirectory() {
661  return $this->getZonePath( 'public' );
662  }
663 
671  public function getHashPath( $name ) {
672  return self::getHashPathForLevel( $name, $this->hashLevels );
673  }
674 
682  public function getTempHashPath( $suffix ) {
683  $parts = explode( '!', $suffix, 2 ); // format is <timestamp>!<name> or just <name>
684  $name = $parts[1] ?? $suffix; // hash path is not based on timestamp
685  return self::getHashPathForLevel( $name, $this->hashLevels );
686  }
687 
693  protected static function getHashPathForLevel( $name, $levels ) {
694  if ( $levels == 0 ) {
695  return '';
696  } else {
697  $hash = md5( $name );
698  $path = '';
699  for ( $i = 1; $i <= $levels; $i++ ) {
700  $path .= substr( $hash, 0, $i ) . '/';
701  }
702 
703  return $path;
704  }
705  }
706 
712  public function getHashLevels() {
713  return $this->hashLevels;
714  }
715 
721  public function getName() {
722  return $this->name;
723  }
724 
732  public function makeUrl( $query = '', $entry = 'index' ) {
733  if ( isset( $this->scriptDirUrl ) ) {
734  return wfAppendQuery( "{$this->scriptDirUrl}/{$entry}.php", $query );
735  }
736 
737  return false;
738  }
739 
752  public function getDescriptionUrl( $name ) {
753  $encName = wfUrlencode( $name );
754  if ( !is_null( $this->descBaseUrl ) ) {
755  # "http://example.com/wiki/File:"
756  return $this->descBaseUrl . $encName;
757  }
758  if ( !is_null( $this->articleUrl ) ) {
759  # "http://example.com/wiki/$1"
760  # We use "Image:" as the canonical namespace for
761  # compatibility across all MediaWiki versions.
762  return str_replace( '$1',
763  "Image:$encName", $this->articleUrl );
764  }
765  if ( !is_null( $this->scriptDirUrl ) ) {
766  # "http://example.com/w"
767  # We use "Image:" as the canonical namespace for
768  # compatibility across all MediaWiki versions,
769  # and just sort of hope index.php is right. ;)
770  return $this->makeUrl( "title=Image:$encName" );
771  }
772 
773  return false;
774  }
775 
786  public function getDescriptionRenderUrl( $name, $lang = null ) {
787  $query = 'action=render';
788  if ( !is_null( $lang ) ) {
789  $query .= '&uselang=' . urlencode( $lang );
790  }
791  if ( isset( $this->scriptDirUrl ) ) {
792  return $this->makeUrl(
793  'title=' .
794  wfUrlencode( 'Image:' . $name ) .
795  "&$query" );
796  } else {
797  $descUrl = $this->getDescriptionUrl( $name );
798  if ( $descUrl ) {
799  return wfAppendQuery( $descUrl, $query );
800  } else {
801  return false;
802  }
803  }
804  }
805 
811  public function getDescriptionStylesheetUrl() {
812  if ( isset( $this->scriptDirUrl ) ) {
813  // Must match canonical query parameter order for optimum caching
814  // See Title::getCdnUrls
815  return $this->makeUrl( 'title=MediaWiki:Filepage.css&action=raw&ctype=text/css' );
816  }
817 
818  return false;
819  }
820 
834  public function store( $srcPath, $dstZone, $dstRel, $flags = 0 ) {
835  $this->assertWritableRepo(); // fail out if read-only
836 
837  $status = $this->storeBatch( [ [ $srcPath, $dstZone, $dstRel ] ], $flags );
838  if ( $status->successCount == 0 ) {
839  $status->setOK( false );
840  }
841 
842  return $status;
843  }
844 
857  public function storeBatch( array $triplets, $flags = 0 ) {
858  $this->assertWritableRepo(); // fail out if read-only
859 
860  if ( $flags & self::DELETE_SOURCE ) {
861  throw new InvalidArgumentException( "DELETE_SOURCE not supported in " . __METHOD__ );
862  }
863 
864  $status = $this->newGood();
865  $backend = $this->backend; // convenience
866 
867  $operations = [];
868  // Validate each triplet and get the store operation...
869  foreach ( $triplets as $triplet ) {
870  list( $srcPath, $dstZone, $dstRel ) = $triplet;
871  wfDebug( __METHOD__
872  . "( \$src='$srcPath', \$dstZone='$dstZone', \$dstRel='$dstRel' )\n"
873  );
874 
875  // Resolve destination path
876  $root = $this->getZonePath( $dstZone );
877  if ( !$root ) {
878  throw new MWException( "Invalid zone: $dstZone" );
879  }
880  if ( !$this->validateFilename( $dstRel ) ) {
881  throw new MWException( 'Validation error in $dstRel' );
882  }
883  $dstPath = "$root/$dstRel";
884  $dstDir = dirname( $dstPath );
885  // Create destination directories for this triplet
886  if ( !$this->initDirectory( $dstDir )->isOK() ) {
887  return $this->newFatal( 'directorycreateerror', $dstDir );
888  }
889 
890  // Resolve source to a storage path if virtual
891  $srcPath = $this->resolveToStoragePath( $srcPath );
892 
893  // Get the appropriate file operation
894  if ( FileBackend::isStoragePath( $srcPath ) ) {
895  $opName = 'copy';
896  } else {
897  $opName = 'store';
898  }
899  $operations[] = [
900  'op' => $opName,
901  'src' => $srcPath,
902  'dst' => $dstPath,
903  'overwrite' => $flags & self::OVERWRITE,
904  'overwriteSame' => $flags & self::OVERWRITE_SAME,
905  ];
906  }
907 
908  // Execute the store operation for each triplet
909  $opts = [ 'force' => true ];
910  if ( $flags & self::SKIP_LOCKING ) {
911  $opts['nonLocking'] = true;
912  }
913  $status->merge( $backend->doOperations( $operations, $opts ) );
914 
915  return $status;
916  }
917 
928  public function cleanupBatch( array $files, $flags = 0 ) {
929  $this->assertWritableRepo(); // fail out if read-only
930 
931  $status = $this->newGood();
932 
933  $operations = [];
934  foreach ( $files as $path ) {
935  if ( is_array( $path ) ) {
936  // This is a pair, extract it
937  list( $zone, $rel ) = $path;
938  $path = $this->getZonePath( $zone ) . "/$rel";
939  } else {
940  // Resolve source to a storage path if virtual
941  $path = $this->resolveToStoragePath( $path );
942  }
943  $operations[] = [ 'op' => 'delete', 'src' => $path ];
944  }
945  // Actually delete files from storage...
946  $opts = [ 'force' => true ];
947  if ( $flags & self::SKIP_LOCKING ) {
948  $opts['nonLocking'] = true;
949  }
950  $status->merge( $this->backend->doOperations( $operations, $opts ) );
951 
952  return $status;
953  }
954 
968  final public function quickImport( $src, $dst, $options = null ) {
969  return $this->quickImportBatch( [ [ $src, $dst, $options ] ] );
970  }
971 
980  final public function quickPurge( $path ) {
981  return $this->quickPurgeBatch( [ $path ] );
982  }
983 
991  public function quickCleanDir( $dir ) {
992  $status = $this->newGood();
993  $status->merge( $this->backend->clean(
994  [ 'dir' => $this->resolveToStoragePath( $dir ) ] ) );
995 
996  return $status;
997  }
998 
1011  public function quickImportBatch( array $triples ) {
1012  $status = $this->newGood();
1013  $operations = [];
1014  foreach ( $triples as $triple ) {
1015  list( $src, $dst ) = $triple;
1016  if ( $src instanceof FSFile ) {
1017  $op = 'store';
1018  } else {
1019  $src = $this->resolveToStoragePath( $src );
1020  $op = FileBackend::isStoragePath( $src ) ? 'copy' : 'store';
1021  }
1022  $dst = $this->resolveToStoragePath( $dst );
1023 
1024  if ( !isset( $triple[2] ) ) {
1025  $headers = [];
1026  } elseif ( is_string( $triple[2] ) ) {
1027  // back-compat
1028  $headers = [ 'Content-Disposition' => $triple[2] ];
1029  } elseif ( is_array( $triple[2] ) && isset( $triple[2]['headers'] ) ) {
1030  $headers = $triple[2]['headers'];
1031  } else {
1032  $headers = [];
1033  }
1034 
1035  $operations[] = [
1036  'op' => $op,
1037  'src' => $src,
1038  'dst' => $dst,
1039  'headers' => $headers
1040  ];
1041  $status->merge( $this->initDirectory( dirname( $dst ) ) );
1042  }
1043  $status->merge( $this->backend->doQuickOperations( $operations ) );
1044 
1045  return $status;
1046  }
1047 
1056  public function quickPurgeBatch( array $paths ) {
1057  $status = $this->newGood();
1058  $operations = [];
1059  foreach ( $paths as $path ) {
1060  $operations[] = [
1061  'op' => 'delete',
1062  'src' => $this->resolveToStoragePath( $path ),
1063  'ignoreMissingSource' => true
1064  ];
1065  }
1066  $status->merge( $this->backend->doQuickOperations( $operations ) );
1067 
1068  return $status;
1069  }
1070 
1081  public function storeTemp( $originalName, $srcPath ) {
1082  $this->assertWritableRepo(); // fail out if read-only
1083 
1084  $date = MWTimestamp::getInstance()->format( 'YmdHis' );
1085  $hashPath = $this->getHashPath( $originalName );
1086  $dstUrlRel = $hashPath . $date . '!' . rawurlencode( $originalName );
1087  $virtualUrl = $this->getVirtualUrl( 'temp' ) . '/' . $dstUrlRel;
1088 
1089  $result = $this->quickImport( $srcPath, $virtualUrl );
1090  $result->value = $virtualUrl;
1091 
1092  return $result;
1093  }
1094 
1101  public function freeTemp( $virtualUrl ) {
1102  $this->assertWritableRepo(); // fail out if read-only
1103 
1104  $temp = $this->getVirtualUrl( 'temp' );
1105  if ( substr( $virtualUrl, 0, strlen( $temp ) ) != $temp ) {
1106  wfDebug( __METHOD__ . ": Invalid temp virtual URL\n" );
1107 
1108  return false;
1109  }
1110 
1111  return $this->quickPurge( $virtualUrl )->isOK();
1112  }
1113 
1123  public function concatenate( array $srcPaths, $dstPath, $flags = 0 ) {
1124  $this->assertWritableRepo(); // fail out if read-only
1125 
1126  $status = $this->newGood();
1127 
1128  $sources = [];
1129  foreach ( $srcPaths as $srcPath ) {
1130  // Resolve source to a storage path if virtual
1131  $source = $this->resolveToStoragePath( $srcPath );
1132  $sources[] = $source; // chunk to merge
1133  }
1134 
1135  // Concatenate the chunks into one FS file
1136  $params = [ 'srcs' => $sources, 'dst' => $dstPath ];
1137  $status->merge( $this->backend->concatenate( $params ) );
1138  if ( !$status->isOK() ) {
1139  return $status;
1140  }
1141 
1142  // Delete the sources if required
1143  if ( $flags & self::DELETE_SOURCE ) {
1144  $status->merge( $this->quickPurgeBatch( $srcPaths ) );
1145  }
1146 
1147  // Make sure status is OK, despite any quickPurgeBatch() fatals
1148  $status->setResult( true );
1149 
1150  return $status;
1151  }
1152 
1172  public function publish(
1173  $src, $dstRel, $archiveRel, $flags = 0, array $options = []
1174  ) {
1175  $this->assertWritableRepo(); // fail out if read-only
1176 
1177  $status = $this->publishBatch(
1178  [ [ $src, $dstRel, $archiveRel, $options ] ], $flags );
1179  if ( $status->successCount == 0 ) {
1180  $status->setOK( false );
1181  }
1182  $status->value = $status->value[0] ?? false;
1183 
1184  return $status;
1185  }
1186 
1197  public function publishBatch( array $ntuples, $flags = 0 ) {
1198  $this->assertWritableRepo(); // fail out if read-only
1199 
1200  $backend = $this->backend; // convenience
1201  // Try creating directories
1202  $status = $this->initZones( 'public' );
1203  if ( !$status->isOK() ) {
1204  return $status;
1205  }
1206 
1207  $status = $this->newGood( [] );
1208 
1209  $operations = [];
1210  $sourceFSFilesToDelete = []; // cleanup for disk source files
1211  // Validate each triplet and get the store operation...
1212  foreach ( $ntuples as $ntuple ) {
1213  list( $src, $dstRel, $archiveRel ) = $ntuple;
1214  $srcPath = ( $src instanceof FSFile ) ? $src->getPath() : $src;
1215 
1216  $options = $ntuple[3] ?? [];
1217  // Resolve source to a storage path if virtual
1218  $srcPath = $this->resolveToStoragePath( $srcPath );
1219  if ( !$this->validateFilename( $dstRel ) ) {
1220  throw new MWException( 'Validation error in $dstRel' );
1221  }
1222  if ( !$this->validateFilename( $archiveRel ) ) {
1223  throw new MWException( 'Validation error in $archiveRel' );
1224  }
1225 
1226  $publicRoot = $this->getZonePath( 'public' );
1227  $dstPath = "$publicRoot/$dstRel";
1228  $archivePath = "$publicRoot/$archiveRel";
1229 
1230  $dstDir = dirname( $dstPath );
1231  $archiveDir = dirname( $archivePath );
1232  // Abort immediately on directory creation errors since they're likely to be repetitive
1233  if ( !$this->initDirectory( $dstDir )->isOK() ) {
1234  return $this->newFatal( 'directorycreateerror', $dstDir );
1235  }
1236  if ( !$this->initDirectory( $archiveDir )->isOK() ) {
1237  return $this->newFatal( 'directorycreateerror', $archiveDir );
1238  }
1239 
1240  // Set any desired headers to be use in GET/HEAD responses
1241  $headers = $options['headers'] ?? [];
1242 
1243  // Archive destination file if it exists.
1244  // This will check if the archive file also exists and fail if does.
1245  // This is a sanity check to avoid data loss. On Windows and Linux,
1246  // copy() will overwrite, so the existence check is vulnerable to
1247  // race conditions unless a functioning LockManager is used.
1248  // LocalFile also uses SELECT FOR UPDATE for synchronization.
1249  $operations[] = [
1250  'op' => 'copy',
1251  'src' => $dstPath,
1252  'dst' => $archivePath,
1253  'ignoreMissingSource' => true
1254  ];
1255 
1256  // Copy (or move) the source file to the destination
1257  if ( FileBackend::isStoragePath( $srcPath ) ) {
1258  if ( $flags & self::DELETE_SOURCE ) {
1259  $operations[] = [
1260  'op' => 'move',
1261  'src' => $srcPath,
1262  'dst' => $dstPath,
1263  'overwrite' => true, // replace current
1264  'headers' => $headers
1265  ];
1266  } else {
1267  $operations[] = [
1268  'op' => 'copy',
1269  'src' => $srcPath,
1270  'dst' => $dstPath,
1271  'overwrite' => true, // replace current
1272  'headers' => $headers
1273  ];
1274  }
1275  } else { // FS source path
1276  $operations[] = [
1277  'op' => 'store',
1278  'src' => $src, // prefer FSFile objects
1279  'dst' => $dstPath,
1280  'overwrite' => true, // replace current
1281  'headers' => $headers
1282  ];
1283  if ( $flags & self::DELETE_SOURCE ) {
1284  $sourceFSFilesToDelete[] = $srcPath;
1285  }
1286  }
1287  }
1288 
1289  // Execute the operations for each triplet
1290  $status->merge( $backend->doOperations( $operations ) );
1291  // Find out which files were archived...
1292  foreach ( $ntuples as $i => $ntuple ) {
1293  list( , , $archiveRel ) = $ntuple;
1294  $archivePath = $this->getZonePath( 'public' ) . "/$archiveRel";
1295  if ( $this->fileExists( $archivePath ) ) {
1296  $status->value[$i] = 'archived';
1297  } else {
1298  $status->value[$i] = 'new';
1299  }
1300  }
1301  // Cleanup for disk source files...
1302  foreach ( $sourceFSFilesToDelete as $file ) {
1303  Wikimedia\suppressWarnings();
1304  unlink( $file ); // FS cleanup
1305  Wikimedia\restoreWarnings();
1306  }
1307 
1308  return $status;
1309  }
1310 
1318  protected function initDirectory( $dir ) {
1319  $path = $this->resolveToStoragePath( $dir );
1320  list( , $container, ) = FileBackend::splitStoragePath( $path );
1321 
1322  $params = [ 'dir' => $path ];
1323  if ( $this->isPrivate
1324  || $container === $this->zones['deleted']['container']
1325  || $container === $this->zones['temp']['container']
1326  ) {
1327  # Take all available measures to prevent web accessibility of new deleted
1328  # directories, in case the user has not configured offline storage
1329  $params = [ 'noAccess' => true, 'noListing' => true ] + $params;
1330  }
1331 
1332  $status = $this->newGood();
1333  $status->merge( $this->backend->prepare( $params ) );
1334 
1335  return $status;
1336  }
1337 
1344  public function cleanDir( $dir ) {
1345  $this->assertWritableRepo(); // fail out if read-only
1346 
1347  $status = $this->newGood();
1348  $status->merge( $this->backend->clean(
1349  [ 'dir' => $this->resolveToStoragePath( $dir ) ] ) );
1350 
1351  return $status;
1352  }
1353 
1360  public function fileExists( $file ) {
1361  $result = $this->fileExistsBatch( [ $file ] );
1362 
1363  return $result[0];
1364  }
1365 
1372  public function fileExistsBatch( array $files ) {
1373  $paths = array_map( [ $this, 'resolveToStoragePath' ], $files );
1374  $this->backend->preloadFileStat( [ 'srcs' => $paths ] );
1375 
1376  $result = [];
1377  foreach ( $files as $key => $file ) {
1378  $path = $this->resolveToStoragePath( $file );
1379  $result[$key] = $this->backend->fileExists( [ 'src' => $path ] );
1380  }
1381 
1382  return $result;
1383  }
1384 
1395  public function delete( $srcRel, $archiveRel ) {
1396  $this->assertWritableRepo(); // fail out if read-only
1397 
1398  return $this->deleteBatch( [ [ $srcRel, $archiveRel ] ] );
1399  }
1400 
1418  public function deleteBatch( array $sourceDestPairs ) {
1419  $this->assertWritableRepo(); // fail out if read-only
1420 
1421  // Try creating directories
1422  $status = $this->initZones( [ 'public', 'deleted' ] );
1423  if ( !$status->isOK() ) {
1424  return $status;
1425  }
1426 
1427  $status = $this->newGood();
1428 
1429  $backend = $this->backend; // convenience
1430  $operations = [];
1431  // Validate filenames and create archive directories
1432  foreach ( $sourceDestPairs as $pair ) {
1433  list( $srcRel, $archiveRel ) = $pair;
1434  if ( !$this->validateFilename( $srcRel ) ) {
1435  throw new MWException( __METHOD__ . ':Validation error in $srcRel' );
1436  } elseif ( !$this->validateFilename( $archiveRel ) ) {
1437  throw new MWException( __METHOD__ . ':Validation error in $archiveRel' );
1438  }
1439 
1440  $publicRoot = $this->getZonePath( 'public' );
1441  $srcPath = "{$publicRoot}/$srcRel";
1442 
1443  $deletedRoot = $this->getZonePath( 'deleted' );
1444  $archivePath = "{$deletedRoot}/{$archiveRel}";
1445  $archiveDir = dirname( $archivePath ); // does not touch FS
1446 
1447  // Create destination directories
1448  if ( !$this->initDirectory( $archiveDir )->isOK() ) {
1449  return $this->newFatal( 'directorycreateerror', $archiveDir );
1450  }
1451 
1452  $operations[] = [
1453  'op' => 'move',
1454  'src' => $srcPath,
1455  'dst' => $archivePath,
1456  // We may have 2+ identical files being deleted,
1457  // all of which will map to the same destination file
1458  'overwriteSame' => true // also see T33792
1459  ];
1460  }
1461 
1462  // Move the files by execute the operations for each pair.
1463  // We're now committed to returning an OK result, which will
1464  // lead to the files being moved in the DB also.
1465  $opts = [ 'force' => true ];
1466  $status->merge( $backend->doOperations( $operations, $opts ) );
1467 
1468  return $status;
1469  }
1470 
1477  public function cleanupDeletedBatch( array $storageKeys ) {
1478  $this->assertWritableRepo();
1479  }
1480 
1489  public function getDeletedHashPath( $key ) {
1490  if ( strlen( $key ) < 31 ) {
1491  throw new MWException( "Invalid storage key '$key'." );
1492  }
1493  $path = '';
1494  for ( $i = 0; $i < $this->deletedHashLevels; $i++ ) {
1495  $path .= $key[$i] . '/';
1496  }
1497 
1498  return $path;
1499  }
1500 
1509  protected function resolveToStoragePath( $path ) {
1510  if ( $this->isVirtualUrl( $path ) ) {
1511  return $this->resolveVirtualUrl( $path );
1512  }
1513 
1514  return $path;
1515  }
1516 
1524  public function getLocalCopy( $virtualUrl ) {
1525  $path = $this->resolveToStoragePath( $virtualUrl );
1526 
1527  return $this->backend->getLocalCopy( [ 'src' => $path ] );
1528  }
1529 
1538  public function getLocalReference( $virtualUrl ) {
1539  $path = $this->resolveToStoragePath( $virtualUrl );
1540 
1541  return $this->backend->getLocalReference( [ 'src' => $path ] );
1542  }
1543 
1551  public function getFileProps( $virtualUrl ) {
1552  $fsFile = $this->getLocalReference( $virtualUrl );
1553  $mwProps = new MWFileProps( MediaWiki\MediaWikiServices::getInstance()->getMimeAnalyzer() );
1554  if ( $fsFile ) {
1555  $props = $mwProps->getPropsFromPath( $fsFile->getPath(), true );
1556  } else {
1557  $props = $mwProps->newPlaceholderProps();
1558  }
1559 
1560  return $props;
1561  }
1562 
1569  public function getFileTimestamp( $virtualUrl ) {
1570  $path = $this->resolveToStoragePath( $virtualUrl );
1571 
1572  return $this->backend->getFileTimestamp( [ 'src' => $path ] );
1573  }
1574 
1581  public function getFileSize( $virtualUrl ) {
1582  $path = $this->resolveToStoragePath( $virtualUrl );
1583 
1584  return $this->backend->getFileSize( [ 'src' => $path ] );
1585  }
1586 
1593  public function getFileSha1( $virtualUrl ) {
1594  $path = $this->resolveToStoragePath( $virtualUrl );
1595 
1596  return $this->backend->getFileSha1Base36( [ 'src' => $path ] );
1597  }
1598 
1608  public function streamFileWithStatus( $virtualUrl, $headers = [], $optHeaders = [] ) {
1609  $path = $this->resolveToStoragePath( $virtualUrl );
1610  $params = [ 'src' => $path, 'headers' => $headers, 'options' => $optHeaders ];
1611 
1612  // T172851: HHVM does not flush the output properly, causing OOM
1613  ob_start( null, 1048576 );
1614  ob_implicit_flush( true );
1615 
1616  $status = $this->newGood();
1617  $status->merge( $this->backend->streamFile( $params ) );
1618 
1619  // T186565: Close the buffer, unless it has already been closed
1620  // in HTTPFileStreamer::resetOutputBuffers().
1621  if ( ob_get_status() ) {
1622  ob_end_flush();
1623  }
1624 
1625  return $status;
1626  }
1627 
1636  public function streamFile( $virtualUrl, $headers = [] ) {
1637  return $this->streamFileWithStatus( $virtualUrl, $headers )->isOK();
1638  }
1639 
1648  public function enumFiles( $callback ) {
1649  $this->enumFilesInStorage( $callback );
1650  }
1651 
1659  protected function enumFilesInStorage( $callback ) {
1660  $publicRoot = $this->getZonePath( 'public' );
1661  $numDirs = 1 << ( $this->hashLevels * 4 );
1662  // Use a priori assumptions about directory structure
1663  // to reduce the tree height of the scanning process.
1664  for ( $flatIndex = 0; $flatIndex < $numDirs; $flatIndex++ ) {
1665  $hexString = sprintf( "%0{$this->hashLevels}x", $flatIndex );
1666  $path = $publicRoot;
1667  for ( $hexPos = 0; $hexPos < $this->hashLevels; $hexPos++ ) {
1668  $path .= '/' . substr( $hexString, 0, $hexPos + 1 );
1669  }
1670  $iterator = $this->backend->getFileList( [ 'dir' => $path ] );
1671  foreach ( $iterator as $name ) {
1672  // Each item returned is a public file
1673  call_user_func( $callback, "{$path}/{$name}" );
1674  }
1675  }
1676  }
1677 
1684  public function validateFilename( $filename ) {
1685  if ( strval( $filename ) == '' ) {
1686  return false;
1687  }
1688 
1689  return FileBackend::isPathTraversalFree( $filename );
1690  }
1691 
1698  switch ( $this->pathDisclosureProtection ) {
1699  case 'none':
1700  case 'simple': // b/c
1701  $callback = [ $this, 'passThrough' ];
1702  break;
1703  default: // 'paranoid'
1704  $callback = [ $this, 'paranoidClean' ];
1705  }
1706  return $callback;
1707  }
1708 
1715  function paranoidClean( $param ) {
1716  return '[hidden]';
1717  }
1718 
1725  function passThrough( $param ) {
1726  return $param;
1727  }
1728 
1735  public function newFatal( $message /*, parameters...*/ ) {
1736  $status = Status::newFatal( ...func_get_args() );
1737  $status->cleanCallback = $this->getErrorCleanupFunction();
1738 
1739  return $status;
1740  }
1741 
1748  public function newGood( $value = null ) {
1750  $status->cleanCallback = $this->getErrorCleanupFunction();
1751 
1752  return $status;
1753  }
1754 
1763  public function checkRedirect( Title $title ) {
1764  return false;
1765  }
1766 
1774  public function invalidateImageRedirect( Title $title ) {
1775  }
1776 
1782  public function getDisplayName() {
1783  global $wgSitename;
1784 
1785  if ( $this->isLocal() ) {
1786  return $wgSitename;
1787  }
1788 
1789  // 'shared-repo-name-wikimediacommons' is used when $wgUseInstantCommons = true
1790  return wfMessageFallback( 'shared-repo-name-' . $this->name, 'shared-repo' )->text();
1791  }
1792 
1800  public function nameForThumb( $name ) {
1801  if ( strlen( $name ) > $this->abbrvThreshold ) {
1803  $name = ( $ext == '' ) ? 'thumbnail' : "thumbnail.$ext";
1804  }
1805 
1806  return $name;
1807  }
1808 
1814  public function isLocal() {
1815  return $this->getName() == 'local';
1816  }
1817 
1826  public function getSharedCacheKey( /*...*/ ) {
1827  return false;
1828  }
1829 
1837  public function getLocalCacheKey( /*...*/ ) {
1838  $args = func_get_args();
1839  array_unshift( $args, 'filerepo', $this->getName() );
1840 
1841  return wfMemcKey( ...$args );
1842  }
1843 
1852  public function getTempRepo() {
1853  return new TempFileRepo( [
1854  'name' => "{$this->name}-temp",
1855  'backend' => $this->backend,
1856  'zones' => [
1857  'public' => [
1858  // Same place storeTemp() uses in the base repo, though
1859  // the path hashing is mismatched, which is annoying.
1860  'container' => $this->zones['temp']['container'],
1861  'directory' => $this->zones['temp']['directory']
1862  ],
1863  'thumb' => [
1864  'container' => $this->zones['temp']['container'],
1865  'directory' => $this->zones['temp']['directory'] == ''
1866  ? 'thumb'
1867  : $this->zones['temp']['directory'] . '/thumb'
1868  ],
1869  'transcoded' => [
1870  'container' => $this->zones['temp']['container'],
1871  'directory' => $this->zones['temp']['directory'] == ''
1872  ? 'transcoded'
1873  : $this->zones['temp']['directory'] . '/transcoded'
1874  ]
1875  ],
1876  'hashLevels' => $this->hashLevels, // performance
1877  'isPrivate' => true // all in temp zone
1878  ] );
1879  }
1880 
1887  public function getUploadStash( User $user = null ) {
1888  return new UploadStash( $this, $user );
1889  }
1890 
1898  protected function assertWritableRepo() {
1899  }
1900 
1907  public function getInfo() {
1908  $ret = [
1909  'name' => $this->getName(),
1910  'displayname' => $this->getDisplayName(),
1911  'rootUrl' => $this->getZoneUrl( 'public' ),
1912  'local' => $this->isLocal(),
1913  ];
1914 
1915  $optionalSettings = [
1916  'url', 'thumbUrl', 'initialCapital', 'descBaseUrl', 'scriptDirUrl', 'articleUrl',
1917  'fetchDescription', 'descriptionCacheExpiry', 'favicon'
1918  ];
1919  foreach ( $optionalSettings as $k ) {
1920  if ( isset( $this->$k ) ) {
1921  $ret[$k] = $this->$k;
1922  }
1923  }
1924 
1925  return $ret;
1926  }
1927 
1932  public function hasSha1Storage() {
1933  return $this->hasSha1Storage;
1934  }
1935 
1940  public function supportsSha1URLs() {
1941  return $this->supportsSha1URLs;
1942  }
1943 }
FileBackend\splitStoragePath
static splitStoragePath( $storagePath)
Split a storage path into a backend name, a container name, and a relative file path.
Definition: FileBackend.php:1440
$status
Status::newGood()` to allow deletion, and then `return false` from the hook function. Ensure you consume the 'ChangeTagAfterDelete' hook to carry out custom deletion actions. $tag:name of the tag $user:user initiating the action & $status:Status object. See above. 'ChangeTagsListActive':Allows you to nominate which of the tags your extension uses are in active use. & $tags:list of all active tags. Append to this array. 'ChangeTagsAfterUpdateTags':Called after tags have been updated with the ChangeTags::updateTags function. Params:$addedTags:tags effectively added in the update $removedTags:tags effectively removed in the update $prevTags:tags that were present prior to the update $rc_id:recentchanges table id $rev_id:revision table id $log_id:logging table id $params:tag params $rc:RecentChange being tagged when the tagging accompanies the action, or null $user:User who performed the tagging when the tagging is subsequent to the action, or null 'ChangeTagsAllowedAdd':Called when checking if a user can add tags to a change. & $allowedTags:List of all the tags the user is allowed to add. Any tags the user wants to add( $addTags) that are not in this array will cause it to fail. You may add or remove tags to this array as required. $addTags:List of tags user intends to add. $user:User who is adding the tags. 'ChangeUserGroups':Called before user groups are changed. $performer:The User who will perform the change $user:The User whose groups will be changed & $add:The groups that will be added & $remove:The groups that will be removed 'Collation::factory':Called if $wgCategoryCollation is an unknown collation. $collationName:Name of the collation in question & $collationObject:Null. Replace with a subclass of the Collation class that implements the collation given in $collationName. 'ConfirmEmailComplete':Called after a user 's email has been confirmed successfully. $user:user(object) whose email is being confirmed 'ContentAlterParserOutput':Modify parser output for a given content object. Called by Content::getParserOutput after parsing has finished. Can be used for changes that depend on the result of the parsing but have to be done before LinksUpdate is called(such as adding tracking categories based on the rendered HTML). $content:The Content to render $title:Title of the page, as context $parserOutput:ParserOutput to manipulate 'ContentGetParserOutput':Customize parser output for a given content object, called by AbstractContent::getParserOutput. May be used to override the normal model-specific rendering of page content. $content:The Content to render $title:Title of the page, as context $revId:The revision ID, as context $options:ParserOptions for rendering. To avoid confusing the parser cache, the output can only depend on parameters provided to this hook function, not on global state. $generateHtml:boolean, indicating whether full HTML should be generated. If false, generation of HTML may be skipped, but other information should still be present in the ParserOutput object. & $output:ParserOutput, to manipulate or replace 'ContentHandlerDefaultModelFor':Called when the default content model is determined for a given title. May be used to assign a different model for that title. $title:the Title in question & $model:the model name. Use with CONTENT_MODEL_XXX constants. 'ContentHandlerForModelID':Called when a ContentHandler is requested for a given content model name, but no entry for that model exists in $wgContentHandlers. Note:if your extension implements additional models via this hook, please use GetContentModels hook to make them known to core. $modeName:the requested content model name & $handler:set this to a ContentHandler object, if desired. 'ContentModelCanBeUsedOn':Called to determine whether that content model can be used on a given page. This is especially useful to prevent some content models to be used in some special location. $contentModel:ID of the content model in question $title:the Title in question. & $ok:Output parameter, whether it is OK to use $contentModel on $title. Handler functions that modify $ok should generally return false to prevent further hooks from further modifying $ok. 'ContribsPager::getQueryInfo':Before the contributions query is about to run & $pager:Pager object for contributions & $queryInfo:The query for the contribs Pager 'ContribsPager::reallyDoQuery':Called before really executing the query for My Contributions & $data:an array of results of all contribs queries $pager:The ContribsPager object hooked into $offset:Index offset, inclusive $limit:Exact query limit $descending:Query direction, false for ascending, true for descending 'ContributionsLineEnding':Called before a contributions HTML line is finished $page:SpecialPage object for contributions & $ret:the HTML line $row:the DB row for this line & $classes:the classes to add to the surrounding< li > & $attribs:associative array of other HTML attributes for the< li > element. Currently only data attributes reserved to MediaWiki are allowed(see Sanitizer::isReservedDataAttribute). 'ContributionsToolLinks':Change tool links above Special:Contributions $id:User identifier $title:User page title & $tools:Array of tool links $specialPage:SpecialPage instance for context and services. Can be either SpecialContributions or DeletedContributionsPage. Extensions should type hint against a generic SpecialPage though. 'ConvertContent':Called by AbstractContent::convert when a conversion to another content model is requested. Handler functions that modify $result should generally return false to disable further attempts at conversion. $content:The Content object to be converted. $toModel:The ID of the content model to convert to. $lossy:boolean indicating whether lossy conversion is allowed. & $result:Output parameter, in case the handler function wants to provide a converted Content object. Note that $result->getContentModel() must return $toModel. 'ContentSecurityPolicyDefaultSource':Modify the allowed CSP load sources. This affects all directives except for the script directive. If you want to add a script source, see ContentSecurityPolicyScriptSource hook. & $defaultSrc:Array of Content-Security-Policy allowed sources $policyConfig:Current configuration for the Content-Security-Policy header $mode:ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE depending on type of header 'ContentSecurityPolicyDirectives':Modify the content security policy directives. Use this only if ContentSecurityPolicyDefaultSource and ContentSecurityPolicyScriptSource do not meet your needs. & $directives:Array of CSP directives $policyConfig:Current configuration for the CSP header $mode:ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE depending on type of header 'ContentSecurityPolicyScriptSource':Modify the allowed CSP script sources. Note that you also have to use ContentSecurityPolicyDefaultSource if you want non-script sources to be loaded from whatever you add. & $scriptSrc:Array of CSP directives $policyConfig:Current configuration for the CSP header $mode:ContentSecurityPolicy::REPORT_ONLY_MODE or ContentSecurityPolicy::FULL_MODE depending on type of header 'CustomEditor':When invoking the page editor Return true to allow the normal editor to be used, or false if implementing a custom editor, e.g. for a special namespace, etc. $article:Article being edited $user:User performing the edit 'DatabaseOraclePostInit':Called after initialising an Oracle database $db:the DatabaseOracle object 'DeletedContribsPager::reallyDoQuery':Called before really executing the query for Special:DeletedContributions Similar to ContribsPager::reallyDoQuery & $data:an array of results of all contribs queries $pager:The DeletedContribsPager object hooked into $offset:Index offset, inclusive $limit:Exact query limit $descending:Query direction, false for ascending, true for descending 'DeletedContributionsLineEnding':Called before a DeletedContributions HTML line is finished. Similar to ContributionsLineEnding $page:SpecialPage object for DeletedContributions & $ret:the HTML line $row:the DB row for this line & $classes:the classes to add to the surrounding< li > & $attribs:associative array of other HTML attributes for the< li > element. Currently only data attributes reserved to MediaWiki are allowed(see Sanitizer::isReservedDataAttribute). 'DeleteUnknownPreferences':Called by the cleanupPreferences.php maintenance script to build a WHERE clause with which to delete preferences that are not known about. This hook is used by extensions that have dynamically-named preferences that should not be deleted in the usual cleanup process. For example, the Gadgets extension creates preferences prefixed with 'gadget-', and so anything with that prefix is excluded from the deletion. &where:An array that will be passed as the $cond parameter to IDatabase::select() to determine what will be deleted from the user_properties table. $db:The IDatabase object, useful for accessing $db->buildLike() etc. 'DifferenceEngineAfterLoadNewText':called in DifferenceEngine::loadNewText() after the new revision 's content has been loaded into the class member variable $differenceEngine->mNewContent but before returning true from this function. $differenceEngine:DifferenceEngine object 'DifferenceEngineLoadTextAfterNewContentIsLoaded':called in DifferenceEngine::loadText() after the new revision 's content has been loaded into the class member variable $differenceEngine->mNewContent but before checking if the variable 's value is null. This hook can be used to inject content into said class member variable. $differenceEngine:DifferenceEngine object 'DifferenceEngineMarkPatrolledLink':Allows extensions to change the "mark as patrolled" link which is shown both on the diff header as well as on the bottom of a page, usually wrapped in a span element which has class="patrollink". $differenceEngine:DifferenceEngine object & $markAsPatrolledLink:The "mark as patrolled" link HTML(string) $rcid:Recent change ID(rc_id) for this change(int) 'DifferenceEngineMarkPatrolledRCID':Allows extensions to possibly change the rcid parameter. For example the rcid might be set to zero due to the user being the same as the performer of the change but an extension might still want to show it under certain conditions. & $rcid:rc_id(int) of the change or 0 $differenceEngine:DifferenceEngine object $change:RecentChange object $user:User object representing the current user 'DifferenceEngineNewHeader':Allows extensions to change the $newHeader variable, which contains information about the new revision, such as the revision 's author, whether the revision was marked as a minor edit or not, etc. $differenceEngine:DifferenceEngine object & $newHeader:The string containing the various #mw-diff-otitle[1-5] divs, which include things like revision author info, revision comment, RevisionDelete link and more $formattedRevisionTools:Array containing revision tools, some of which may have been injected with the DiffRevisionTools hook $nextlink:String containing the link to the next revision(if any) $status
Definition: hooks.txt:1305
FileBackend\doOperations
doOperations(array $ops, array $opts=[])
This is the main entry point into the backend for write operations.
Definition: FileBackend.php:416
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:244
FileRepo\getReadOnlyReason
getReadOnlyReason()
Get an explanatory message if this repo is read-only.
Definition: FileRepo.php:220
FileRepo\$supportsSha1URLs
bool $supportsSha1URLs
Definition: FileRepo.php:58
FileRepo\initZones
initZones( $doZones=[])
Check if a single zone or list of zones is defined for usage.
Definition: FileRepo.php:231
wfMessageFallback
wfMessageFallback(... $keys)
This function accepts multiple message keys and returns a message instance for the first message whic...
Definition: GlobalFunctions.php:1353
FileRepo\$hasSha1Storage
bool $hasSha1Storage
Definition: FileRepo.php:55
FileRepo\passThrough
passThrough( $param)
Path disclosure protection function.
Definition: FileRepo.php:1725
FileRepo\findBySha1
findBySha1( $hash)
Get an array or iterator of file objects for files that have a given SHA-1 content hash.
Definition: FileRepo.php:565
FileRepo\getThumbScriptUrl
getThumbScriptUrl()
Get the URL of thumb.php.
Definition: FileRepo.php:605
FileRepo\newGood
newGood( $value=null)
Create a new good result.
Definition: FileRepo.php:1748
FileRepo\getDescriptionRenderUrl
getDescriptionRenderUrl( $name, $lang=null)
Get the URL of the content-only fragment of the description page.
Definition: FileRepo.php:786
FileBackend
Base class for all file backend classes (including multi-write backends).
Definition: FileBackend.php:92
FileRepo\$deletedHashLevels
int $deletedHashLevels
The number of directory levels for hash-based division of deleted files.
Definition: FileRepo.php:110
FileRepo\enumFilesInStorage
enumFilesInStorage( $callback)
Call a callback function for every public file in the repository.
Definition: FileRepo.php:1659
FileRepo\$favicon
string $favicon
The URL of the repo's favicon, if any.
Definition: FileRepo.php:119
FileRepo\OVERWRITE_SAME
const OVERWRITE_SAME
Definition: FileRepo.php:42
FileRepo\$isPrivate
bool $isPrivate
Whether all zones should be private (e.g.
Definition: FileRepo.php:122
FileRepo\validateFilename
validateFilename( $filename)
Determine if a relative path is valid, i.e.
Definition: FileRepo.php:1684
FileRepo\getRootDirectory
getRootDirectory()
Get the public zone root storage directory of the repository.
Definition: FileRepo.php:660
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
FileRepo\OVERWRITE
const OVERWRITE
Definition: FileRepo.php:41
FileRepo\getVirtualUrl
getVirtualUrl( $suffix=false)
Get a URL referring to this repository, with the private mwrepo protocol.
Definition: FileRepo.php:261
FileRepo\makeUrl
makeUrl( $query='', $entry='index')
Make an url to this repo.
Definition: FileRepo.php:732
captcha-old.count
count
Definition: captcha-old.py:249
FileRepo\storeBatch
storeBatch(array $triplets, $flags=0)
Store a batch of files.
Definition: FileRepo.php:857
FileRepo\$pathDisclosureProtection
string $pathDisclosureProtection
May be 'paranoid' to remove all parameters from error messages, 'none' to leave the paths in unchange...
Definition: FileRepo.php:98
FileRepo\streamFile
streamFile( $virtualUrl, $headers=[])
Attempt to stream a file with the given virtual URL/storage path.
Definition: FileRepo.php:1636
FileRepo\streamFileWithStatus
streamFileWithStatus( $virtualUrl, $headers=[], $optHeaders=[])
Attempt to stream a file with the given virtual URL/storage path.
Definition: FileRepo.php:1608
$result
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. Return false to stop further processing of the tag $reader:XMLReader object $logInfo:Array of information 'ImportHandlePageXMLTag':When parsing a XML tag in a page. Return false to stop further processing of the tag $reader:XMLReader object & $pageInfo:Array of information 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. Return false to stop further processing of the tag $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. Return false to stop further processing of the tag $reader:XMLReader object 'ImportHandleUnknownUser':When a user doesn 't exist locally, this hook is called to give extensions an opportunity to auto-create it. If the auto-creation is successful, return false. $name:User name 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. Return false to stop further processing of the tag $reader:XMLReader object $revisionInfo:Array of information 'ImportLogInterwikiLink':Hook to change the interwiki link used in log entries and edit summaries for transwiki imports. & $fullInterwikiPrefix:Interwiki prefix, may contain colons. & $pageTitle:String that contains page title. 'ImportSources':Called when reading from the $wgImportSources configuration variable. Can be used to lazy-load the import sources list. & $importSources:The value of $wgImportSources. Modify as necessary. See the comment in DefaultSettings.php for the detail of how to structure this array. 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. & $title:Title object for the current page & $request:WebRequest & $ignoreRedirect:boolean to skip redirect check & $target:Title/string of redirect target & $article:Article object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) & $article:article(object) being checked 'IsTrustedProxy':Override the result of IP::isTrustedProxy() & $ip:IP being check & $result:Change this value to override the result of IP::isTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of Sanitizer::validateEmail(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetMagic':DEPRECATED since 1.16! Use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language & $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetSpecialPageAliases':DEPRECATED! Use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language & $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code:language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Array with elements of the form "language:title" in the order that they will be output. & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LanguageSelector':Hook to change the language selector available on a page. $out:The output page. $cssClassName:CSS class name of the language selector. 'LinkBegin':DEPRECATED since 1.28! Use HtmlPageLinkRendererBegin instead. Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition: hooks.txt:2034
FileRepo\getTempRepo
getTempRepo()
Get a temporary private FileRepo associated with this repo.
Definition: FileRepo.php:1852
FileRepo\getInfo
getInfo()
Return information about the repository.
Definition: FileRepo.php:1907
UploadStash
UploadStash is intended to accomplish a few things:
Definition: UploadStash.php:53
FileRepo\$descriptionCacheExpiry
int $descriptionCacheExpiry
Definition: FileRepo.php:52
FileRepo\getName
getName()
Get the name of this repository, as specified by $info['name]' to the constructor.
Definition: FileRepo.php:721
FileRepo\$thumbUrl
string $thumbUrl
The base thumbnail URL.
Definition: FileRepo.php:104
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:331
FileRepo\quickImportBatch
quickImportBatch(array $triples)
Import a batch of files from the local file system into the repo.
Definition: FileRepo.php:1011
FileBackend\extensionFromPath
static extensionFromPath( $path, $case='lowercase')
Get the final extension from a storage or FS path.
Definition: FileBackend.php:1499
StatusValue\newFatal
static newFatal( $message)
Factory function for fatal errors.
Definition: StatusValue.php:68
NS_FILE
const NS_FILE
Definition: Defines.php:70
FileRepo\getHashPathForLevel
static getHashPathForLevel( $name, $levels)
Definition: FileRepo.php:693
$params
$params
Definition: styleTest.css.php:44
FileRepo\getZoneUrl
getZoneUrl( $zone, $ext=null)
Get the URL corresponding to one of the four basic zones.
Definition: FileRepo.php:277
FileRepo\getZonePath
getZonePath( $zone)
Get the storage path corresponding to one of the zones.
Definition: FileRepo.php:358
FileRepo\getLocalReference
getLocalReference( $virtualUrl)
Get a local FS file with a given virtual URL/storage path.
Definition: FileRepo.php:1538
FileRepo\getZoneLocation
getZoneLocation( $zone)
The the storage container and base path of a zone.
Definition: FileRepo.php:344
FileRepo\resolveToStoragePath
resolveToStoragePath( $path)
If a path is a virtual URL, resolve it to a storage path.
Definition: FileRepo.php:1509
FileRepo\$backend
FileBackend $backend
Definition: FileRepo.php:61
FileRepo\$fileFactory
array $fileFactory
callable Override these in the base class
Definition: FileRepo.php:125
$base
$base
Definition: generateLocalAutoload.php:11
FileRepo\$initialCapital
bool $initialCapital
Equivalent to $wgCapitalLinks (or $wgCapitalLinkOverrides[NS_FILE], determines whether filenames impl...
Definition: FileRepo.php:91
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:184
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
FileBackendGroup\singleton
static singleton()
Definition: FileBackendGroup.php:46
FileRepo\publish
publish( $src, $dstRel, $archiveRel, $flags=0, array $options=[])
Copy or move a file either from a storage path, virtual URL, or file system path, into this repositor...
Definition: FileRepo.php:1172
FileRepo\getDescriptionStylesheetUrl
getDescriptionStylesheetUrl()
Get the URL of the stylesheet to apply to description pages.
Definition: FileRepo.php:811
FileRepo\fileExistsBatch
fileExistsBatch(array $files)
Checks existence of an array of files.
Definition: FileRepo.php:1372
FileRepo
Base class for file repositories.
Definition: FileRepo.php:39
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:460
FileRepo\getSharedCacheKey
getSharedCacheKey()
Get a key on the primary cache for this repository.
Definition: FileRepo.php:1826
FileRepo\freeTemp
freeTemp( $virtualUrl)
Remove a temporary file or mark it for garbage collection.
Definition: FileRepo.php:1101
$query
null for the wiki Added should default to null in handler for backwards compatibility add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition: hooks.txt:1627
name
and how to run hooks for an and one after Each event has a name
Definition: hooks.txt:6
FileRepo\findFiles
findFiles(array $items, $flags=0)
Find many files at once.
Definition: FileRepo.php:491
FileRepo\quickPurge
quickPurge( $path)
Purge a file from the repo.
Definition: FileRepo.php:980
FileRepo\hasSha1Storage
hasSha1Storage()
Returns whether or not storage is SHA-1 based.
Definition: FileRepo.php:1932
FileRepo\findFileFromKey
findFileFromKey( $sha1, $options=[])
Find an instance of the file with this key, created at the specified time Returns false if the file d...
Definition: FileRepo.php:528
FileRepo\newFile
newFile( $title, $time=false)
Create a new File object from the local repository.
Definition: FileRepo.php:382
MWException
MediaWiki exception.
Definition: MWException.php:26
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:964
FileRepo\enumFiles
enumFiles( $callback)
Call a callback function for every public regular file in the repository.
Definition: FileRepo.php:1648
FileRepo\checkRedirect
checkRedirect(Title $title)
Checks if there is a redirect named as $title.
Definition: FileRepo.php:1763
FileRepo\quickImport
quickImport( $src, $dst, $options=null)
Import a file from the local file system into the repo.
Definition: FileRepo.php:968
FileBackend\isStoragePath
static isStoragePath( $path)
Check if a given path is a "mwstore://" path.
Definition: FileBackend.php:1428
FileRepo\getUploadStash
getUploadStash(User $user=null)
Get an UploadStash associated with this repo.
Definition: FileRepo.php:1887
FileRepo\$thumbScriptUrl
string $thumbScriptUrl
URL of thumb.php.
Definition: FileRepo.php:67
FileRepo\findFilesByPrefix
findFilesByPrefix( $prefix, $limit)
Return an array of files where the name starts with $prefix.
Definition: FileRepo.php:596
FileRepo\$zones
array $zones
Map of zones to config.
Definition: FileRepo.php:64
FileRepo\paranoidClean
paranoidClean( $param)
Path disclosure protection function.
Definition: FileRepo.php:1715
MediaWiki
A helper class for throttling authentication attempts.
FileRepo\$oldFileFactory
array $oldFileFactory
callable|bool Override these in the base class
Definition: FileRepo.php:127
FileBackend\ATTR_UNICODE_PATHS
const ATTR_UNICODE_PATHS
Definition: FileBackend.php:130
FileRepo\getDescriptionUrl
getDescriptionUrl( $name)
Get the URL of an image description page.
Definition: FileRepo.php:752
FileRepo\getThumbProxySecret
getThumbProxySecret()
Get the secret key for the proxied thumb service.
Definition: FileRepo.php:623
FileRepo\store
store( $srcPath, $dstZone, $dstRel, $flags=0)
Store a file to a given destination.
Definition: FileRepo.php:834
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
FileRepo\$fileFactoryKey
array $fileFactoryKey
callable|bool Override these in the base class
Definition: FileRepo.php:129
MWTimestamp\getInstance
static getInstance( $ts=false)
Get a timestamp instance in GMT.
Definition: MWTimestamp.php:39
MWFileProps
MimeMagic helper wrapper.
Definition: MWFileProps.php:28
FileRepo\nameForThumb
nameForThumb( $name)
Get the portion of the file that contains the origin file name.
Definition: FileRepo.php:1800
$time
see documentation in includes Linker php for Linker::makeImageLink & $time
Definition: hooks.txt:1841
FileRepo\invalidateImageRedirect
invalidateImageRedirect(Title $title)
Invalidates image redirect cache related to that image Doesn't do anything for repositories that don'...
Definition: FileRepo.php:1774
FileRepo\getThumbProxyUrl
getThumbProxyUrl()
Get the URL thumb.php requests are being proxied to.
Definition: FileRepo.php:614
FileRepo\getLocalCopy
getLocalCopy( $virtualUrl)
Get a local FS copy of a file with a given virtual URL/storage path.
Definition: FileRepo.php:1524
TempFileRepo
FileRepo for temporary files created via FileRepo::getTempRepo()
Definition: TempFileRepo.php:5
FileRepo\cleanupBatch
cleanupBatch(array $files, $flags=0)
Deletes a batch of files.
Definition: FileRepo.php:928
array
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))
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:988
FileRepo\fileExists
fileExists( $file)
Checks existence of a file.
Definition: FileRepo.php:1360
FileRepo\getFileSha1
getFileSha1( $virtualUrl)
Get the sha1 (base 36) of a file with a given virtual URL/storage path.
Definition: FileRepo.php:1593
FileRepo\backendSupportsUnicodePaths
backendSupportsUnicodePaths()
Definition: FileRepo.php:306
list
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
FileRepo\getNameFromTitle
getNameFromTitle(Title $title)
Get the name of a file from its title object.
Definition: FileRepo.php:642
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:302
FileRepo\getDisplayName
getDisplayName()
Get the human-readable name of the repo.
Definition: FileRepo.php:1782
FileRepo\findFile
findFile( $title, $options=[])
Find an instance of the named file created at the specified time Returns false if the file does not e...
Definition: FileRepo.php:415
$value
$value
Definition: styleTest.css.php:49
FileRepo\SKIP_LOCKING
const SKIP_LOCKING
Definition: FileRepo.php:43
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
FileRepo\storeTemp
storeTemp( $originalName, $srcPath)
Pick a random name in the temp zone and store a file to it.
Definition: FileRepo.php:1081
FileRepo\newFatal
newFatal( $message)
Create a new fatal error.
Definition: FileRepo.php:1735
FileRepo\publishBatch
publishBatch(array $ntuples, $flags=0)
Publish a batch of files.
Definition: FileRepo.php:1197
$wgSitename
$wgSitename
Name of the site.
Definition: DefaultSettings.php:79
$ret
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
Definition: hooks.txt:2036
FileRepo\$scriptDirUrl
string $scriptDirUrl
URL of the MediaWiki installation, equivalent to $wgScriptPath, e.g.
Definition: FileRepo.php:81
FileRepo\$articleUrl
string $articleUrl
Equivalent to $wgArticlePath, e.g.
Definition: FileRepo.php:84
FileRepo\getHashLevels
getHashLevels()
Get the number of hash directory levels.
Definition: FileRepo.php:712
FileRepo\initDirectory
initDirectory( $dir)
Creates a directory with the appropriate zone permissions.
Definition: FileRepo.php:1318
FSFile
Class representing a non-directory file on the file system.
Definition: FSFile.php:29
FileRepo\getBackend
getBackend()
Get the file backend instance.
Definition: FileRepo.php:210
FileRepo\quickPurgeBatch
quickPurgeBatch(array $paths)
Purge a batch of files from the repo.
Definition: FileRepo.php:1056
FileRepo\getLocalCacheKey
getLocalCacheKey()
Get a key for this repo in the local cache domain.
Definition: FileRepo.php:1837
FileRepo\getFileSize
getFileSize( $virtualUrl)
Get the size of a file with a given virtual URL/storage path.
Definition: FileRepo.php:1581
FileRepo\isLocal
isLocal()
Returns true if this the local file repository.
Definition: FileRepo.php:1814
FileRepo\$thumbProxySecret
string $thumbProxySecret
Secret key to pass as an X-Swift-Secret header to the proxied thumb service.
Definition: FileRepo.php:138
FileRepo\getHashPath
getHashPath( $name)
Get a relative path including trailing slash, e.g.
Definition: FileRepo.php:671
$args
if( $line===false) $args
Definition: cdb.php:64
FileRepo\getErrorCleanupFunction
getErrorCleanupFunction()
Get a callback function to use for cleaning error message parameters.
Definition: FileRepo.php:1697
Title
Represents a title within MediaWiki.
Definition: Title.php:39
FileRepo\__construct
__construct(array $info=null)
Definition: FileRepo.php:144
FileRepo\findBySha1s
findBySha1s(array $hashes)
Get an array of arrays or iterators of file objects for files that have the given SHA-1 content hashe...
Definition: FileRepo.php:576
$options
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition: hooks.txt:2036
FileRepo\getTempHashPath
getTempHashPath( $suffix)
Get a relative path including trailing slash, e.g.
Definition: FileRepo.php:682
FileRepo\$descBaseUrl
string $descBaseUrl
URL of image description pages, e.g.
Definition: FileRepo.php:76
$path
$path
Definition: NoLocalSettings.php:25
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
FileRepo\quickCleanDir
quickCleanDir( $dir)
Deletes a directory if empty.
Definition: FileRepo.php:991
FileRepo\isVirtualUrl
static isVirtualUrl( $url)
Determine if a string is an mwrepo:// URL.
Definition: FileRepo.php:249
MWNamespace\isCapitalized
static isCapitalized( $index)
Is the namespace first-letter capitalized?
Definition: MWNamespace.php:417
FileRepo\getFileTimestamp
getFileTimestamp( $virtualUrl)
Get the timestamp of a file with a given virtual URL/storage path.
Definition: FileRepo.php:1569
FileRepo\concatenate
concatenate(array $srcPaths, $dstPath, $flags=0)
Concatenate a list of temporary files into a target file location.
Definition: FileRepo.php:1123
FileRepo\deleteBatch
deleteBatch(array $sourceDestPairs)
Move a group of files to the deletion archive.
Definition: FileRepo.php:1418
FileRepo\resolveVirtualUrl
resolveVirtualUrl( $url)
Get the backend storage path corresponding to a virtual URL.
Definition: FileRepo.php:318
$source
$source
Definition: mwdoc-filter.php:46
true
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
Definition: hooks.txt:2036
FileBackend\isPathTraversalFree
static isPathTraversalFree( $path)
Check if a relative path has no directory traversals.
Definition: FileBackend.php:1519
FileRepo\cleanDir
cleanDir( $dir)
Deletes a directory if empty.
Definition: FileRepo.php:1344
$hashes
$hashes
Definition: testCompression.php:66
FileRepo\DELETE_SOURCE
const DELETE_SOURCE
Definition: FileRepo.php:40
File\DELETED_FILE
const DELETED_FILE
Definition: File.php:53
class
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
MediaWikiServices
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency MediaWikiServices
Definition: injection.txt:23
FileRepo\getFileProps
getFileProps( $virtualUrl)
Get properties of a file with a given virtual URL/storage path.
Definition: FileRepo.php:1551
wfMemcKey
wfMemcKey(... $args)
Make a cache key for the local wiki.
Definition: GlobalFunctions.php:2603
FileRepo\$abbrvThreshold
int $abbrvThreshold
File names over this size will use the short form of thumbnail names.
Definition: FileRepo.php:116
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:47
$ext
$ext
Definition: router.php:55
FileRepo\$transformVia404
bool $transformVia404
Whether to skip media file transformation on parse and rely on a 404 handler instead.
Definition: FileRepo.php:71
FileRepo\supportsSha1URLs
supportsSha1URLs()
Returns whether or not repo supports having originals SHA-1s in the thumb URLs.
Definition: FileRepo.php:1940
FileRepo\$hashLevels
int $hashLevels
The number of directory levels for hash-based division of files.
Definition: FileRepo.php:107
FileRepo\getDeletedHashPath
getDeletedHashPath( $key)
Get a relative path for a deletion archive key, e.g.
Definition: FileRepo.php:1489
FileRepo\assertWritableRepo
assertWritableRepo()
Throw an exception if this repo is read-only by design.
Definition: FileRepo.php:1898
FileRepo\NAME_AND_TIME_ONLY
const NAME_AND_TIME_ONLY
Definition: FileRepo.php:45
FileRepo\cleanupDeletedBatch
cleanupDeletedBatch(array $storageKeys)
Delete files in the deleted directory if they are not referenced in the filearchive table.
Definition: FileRepo.php:1477
FileRepo\$url
string false $url
Public zone URL.
Definition: FileRepo.php:101
FileRepo\canTransformVia404
canTransformVia404()
Returns true if the repository can transform files via a 404 handler.
Definition: FileRepo.php:632
FileRepo\$fetchDescription
bool $fetchDescription
Whether to fetch commons image description pages and display them on the local wiki.
Definition: FileRepo.php:49
FileRepo\$oldFileFactoryKey
array $oldFileFactoryKey
callable|bool Override these in the base class
Definition: FileRepo.php:131
FileRepo\$thumbProxyUrl
string $thumbProxyUrl
URL of where to proxy thumb.php requests to.
Definition: FileRepo.php:136