MediaWiki  1.27.2
FileOp.php
Go to the documentation of this file.
1 <?php
36 abstract class FileOp {
38  protected $params = [];
39 
41  protected $backend;
42 
44  protected $state = self::STATE_NEW;
45 
47  protected $failed = false;
48 
50  protected $async = false;
51 
53  protected $batchId;
54 
56  protected $doOperation = true;
57 
59  protected $sourceSha1;
60 
62  protected $overwriteSameCase;
63 
65  protected $destExists;
66 
67  /* Object life-cycle */
68  const STATE_NEW = 1;
69  const STATE_CHECKED = 2;
70  const STATE_ATTEMPTED = 3;
71 
79  final public function __construct( FileBackendStore $backend, array $params ) {
80  $this->backend = $backend;
81  list( $required, $optional, $paths ) = $this->allowedParams();
82  foreach ( $required as $name ) {
83  if ( isset( $params[$name] ) ) {
84  $this->params[$name] = $params[$name];
85  } else {
86  throw new FileBackendError( "File operation missing parameter '$name'." );
87  }
88  }
89  foreach ( $optional as $name ) {
90  if ( isset( $params[$name] ) ) {
91  $this->params[$name] = $params[$name];
92  }
93  }
94  foreach ( $paths as $name ) {
95  if ( isset( $this->params[$name] ) ) {
96  // Normalize paths so the paths to the same file have the same string
97  $this->params[$name] = self::normalizeIfValidStoragePath( $this->params[$name] );
98  }
99  }
100  }
101 
108  protected static function normalizeIfValidStoragePath( $path ) {
111 
112  return ( $res !== null ) ? $res : $path;
113  }
114 
115  return $path;
116  }
117 
123  final public function setBatchId( $batchId ) {
124  $this->batchId = $batchId;
125  }
126 
133  final public function getParam( $name ) {
134  return isset( $this->params[$name] ) ? $this->params[$name] : null;
135  }
136 
142  final public function failed() {
143  return $this->failed;
144  }
145 
151  final public static function newPredicates() {
152  return [ 'exists' => [], 'sha1' => [] ];
153  }
154 
160  final public static function newDependencies() {
161  return [ 'read' => [], 'write' => [] ];
162  }
163 
170  final public function applyDependencies( array $deps ) {
171  $deps['read'] += array_fill_keys( $this->storagePathsRead(), 1 );
172  $deps['write'] += array_fill_keys( $this->storagePathsChanged(), 1 );
173 
174  return $deps;
175  }
176 
183  final public function dependsOn( array $deps ) {
184  foreach ( $this->storagePathsChanged() as $path ) {
185  if ( isset( $deps['read'][$path] ) || isset( $deps['write'][$path] ) ) {
186  return true; // "output" or "anti" dependency
187  }
188  }
189  foreach ( $this->storagePathsRead() as $path ) {
190  if ( isset( $deps['write'][$path] ) ) {
191  return true; // "flow" dependency
192  }
193  }
194 
195  return false;
196  }
197 
205  final public function getJournalEntries( array $oPredicates, array $nPredicates ) {
206  if ( !$this->doOperation ) {
207  return []; // this is a no-op
208  }
209  $nullEntries = [];
210  $updateEntries = [];
211  $deleteEntries = [];
212  $pathsUsed = array_merge( $this->storagePathsRead(), $this->storagePathsChanged() );
213  foreach ( array_unique( $pathsUsed ) as $path ) {
214  $nullEntries[] = [ // assertion for recovery
215  'op' => 'null',
216  'path' => $path,
217  'newSha1' => $this->fileSha1( $path, $oPredicates )
218  ];
219  }
220  foreach ( $this->storagePathsChanged() as $path ) {
221  if ( $nPredicates['sha1'][$path] === false ) { // deleted
222  $deleteEntries[] = [
223  'op' => 'delete',
224  'path' => $path,
225  'newSha1' => ''
226  ];
227  } else { // created/updated
228  $updateEntries[] = [
229  'op' => $this->fileExists( $path, $oPredicates ) ? 'update' : 'create',
230  'path' => $path,
231  'newSha1' => $nPredicates['sha1'][$path]
232  ];
233  }
234  }
235 
236  return array_merge( $nullEntries, $updateEntries, $deleteEntries );
237  }
238 
247  final public function precheck( array &$predicates ) {
248  if ( $this->state !== self::STATE_NEW ) {
249  return Status::newFatal( 'fileop-fail-state', self::STATE_NEW, $this->state );
250  }
251  $this->state = self::STATE_CHECKED;
252  $status = $this->doPrecheck( $predicates );
253  if ( !$status->isOK() ) {
254  $this->failed = true;
255  }
256 
257  return $status;
258  }
259 
264  protected function doPrecheck( array &$predicates ) {
265  return Status::newGood();
266  }
267 
273  final public function attempt() {
274  if ( $this->state !== self::STATE_CHECKED ) {
275  return Status::newFatal( 'fileop-fail-state', self::STATE_CHECKED, $this->state );
276  } elseif ( $this->failed ) { // failed precheck
277  return Status::newFatal( 'fileop-fail-attempt-precheck' );
278  }
279  $this->state = self::STATE_ATTEMPTED;
280  if ( $this->doOperation ) {
281  $status = $this->doAttempt();
282  if ( !$status->isOK() ) {
283  $this->failed = true;
284  $this->logFailure( 'attempt' );
285  }
286  } else { // no-op
288  }
289 
290  return $status;
291  }
292 
296  protected function doAttempt() {
297  return Status::newGood();
298  }
299 
305  final public function attemptAsync() {
306  $this->async = true;
307  $result = $this->attempt();
308  $this->async = false;
309 
310  return $result;
311  }
312 
318  protected function allowedParams() {
319  return [ [], [], [] ];
320  }
321 
328  protected function setFlags( array $params ) {
329  return [ 'async' => $this->async ] + $params;
330  }
331 
337  public function storagePathsRead() {
338  return [];
339  }
340 
346  public function storagePathsChanged() {
347  return [];
348  }
349 
358  protected function precheckDestExistence( array $predicates ) {
360  // Get hash of source file/string and the destination file
361  $this->sourceSha1 = $this->getSourceSha1Base36(); // FS file or data string
362  if ( $this->sourceSha1 === null ) { // file in storage?
363  $this->sourceSha1 = $this->fileSha1( $this->params['src'], $predicates );
364  }
365  $this->overwriteSameCase = false;
366  $this->destExists = $this->fileExists( $this->params['dst'], $predicates );
367  if ( $this->destExists ) {
368  if ( $this->getParam( 'overwrite' ) ) {
369  return $status; // OK
370  } elseif ( $this->getParam( 'overwriteSame' ) ) {
371  $dhash = $this->fileSha1( $this->params['dst'], $predicates );
372  // Check if hashes are valid and match each other...
373  if ( !strlen( $this->sourceSha1 ) || !strlen( $dhash ) ) {
374  $status->fatal( 'backend-fail-hashes' );
375  } elseif ( $this->sourceSha1 !== $dhash ) {
376  // Give an error if the files are not identical
377  $status->fatal( 'backend-fail-notsame', $this->params['dst'] );
378  } else {
379  $this->overwriteSameCase = true; // OK
380  }
381 
382  return $status; // do nothing; either OK or bad status
383  } else {
384  $status->fatal( 'backend-fail-alreadyexists', $this->params['dst'] );
385 
386  return $status;
387  }
388  }
389 
390  return $status;
391  }
392 
399  protected function getSourceSha1Base36() {
400  return null; // N/A
401  }
402 
410  final protected function fileExists( $source, array $predicates ) {
411  if ( isset( $predicates['exists'][$source] ) ) {
412  return $predicates['exists'][$source]; // previous op assures this
413  } else {
414  $params = [ 'src' => $source, 'latest' => true ];
415 
416  return $this->backend->fileExists( $params );
417  }
418  }
419 
427  final protected function fileSha1( $source, array $predicates ) {
428  if ( isset( $predicates['sha1'][$source] ) ) {
429  return $predicates['sha1'][$source]; // previous op assures this
430  } elseif ( isset( $predicates['exists'][$source] ) && !$predicates['exists'][$source] ) {
431  return false; // previous op assures this
432  } else {
433  $params = [ 'src' => $source, 'latest' => true ];
434 
435  return $this->backend->getFileSha1Base36( $params );
436  }
437  }
438 
444  public function getBackend() {
445  return $this->backend;
446  }
447 
453  final public function logFailure( $action ) {
455  $params['failedAction'] = $action;
456  try {
457  wfDebugLog( 'FileOperation', get_class( $this ) .
458  " failed (batch #{$this->batchId}): " . FormatJson::encode( $params ) );
459  } catch ( Exception $e ) {
460  // bad config? debug log error?
461  }
462  }
463 }
464 
469 class CreateFileOp extends FileOp {
470  protected function allowedParams() {
471  return [
472  [ 'content', 'dst' ],
473  [ 'overwrite', 'overwriteSame', 'headers' ],
474  [ 'dst' ]
475  ];
476  }
477 
478  protected function doPrecheck( array &$predicates ) {
480  // Check if the source data is too big
481  if ( strlen( $this->getParam( 'content' ) ) > $this->backend->maxFileSizeInternal() ) {
482  $status->fatal( 'backend-fail-maxsize',
483  $this->params['dst'], $this->backend->maxFileSizeInternal() );
484  $status->fatal( 'backend-fail-create', $this->params['dst'] );
485 
486  return $status;
487  // Check if a file can be placed/changed at the destination
488  } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
489  $status->fatal( 'backend-fail-usable', $this->params['dst'] );
490  $status->fatal( 'backend-fail-create', $this->params['dst'] );
491 
492  return $status;
493  }
494  // Check if destination file exists
495  $status->merge( $this->precheckDestExistence( $predicates ) );
496  $this->params['dstExists'] = $this->destExists; // see FileBackendStore::setFileCache()
497  if ( $status->isOK() ) {
498  // Update file existence predicates
499  $predicates['exists'][$this->params['dst']] = true;
500  $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
501  }
502 
503  return $status; // safe to call attempt()
504  }
505 
506  protected function doAttempt() {
507  if ( !$this->overwriteSameCase ) {
508  // Create the file at the destination
509  return $this->backend->createInternal( $this->setFlags( $this->params ) );
510  }
511 
512  return Status::newGood();
513  }
514 
515  protected function getSourceSha1Base36() {
516  return Wikimedia\base_convert( sha1( $this->params['content'] ), 16, 36, 31 );
517  }
518 
519  public function storagePathsChanged() {
520  return [ $this->params['dst'] ];
521  }
522 }
523 
528 class StoreFileOp extends FileOp {
529  protected function allowedParams() {
530  return [
531  [ 'src', 'dst' ],
532  [ 'overwrite', 'overwriteSame', 'headers' ],
533  [ 'src', 'dst' ]
534  ];
535  }
536 
537  protected function doPrecheck( array &$predicates ) {
539  // Check if the source file exists on the file system
540  if ( !is_file( $this->params['src'] ) ) {
541  $status->fatal( 'backend-fail-notexists', $this->params['src'] );
542 
543  return $status;
544  // Check if the source file is too big
545  } elseif ( filesize( $this->params['src'] ) > $this->backend->maxFileSizeInternal() ) {
546  $status->fatal( 'backend-fail-maxsize',
547  $this->params['dst'], $this->backend->maxFileSizeInternal() );
548  $status->fatal( 'backend-fail-store', $this->params['src'], $this->params['dst'] );
549 
550  return $status;
551  // Check if a file can be placed/changed at the destination
552  } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
553  $status->fatal( 'backend-fail-usable', $this->params['dst'] );
554  $status->fatal( 'backend-fail-store', $this->params['src'], $this->params['dst'] );
555 
556  return $status;
557  }
558  // Check if destination file exists
559  $status->merge( $this->precheckDestExistence( $predicates ) );
560  $this->params['dstExists'] = $this->destExists; // see FileBackendStore::setFileCache()
561  if ( $status->isOK() ) {
562  // Update file existence predicates
563  $predicates['exists'][$this->params['dst']] = true;
564  $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
565  }
566 
567  return $status; // safe to call attempt()
568  }
569 
570  protected function doAttempt() {
571  if ( !$this->overwriteSameCase ) {
572  // Store the file at the destination
573  return $this->backend->storeInternal( $this->setFlags( $this->params ) );
574  }
575 
576  return Status::newGood();
577  }
578 
579  protected function getSourceSha1Base36() {
580  MediaWiki\suppressWarnings();
581  $hash = sha1_file( $this->params['src'] );
582  MediaWiki\restoreWarnings();
583  if ( $hash !== false ) {
584  $hash = Wikimedia\base_convert( $hash, 16, 36, 31 );
585  }
586 
587  return $hash;
588  }
589 
590  public function storagePathsChanged() {
591  return [ $this->params['dst'] ];
592  }
593 }
594 
599 class CopyFileOp extends FileOp {
600  protected function allowedParams() {
601  return [
602  [ 'src', 'dst' ],
603  [ 'overwrite', 'overwriteSame', 'ignoreMissingSource', 'headers' ],
604  [ 'src', 'dst' ]
605  ];
606  }
607 
608  protected function doPrecheck( array &$predicates ) {
610  // Check if the source file exists
611  if ( !$this->fileExists( $this->params['src'], $predicates ) ) {
612  if ( $this->getParam( 'ignoreMissingSource' ) ) {
613  $this->doOperation = false; // no-op
614  // Update file existence predicates (cache 404s)
615  $predicates['exists'][$this->params['src']] = false;
616  $predicates['sha1'][$this->params['src']] = false;
617 
618  return $status; // nothing to do
619  } else {
620  $status->fatal( 'backend-fail-notexists', $this->params['src'] );
621 
622  return $status;
623  }
624  // Check if a file can be placed/changed at the destination
625  } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
626  $status->fatal( 'backend-fail-usable', $this->params['dst'] );
627  $status->fatal( 'backend-fail-copy', $this->params['src'], $this->params['dst'] );
628 
629  return $status;
630  }
631  // Check if destination file exists
632  $status->merge( $this->precheckDestExistence( $predicates ) );
633  $this->params['dstExists'] = $this->destExists; // see FileBackendStore::setFileCache()
634  if ( $status->isOK() ) {
635  // Update file existence predicates
636  $predicates['exists'][$this->params['dst']] = true;
637  $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
638  }
639 
640  return $status; // safe to call attempt()
641  }
642 
643  protected function doAttempt() {
644  if ( $this->overwriteSameCase ) {
645  $status = Status::newGood(); // nothing to do
646  } elseif ( $this->params['src'] === $this->params['dst'] ) {
647  // Just update the destination file headers
648  $headers = $this->getParam( 'headers' ) ?: [];
649  $status = $this->backend->describeInternal( $this->setFlags( [
650  'src' => $this->params['dst'], 'headers' => $headers
651  ] ) );
652  } else {
653  // Copy the file to the destination
654  $status = $this->backend->copyInternal( $this->setFlags( $this->params ) );
655  }
656 
657  return $status;
658  }
659 
660  public function storagePathsRead() {
661  return [ $this->params['src'] ];
662  }
663 
664  public function storagePathsChanged() {
665  return [ $this->params['dst'] ];
666  }
667 }
668 
673 class MoveFileOp extends FileOp {
674  protected function allowedParams() {
675  return [
676  [ 'src', 'dst' ],
677  [ 'overwrite', 'overwriteSame', 'ignoreMissingSource', 'headers' ],
678  [ 'src', 'dst' ]
679  ];
680  }
681 
682  protected function doPrecheck( array &$predicates ) {
684  // Check if the source file exists
685  if ( !$this->fileExists( $this->params['src'], $predicates ) ) {
686  if ( $this->getParam( 'ignoreMissingSource' ) ) {
687  $this->doOperation = false; // no-op
688  // Update file existence predicates (cache 404s)
689  $predicates['exists'][$this->params['src']] = false;
690  $predicates['sha1'][$this->params['src']] = false;
691 
692  return $status; // nothing to do
693  } else {
694  $status->fatal( 'backend-fail-notexists', $this->params['src'] );
695 
696  return $status;
697  }
698  // Check if a file can be placed/changed at the destination
699  } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
700  $status->fatal( 'backend-fail-usable', $this->params['dst'] );
701  $status->fatal( 'backend-fail-move', $this->params['src'], $this->params['dst'] );
702 
703  return $status;
704  }
705  // Check if destination file exists
706  $status->merge( $this->precheckDestExistence( $predicates ) );
707  $this->params['dstExists'] = $this->destExists; // see FileBackendStore::setFileCache()
708  if ( $status->isOK() ) {
709  // Update file existence predicates
710  $predicates['exists'][$this->params['src']] = false;
711  $predicates['sha1'][$this->params['src']] = false;
712  $predicates['exists'][$this->params['dst']] = true;
713  $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
714  }
715 
716  return $status; // safe to call attempt()
717  }
718 
719  protected function doAttempt() {
720  if ( $this->overwriteSameCase ) {
721  if ( $this->params['src'] === $this->params['dst'] ) {
722  // Do nothing to the destination (which is also the source)
724  } else {
725  // Just delete the source as the destination file needs no changes
726  $status = $this->backend->deleteInternal( $this->setFlags(
727  [ 'src' => $this->params['src'] ]
728  ) );
729  }
730  } elseif ( $this->params['src'] === $this->params['dst'] ) {
731  // Just update the destination file headers
732  $headers = $this->getParam( 'headers' ) ?: [];
733  $status = $this->backend->describeInternal( $this->setFlags(
734  [ 'src' => $this->params['dst'], 'headers' => $headers ]
735  ) );
736  } else {
737  // Move the file to the destination
738  $status = $this->backend->moveInternal( $this->setFlags( $this->params ) );
739  }
740 
741  return $status;
742  }
743 
744  public function storagePathsRead() {
745  return [ $this->params['src'] ];
746  }
747 
748  public function storagePathsChanged() {
749  return [ $this->params['src'], $this->params['dst'] ];
750  }
751 }
752 
757 class DeleteFileOp extends FileOp {
758  protected function allowedParams() {
759  return [ [ 'src' ], [ 'ignoreMissingSource' ], [ 'src' ] ];
760  }
761 
762  protected function doPrecheck( array &$predicates ) {
764  // Check if the source file exists
765  if ( !$this->fileExists( $this->params['src'], $predicates ) ) {
766  if ( $this->getParam( 'ignoreMissingSource' ) ) {
767  $this->doOperation = false; // no-op
768  // Update file existence predicates (cache 404s)
769  $predicates['exists'][$this->params['src']] = false;
770  $predicates['sha1'][$this->params['src']] = false;
771 
772  return $status; // nothing to do
773  } else {
774  $status->fatal( 'backend-fail-notexists', $this->params['src'] );
775 
776  return $status;
777  }
778  // Check if a file can be placed/changed at the source
779  } elseif ( !$this->backend->isPathUsableInternal( $this->params['src'] ) ) {
780  $status->fatal( 'backend-fail-usable', $this->params['src'] );
781  $status->fatal( 'backend-fail-delete', $this->params['src'] );
782 
783  return $status;
784  }
785  // Update file existence predicates
786  $predicates['exists'][$this->params['src']] = false;
787  $predicates['sha1'][$this->params['src']] = false;
788 
789  return $status; // safe to call attempt()
790  }
791 
792  protected function doAttempt() {
793  // Delete the source file
794  return $this->backend->deleteInternal( $this->setFlags( $this->params ) );
795  }
796 
797  public function storagePathsChanged() {
798  return [ $this->params['src'] ];
799  }
800 }
801 
806 class DescribeFileOp extends FileOp {
807  protected function allowedParams() {
808  return [ [ 'src' ], [ 'headers' ], [ 'src' ] ];
809  }
810 
811  protected function doPrecheck( array &$predicates ) {
813  // Check if the source file exists
814  if ( !$this->fileExists( $this->params['src'], $predicates ) ) {
815  $status->fatal( 'backend-fail-notexists', $this->params['src'] );
816 
817  return $status;
818  // Check if a file can be placed/changed at the source
819  } elseif ( !$this->backend->isPathUsableInternal( $this->params['src'] ) ) {
820  $status->fatal( 'backend-fail-usable', $this->params['src'] );
821  $status->fatal( 'backend-fail-describe', $this->params['src'] );
822 
823  return $status;
824  }
825  // Update file existence predicates
826  $predicates['exists'][$this->params['src']] =
827  $this->fileExists( $this->params['src'], $predicates );
828  $predicates['sha1'][$this->params['src']] =
829  $this->fileSha1( $this->params['src'], $predicates );
830 
831  return $status; // safe to call attempt()
832  }
833 
834  protected function doAttempt() {
835  // Update the source file's metadata
836  return $this->backend->describeInternal( $this->setFlags( $this->params ) );
837  }
838 
839  public function storagePathsChanged() {
840  return [ $this->params['src'] ];
841  }
842 }
843 
847 class NullFileOp extends FileOp {
848 }
setBatchId($batchId)
Set the batch UUID this operation belongs to.
Definition: FileOp.php:123
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
storagePathsChanged()
Definition: FileOp.php:519
the array() calling protocol came about after MediaWiki 1.4rc1.
logFailure($action)
Log a file operation failure and preserve any temp files.
Definition: FileOp.php:453
getJournalEntries(array $oPredicates, array $nPredicates)
Get the file journal entries for this file operation.
Definition: FileOp.php:205
bool $failed
Definition: FileOp.php:47
Delete a file at the given storage path from the backend.
Definition: FileOp.php:757
Store a file into the backend from a file on the file system.
Definition: FileOp.php:528
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException'returning false will NOT prevent logging $e
Definition: hooks.txt:1932
storagePathsRead()
Definition: FileOp.php:660
FileBackend helper class for representing operations.
Definition: FileOp.php:36
applyDependencies(array $deps)
Update a dependency tracking array to account for this operation.
Definition: FileOp.php:170
fileSha1($source, array $predicates)
Get the SHA-1 of a file in storage when this operation is attempted.
Definition: FileOp.php:427
storagePathsChanged()
Definition: FileOp.php:664
getParam($name)
Get the value of the parameter with the given name.
Definition: FileOp.php:133
Copy a file from one storage path to another in the backend.
Definition: FileOp.php:599
array $params
Definition: FileOp.php:38
$source
doPrecheck(array &$predicates)
Definition: FileOp.php:537
Move a file from one storage path to another in the backend.
Definition: FileOp.php:673
setFlags(array $params)
Adjust params to FileBackendStore internal file calls.
Definition: FileOp.php:328
bool $doOperation
Operation is not a no-op.
Definition: FileOp.php:56
string $batchId
Definition: FileOp.php:53
getSourceSha1Base36()
Definition: FileOp.php:515
doAttempt()
Definition: FileOp.php:719
const STATE_CHECKED
Definition: FileOp.php:69
storagePathsChanged()
Definition: FileOp.php:839
static newFatal($message)
Factory function for fatal errors.
Definition: Status.php:89
doPrecheck(array &$predicates)
Definition: FileOp.php:478
const STATE_NEW
Definition: FileOp.php:68
storagePathsChanged()
Definition: FileOp.php:797
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 '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!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:Associative array mapping language codes to prefixed links of the form"language:title".&$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':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:1796
attempt()
Attempt the operation.
Definition: FileOp.php:273
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:1798
wfDebugLog($logGroup, $text, $dest= 'all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not...
storagePathsChanged()
Definition: FileOp.php:748
int $state
Definition: FileOp.php:44
const STATE_ATTEMPTED
Definition: FileOp.php:70
File backend exception for checked exceptions (e.g.
storagePathsRead()
Get a list of storage paths read from for this operation.
Definition: FileOp.php:337
dependsOn(array $deps)
Check if this operation changes files listed in $paths.
Definition: FileOp.php:183
static newPredicates()
Get a new empty predicates array for precheck()
Definition: FileOp.php:151
precheckDestExistence(array $predicates)
Check for errors with regards to the destination file already existing.
Definition: FileOp.php:358
$res
Definition: database.txt:21
static isStoragePath($path)
Check if a given path is a "mwstore://" path.
attemptAsync()
Attempt the operation in the background.
Definition: FileOp.php:305
getSourceSha1Base36()
precheckDestExistence() helper function to get the source file SHA-1.
Definition: FileOp.php:399
doPrecheck(array &$predicates)
Definition: FileOp.php:811
Change metadata for a file at the given storage path in the backend.
Definition: FileOp.php:806
static encode($value, $pretty=false, $escaping=0)
Returns the JSON representation of a value.
Definition: FormatJson.php:127
allowedParams()
Get the file operation parameters.
Definition: FileOp.php:318
getSourceSha1Base36()
Definition: FileOp.php:579
storagePathsRead()
Definition: FileOp.php:744
getBackend()
Get the backend this operation is for.
Definition: FileOp.php:444
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
doAttempt()
Definition: FileOp.php:643
doAttempt()
Definition: FileOp.php:296
static normalizeIfValidStoragePath($path)
Normalize a string if it is a valid storage path.
Definition: FileOp.php:108
Base class for all backends using particular storage medium.
precheck(array &$predicates)
Check preconditions of the operation without writing anything.
Definition: FileOp.php:247
FileBackendStore $backend
Definition: FileOp.php:41
Placeholder operation that has no params and does nothing.
Definition: FileOp.php:847
doPrecheck(array &$predicates)
Definition: FileOp.php:264
static normalizeStoragePath($storagePath)
Normalize a storage path by cleaning up directory separators.
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
bool $destExists
Definition: FileOp.php:65
static newDependencies()
Get a new empty dependency tracking array for paths read/written to.
Definition: FileOp.php:160
allowedParams()
Definition: FileOp.php:529
allowedParams()
Definition: FileOp.php:470
storagePathsChanged()
Get a list of storage paths written to for this operation.
Definition: FileOp.php:346
doPrecheck(array &$predicates)
Definition: FileOp.php:762
allowedParams()
Definition: FileOp.php:758
fileExists($source, array $predicates)
Check if a file will exist in storage when this operation is attempted.
Definition: FileOp.php:410
allowedParams()
Definition: FileOp.php:674
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set $status
Definition: hooks.txt:1004
allowedParams()
Definition: FileOp.php:600
bool $async
Definition: FileOp.php:50
string $sourceSha1
Definition: FileOp.php:59
storagePathsChanged()
Definition: FileOp.php:590
doPrecheck(array &$predicates)
Definition: FileOp.php:608
Create a file in the backend with the given content.
Definition: FileOp.php:469
doPrecheck(array &$predicates)
Definition: FileOp.php:682
static newGood($value=null)
Factory function for good results.
Definition: Status.php:101
failed()
Check if this operation failed precheck() or attempt()
Definition: FileOp.php:142
__construct(FileBackendStore $backend, array $params)
Build a new batch file operation transaction.
Definition: FileOp.php:79
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:310
bool $overwriteSameCase
Definition: FileOp.php:62