MediaWiki  master
FileBackend.php
Go to the documentation of this file.
1 <?php
85 abstract class FileBackend {
87  protected $name;
88 
90  protected $wikiId;
91 
93  protected $readOnly;
94 
96  protected $parallelize;
97 
99  protected $concurrency;
100 
102  protected $lockManager;
103 
105  protected $fileJournal;
106 
108  const ATTR_HEADERS = 1; // files can be tagged with standard HTTP headers
109  const ATTR_METADATA = 2; // files can be stored with metadata key/values
110  const ATTR_UNICODE_PATHS = 4; // files can have Unicode paths (not just ASCII)
111 
136  public function __construct( array $config ) {
137  $this->name = $config['name'];
138  $this->wikiId = $config['wikiId']; // e.g. "my_wiki-en_"
139  if ( !preg_match( '!^[a-zA-Z0-9-_]{1,255}$!', $this->name ) ) {
140  throw new FileBackendException( "Backend name '{$this->name}' is invalid." );
141  } elseif ( !is_string( $this->wikiId ) ) {
142  throw new FileBackendException( "Backend wiki ID not provided for '{$this->name}'." );
143  }
144  $this->lockManager = isset( $config['lockManager'] )
145  ? $config['lockManager']
146  : new NullLockManager( [] );
147  $this->fileJournal = isset( $config['fileJournal'] )
148  ? $config['fileJournal']
149  : FileJournal::factory( [ 'class' => 'NullFileJournal' ], $this->name );
150  $this->readOnly = isset( $config['readOnly'] )
151  ? (string)$config['readOnly']
152  : '';
153  $this->parallelize = isset( $config['parallelize'] )
154  ? (string)$config['parallelize']
155  : 'off';
156  $this->concurrency = isset( $config['concurrency'] )
157  ? (int)$config['concurrency']
158  : 50;
159  }
160 
168  final public function getName() {
169  return $this->name;
170  }
171 
179  final public function getWikiId() {
180  return $this->wikiId;
181  }
182 
188  final public function isReadOnly() {
189  return ( $this->readOnly != '' );
190  }
191 
197  final public function getReadOnlyReason() {
198  return ( $this->readOnly != '' ) ? $this->readOnly : false;
199  }
200 
207  public function getFeatures() {
208  return self::ATTR_UNICODE_PATHS;
209  }
210 
218  final public function hasFeatures( $bitfield ) {
219  return ( $this->getFeatures() & $bitfield ) === $bitfield;
220  }
221 
370  final public function doOperations( array $ops, array $opts = [] ) {
371  if ( empty( $opts['bypassReadOnly'] ) && $this->isReadOnly() ) {
372  return Status::newFatal( 'backend-fail-readonly', $this->name, $this->readOnly );
373  }
374  if ( !count( $ops ) ) {
375  return Status::newGood(); // nothing to do
376  }
377 
378  $ops = $this->resolveFSFileObjects( $ops );
379  if ( empty( $opts['force'] ) ) { // sanity
380  unset( $opts['nonLocking'] );
381  }
382 
384  $scope = $this->getScopedPHPBehaviorForOps(); // try to ignore client aborts
385 
386  return $this->doOperationsInternal( $ops, $opts );
387  }
388 
394  abstract protected function doOperationsInternal( array $ops, array $opts );
395 
407  final public function doOperation( array $op, array $opts = [] ) {
408  return $this->doOperations( [ $op ], $opts );
409  }
410 
421  final public function create( array $params, array $opts = [] ) {
422  return $this->doOperation( [ 'op' => 'create' ] + $params, $opts );
423  }
424 
435  final public function store( array $params, array $opts = [] ) {
436  return $this->doOperation( [ 'op' => 'store' ] + $params, $opts );
437  }
438 
449  final public function copy( array $params, array $opts = [] ) {
450  return $this->doOperation( [ 'op' => 'copy' ] + $params, $opts );
451  }
452 
463  final public function move( array $params, array $opts = [] ) {
464  return $this->doOperation( [ 'op' => 'move' ] + $params, $opts );
465  }
466 
477  final public function delete( array $params, array $opts = [] ) {
478  return $this->doOperation( [ 'op' => 'delete' ] + $params, $opts );
479  }
480 
492  final public function describe( array $params, array $opts = [] ) {
493  return $this->doOperation( [ 'op' => 'describe' ] + $params, $opts );
494  }
495 
608  final public function doQuickOperations( array $ops, array $opts = [] ) {
609  if ( empty( $opts['bypassReadOnly'] ) && $this->isReadOnly() ) {
610  return Status::newFatal( 'backend-fail-readonly', $this->name, $this->readOnly );
611  }
612  if ( !count( $ops ) ) {
613  return Status::newGood(); // nothing to do
614  }
615 
616  $ops = $this->resolveFSFileObjects( $ops );
617  foreach ( $ops as &$op ) {
618  $op['overwrite'] = true; // avoids RTTs in key/value stores
619  }
620 
622  $scope = $this->getScopedPHPBehaviorForOps(); // try to ignore client aborts
623 
624  return $this->doQuickOperationsInternal( $ops );
625  }
626 
632  abstract protected function doQuickOperationsInternal( array $ops );
633 
644  final public function doQuickOperation( array $op ) {
645  return $this->doQuickOperations( [ $op ] );
646  }
647 
658  final public function quickCreate( array $params ) {
659  return $this->doQuickOperation( [ 'op' => 'create' ] + $params );
660  }
661 
672  final public function quickStore( array $params ) {
673  return $this->doQuickOperation( [ 'op' => 'store' ] + $params );
674  }
675 
686  final public function quickCopy( array $params ) {
687  return $this->doQuickOperation( [ 'op' => 'copy' ] + $params );
688  }
689 
700  final public function quickMove( array $params ) {
701  return $this->doQuickOperation( [ 'op' => 'move' ] + $params );
702  }
703 
714  final public function quickDelete( array $params ) {
715  return $this->doQuickOperation( [ 'op' => 'delete' ] + $params );
716  }
717 
728  final public function quickDescribe( array $params ) {
729  return $this->doQuickOperation( [ 'op' => 'describe' ] + $params );
730  }
731 
744  abstract public function concatenate( array $params );
745 
764  final public function prepare( array $params ) {
765  if ( empty( $params['bypassReadOnly'] ) && $this->isReadOnly() ) {
766  return Status::newFatal( 'backend-fail-readonly', $this->name, $this->readOnly );
767  }
769  $scope = $this->getScopedPHPBehaviorForOps(); // try to ignore client aborts
770  return $this->doPrepare( $params );
771  }
772 
777  abstract protected function doPrepare( array $params );
778 
795  final public function secure( array $params ) {
796  if ( empty( $params['bypassReadOnly'] ) && $this->isReadOnly() ) {
797  return Status::newFatal( 'backend-fail-readonly', $this->name, $this->readOnly );
798  }
800  $scope = $this->getScopedPHPBehaviorForOps(); // try to ignore client aborts
801  return $this->doSecure( $params );
802  }
803 
808  abstract protected function doSecure( array $params );
809 
828  final public function publish( array $params ) {
829  if ( empty( $params['bypassReadOnly'] ) && $this->isReadOnly() ) {
830  return Status::newFatal( 'backend-fail-readonly', $this->name, $this->readOnly );
831  }
833  $scope = $this->getScopedPHPBehaviorForOps(); // try to ignore client aborts
834  return $this->doPublish( $params );
835  }
836 
841  abstract protected function doPublish( array $params );
842 
854  final public function clean( array $params ) {
855  if ( empty( $params['bypassReadOnly'] ) && $this->isReadOnly() ) {
856  return Status::newFatal( 'backend-fail-readonly', $this->name, $this->readOnly );
857  }
859  $scope = $this->getScopedPHPBehaviorForOps(); // try to ignore client aborts
860  return $this->doClean( $params );
861  }
862 
867  abstract protected function doClean( array $params );
868 
876  final protected function getScopedPHPBehaviorForOps() {
877  if ( PHP_SAPI != 'cli' ) { // http://bugs.php.net/bug.php?id=47540
878  $old = ignore_user_abort( true ); // avoid half-finished operations
879  return new ScopedCallback( function () use ( $old ) {
880  ignore_user_abort( $old );
881  } );
882  }
883 
884  return null;
885  }
886 
896  abstract public function fileExists( array $params );
897 
906  abstract public function getFileTimestamp( array $params );
907 
917  final public function getFileContents( array $params ) {
918  $contents = $this->getFileContentsMulti(
919  [ 'srcs' => [ $params['src'] ] ] + $params );
920 
921  return $contents[$params['src']];
922  }
923 
938  abstract public function getFileContentsMulti( array $params );
939 
958  abstract public function getFileXAttributes( array $params );
959 
968  abstract public function getFileSize( array $params );
969 
983  abstract public function getFileStat( array $params );
984 
993  abstract public function getFileSha1Base36( array $params );
994 
1004  abstract public function getFileProps( array $params );
1005 
1025  abstract public function streamFile( array $params );
1026 
1045  final public function getLocalReference( array $params ) {
1046  $fsFiles = $this->getLocalReferenceMulti(
1047  [ 'srcs' => [ $params['src'] ] ] + $params );
1048 
1049  return $fsFiles[$params['src']];
1050  }
1051 
1066  abstract public function getLocalReferenceMulti( array $params );
1067 
1078  final public function getLocalCopy( array $params ) {
1079  $tmpFiles = $this->getLocalCopyMulti(
1080  [ 'srcs' => [ $params['src'] ] ] + $params );
1081 
1082  return $tmpFiles[$params['src']];
1083  }
1084 
1099  abstract public function getLocalCopyMulti( array $params );
1100 
1117  abstract public function getFileHttpUrl( array $params );
1118 
1131  abstract public function directoryExists( array $params );
1132 
1151  abstract public function getDirectoryList( array $params );
1152 
1166  final public function getTopDirectoryList( array $params ) {
1167  return $this->getDirectoryList( [ 'topOnly' => true ] + $params );
1168  }
1169 
1188  abstract public function getFileList( array $params );
1189 
1204  final public function getTopFileList( array $params ) {
1205  return $this->getFileList( [ 'topOnly' => true ] + $params );
1206  }
1207 
1216  abstract public function preloadCache( array $paths );
1217 
1226  abstract public function clearCache( array $paths = null );
1227 
1242  abstract public function preloadFileStat( array $params );
1243 
1255  final public function lockFiles( array $paths, $type, $timeout = 0 ) {
1256  $paths = array_map( 'FileBackend::normalizeStoragePath', $paths );
1257 
1258  return $this->lockManager->lock( $paths, $type, $timeout );
1259  }
1260 
1268  final public function unlockFiles( array $paths, $type ) {
1269  $paths = array_map( 'FileBackend::normalizeStoragePath', $paths );
1270 
1271  return $this->lockManager->unlock( $paths, $type );
1272  }
1273 
1290  final public function getScopedFileLocks( array $paths, $type, Status $status, $timeout = 0 ) {
1291  if ( $type === 'mixed' ) {
1292  foreach ( $paths as &$typePaths ) {
1293  $typePaths = array_map( 'FileBackend::normalizeStoragePath', $typePaths );
1294  }
1295  } else {
1296  $paths = array_map( 'FileBackend::normalizeStoragePath', $paths );
1297  }
1298 
1299  return ScopedLock::factory( $this->lockManager, $paths, $type, $status, $timeout );
1300  }
1301 
1318  abstract public function getScopedLocksForOps( array $ops, Status $status );
1319 
1327  final public function getRootStoragePath() {
1328  return "mwstore://{$this->name}";
1329  }
1330 
1338  final public function getContainerStoragePath( $container ) {
1339  return $this->getRootStoragePath() . "/{$container}";
1340  }
1341 
1347  final public function getJournal() {
1348  return $this->fileJournal;
1349  }
1350 
1360  protected function resolveFSFileObjects( array $ops ) {
1361  foreach ( $ops as &$op ) {
1362  $src = isset( $op['src'] ) ? $op['src'] : null;
1363  if ( $src instanceof FSFile ) {
1364  $op['srcRef'] = $src;
1365  $op['src'] = $src->getPath();
1366  }
1367  }
1368  unset( $op );
1369 
1370  return $ops;
1371  }
1372 
1380  final public static function isStoragePath( $path ) {
1381  return ( strpos( $path, 'mwstore://' ) === 0 );
1382  }
1383 
1392  final public static function splitStoragePath( $storagePath ) {
1393  if ( self::isStoragePath( $storagePath ) ) {
1394  // Remove the "mwstore://" prefix and split the path
1395  $parts = explode( '/', substr( $storagePath, 10 ), 3 );
1396  if ( count( $parts ) >= 2 && $parts[0] != '' && $parts[1] != '' ) {
1397  if ( count( $parts ) == 3 ) {
1398  return $parts; // e.g. "backend/container/path"
1399  } else {
1400  return [ $parts[0], $parts[1], '' ]; // e.g. "backend/container"
1401  }
1402  }
1403  }
1404 
1405  return [ null, null, null ];
1406  }
1407 
1415  final public static function normalizeStoragePath( $storagePath ) {
1416  list( $backend, $container, $relPath ) = self::splitStoragePath( $storagePath );
1417  if ( $relPath !== null ) { // must be for this backend
1418  $relPath = self::normalizeContainerPath( $relPath );
1419  if ( $relPath !== null ) {
1420  return ( $relPath != '' )
1421  ? "mwstore://{$backend}/{$container}/{$relPath}"
1422  : "mwstore://{$backend}/{$container}";
1423  }
1424  }
1425 
1426  return null;
1427  }
1428 
1437  final public static function parentStoragePath( $storagePath ) {
1438  $storagePath = dirname( $storagePath );
1439  list( , , $rel ) = self::splitStoragePath( $storagePath );
1440 
1441  return ( $rel === null ) ? null : $storagePath;
1442  }
1443 
1451  final public static function extensionFromPath( $path, $case = 'lowercase' ) {
1452  $i = strrpos( $path, '.' );
1453  $ext = $i ? substr( $path, $i + 1 ) : '';
1454 
1455  if ( $case === 'lowercase' ) {
1456  $ext = strtolower( $ext );
1457  } elseif ( $case === 'uppercase' ) {
1458  $ext = strtoupper( $ext );
1459  }
1460 
1461  return $ext;
1462  }
1463 
1471  final public static function isPathTraversalFree( $path ) {
1472  return ( self::normalizeContainerPath( $path ) !== null );
1473  }
1474 
1484  final public static function makeContentDisposition( $type, $filename = '' ) {
1485  $parts = [];
1486 
1487  $type = strtolower( $type );
1488  if ( !in_array( $type, [ 'inline', 'attachment' ] ) ) {
1489  throw new FileBackendError( "Invalid Content-Disposition type '$type'." );
1490  }
1491  $parts[] = $type;
1492 
1493  if ( strlen( $filename ) ) {
1494  $parts[] = "filename*=UTF-8''" . rawurlencode( basename( $filename ) );
1495  }
1496 
1497  return implode( ';', $parts );
1498  }
1499 
1510  final protected static function normalizeContainerPath( $path ) {
1511  // Normalize directory separators
1512  $path = strtr( $path, '\\', '/' );
1513  // Collapse any consecutive directory separators
1514  $path = preg_replace( '![/]{2,}!', '/', $path );
1515  // Remove any leading directory separator
1516  $path = ltrim( $path, '/' );
1517  // Use the same traversal protection as Title::secureAndSplit()
1518  if ( strpos( $path, '.' ) !== false ) {
1519  if (
1520  $path === '.' ||
1521  $path === '..' ||
1522  strpos( $path, './' ) === 0 ||
1523  strpos( $path, '../' ) === 0 ||
1524  strpos( $path, '/./' ) !== false ||
1525  strpos( $path, '/../' ) !== false
1526  ) {
1527  return null;
1528  }
1529  }
1530 
1531  return $path;
1532  }
1533 }
1534 
1541 class FileBackendException extends Exception {
1542 }
1543 
1551 }
doQuickOperationsInternal(array $ops)
FileJournal $fileJournal
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
describe(array $params, array $opts=[])
Performs a single describe operation.
the array() calling protocol came about after MediaWiki 1.4rc1.
unlockFiles(array $paths, $type)
Unlock the files at the given storage paths in the backend.
doOperations(array $ops, array $opts=[])
This is the main entry point into the backend for write operations.
doPrepare(array $params)
getFileStat(array $params)
Get quick information about a file at a storage path in the backend.
getWikiId()
Get the wiki identifier used for this backend (possibly empty).
publish(array $params)
Remove measures to block web access to a storage directory and the container it belongs to...
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
secure(array $params)
Take measures to block web access to a storage directory and the container it belongs to...
Simple version of LockManager that does nothing.
const ATTR_HEADERS
Bitfield flags for supported features.
Generic operation result class Has warning/error list, boolean status and arbitrary value...
Definition: Status.php:40
quickMove(array $params)
Performs a single quick move operation.
getFileHttpUrl(array $params)
Return an HTTP URL to a given file that requires no authentication to use.
quickDelete(array $params)
Performs a single quick delete operation.
This code would result in ircNotify being run twice when an article is and once for brion Hooks can return three possible true was required This is the default since MediaWiki *some string
Definition: hooks.txt:177
getFileXAttributes(array $params)
Get metadata about a file at a storage path in the backend.
getScopedPHPBehaviorForOps()
Enter file operation scope.
getName()
Get the unique backend name.
getFileContentsMulti(array $params)
Like getFileContents() except it takes an array of storage paths and returns a map of storage paths t...
getDirectoryList(array $params)
Get an iterator to list all directories under a storage directory.
doOperation(array $op, array $opts=[])
Same as doOperations() except it takes a single operation.
doClean(array $params)
getFileTimestamp(array $params)
Get the last-modified timestamp of the file at a storage path.
int $concurrency
How many operations can be done in parallel.
Definition: FileBackend.php:99
static newFatal($message)
Factory function for fatal errors.
Definition: Status.php:89
getLocalReferenceMulti(array $params)
Like getLocalReference() except it takes an array of storage paths and returns a map of storage paths...
static extensionFromPath($path, $case= 'lowercase')
Get the final extension from a storage or FS path.
directoryExists(array $params)
Check if a directory exists at a given storage path.
hasFeatures($bitfield)
Check if the backend medium supports a field of extra features.
resolveFSFileObjects(array $ops)
Convert FSFile 'src' paths to string paths (with an 'srcRef' field set to the FSFile) ...
Generic file backend exception for checked and unexpected (e.g.
string $readOnly
Read-only explanation message.
Definition: FileBackend.php:93
Class for asserting that a callback happens when an dummy object leaves scope.
create(array $params, array $opts=[])
Performs a single create operation.
move(array $params, array $opts=[])
Performs a single move operation.
quickStore(array $params)
Performs a single quick store operation.
getContainerStoragePath($container)
Get the storage path for the given container for this backend.
getReadOnlyReason()
Get an explanatory message if this backend is read-only.
static normalizeContainerPath($path)
Validate and normalize a relative storage path.
quickCreate(array $params)
Performs a single quick create operation.
getTopFileList(array $params)
Same as FileBackend::getFileList() except only lists files that are immediately under the given direc...
File backend exception for checked exceptions (e.g.
lockFiles(array $paths, $type, $timeout=0)
Lock the files at the given storage paths in the backend.
__construct(array $config)
Create a new backend instance from configuration.
static isStoragePath($path)
Check if a given path is a "mwstore://" path.
quickCopy(array $params)
Performs a single quick copy operation.
fileExists(array $params)
Check if a file exists at a storage path in the backend.
getFileSha1Base36(array $params)
Get a SHA-1 hash of the file at a storage path in the backend.
$params
store(array $params, array $opts=[])
Performs a single store operation.
const ATTR_UNICODE_PATHS
doSecure(array $params)
const ATTR_METADATA
getFileSize(array $params)
Get the size (bytes) of a file at a storage path in the backend.
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
doQuickOperations(array $ops, array $opts=[])
Perform a set of independent file operations on some files.
prepare(array $params)
Prepare a storage directory for usage.
string $name
Unique backend name.
Definition: FileBackend.php:87
getLocalCopy(array $params)
Get a local copy on disk of the file at a storage path in the backend.
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
getJournal()
Get the file journal object for this backend.
concatenate(array $params)
Concatenate a list of storage files into a single file system file.
static factory(LockManager $manager, array $paths, $type, Status $status, $timeout=0)
Get a ScopedLock object representing a lock on resource paths.
Definition: ScopedLock.php:69
getRootStoragePath()
Get the root storage path of this backend.
Class representing a non-directory file on the file system.
Definition: FSFile.php:29
preloadCache(array $paths)
Preload persistent file stat cache and property cache into in-process cache.
copy(array $params, array $opts=[])
Performs a single copy operation.
doOperationsInternal(array $ops, array $opts)
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at name
Definition: design.txt:12
Base class for all file backend classes (including multi-write backends).
Definition: FileBackend.php:85
getFileList(array $params)
Get an iterator to list all stored files under a storage directory.
static isPathTraversalFree($path)
Check if a relative path has no directory traversals.
getTopDirectoryList(array $params)
Same as FileBackend::getDirectoryList() except only lists directories that are immediately under the ...
getLocalCopyMulti(array $params)
Like getLocalCopy() except it takes an array of storage paths and returns a map of storage paths to T...
static makeContentDisposition($type, $filename= '')
Build a Content-Disposition header value per RFC 6266.
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:1020
quickDescribe(array $params)
Performs a single quick describe operation.
string $parallelize
When to do operations in parallel.
Definition: FileBackend.php:96
streamFile(array $params)
Stream the file at a storage path in the backend.
getScopedLocksForOps(array $ops, Status $status)
Get an array of scoped locks needed for a batch of file operations.
clean(array $params)
Delete a storage directory if it is empty.
getFileProps(array $params)
Get the properties of the file at a storage path in the backend.
static splitStoragePath($storagePath)
Split a storage path into a backend name, a container name, and a relative file path.
clearCache(array $paths=null)
Invalidate any in-process file stat and property cache.
LockManager $lockManager
doQuickOperation(array $op)
Same as doQuickOperations() except it takes a single operation.
string $wikiId
Unique wiki name.
Definition: FileBackend.php:90
isReadOnly()
Check if this backend is read-only.
preloadFileStat(array $params)
Preload file stat information (concurrently if possible) into in-process cache.
getLocalReference(array $params)
Returns a file system file, identical to the file at a storage path.
getFeatures()
Get the a bitfield of extra features supported by the backend medium.
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached one of or reset my talk my contributions etc etc otherwise the built in rate limiting checks are if enabled allows for interception of redirect as a string mapping parameter names to values & $type
Definition: hooks.txt:2376
static factory(array $config, $backend)
Create an appropriate FileJournal object from config.
Definition: FileJournal.php:63
static newGood($value=null)
Factory function for good results.
Definition: Status.php:101
doPublish(array $params)
getFileContents(array $params)
Get the contents of a file at a storage path in the backend.
getScopedFileLocks(array $paths, $type, Status $status, $timeout=0)
Lock the files at the given storage paths in the backend.
static parentStoragePath($storagePath)
Get the parent storage directory of a storage path.