protected $backend;
/** @var array Map of zones to config */
- protected $zones = array();
+ protected $zones = [];
/** @var string URL of thumb.php */
protected $thumbScriptUrl;
protected $isPrivate;
/** @var array callable Override these in the base class */
- protected $fileFactory = array( 'UnregisteredLocalFile', 'newFromTitle' );
+ protected $fileFactory = [ 'UnregisteredLocalFile', 'newFromTitle' ];
/** @var array callable|bool Override these in the base class */
protected $oldFileFactory = false;
/** @var array callable|bool Override these in the base class */
}
// Optional settings that can have no value
- $optionalSettings = array(
+ $optionalSettings = [
'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription',
'thumbScriptUrl', 'pathDisclosureProtection', 'descriptionCacheExpiry',
'scriptExtension', 'favicon'
- );
+ ];
foreach ( $optionalSettings as $var ) {
if ( isset( $info[$var] ) ) {
$this->$var = $info[$var];
: 255;
$this->isPrivate = !empty( $info['isPrivate'] );
// Give defaults for the basic zones...
- $this->zones = isset( $info['zones'] ) ? $info['zones'] : array();
- foreach ( array( 'public', 'thumb', 'transcoded', 'temp', 'deleted' ) as $zone ) {
+ $this->zones = isset( $info['zones'] ) ? $info['zones'] : [];
+ foreach ( [ 'public', 'thumb', 'transcoded', 'temp', 'deleted' ] as $zone ) {
if ( !isset( $this->zones[$zone]['container'] ) ) {
$this->zones[$zone]['container'] = "{$this->name}-{$zone}";
}
$this->zones[$zone]['directory'] = '';
}
if ( !isset( $this->zones[$zone]['urlsByExt'] ) ) {
- $this->zones[$zone]['urlsByExt'] = array();
+ $this->zones[$zone]['urlsByExt'] = [];
}
}
* @throws MWException
* @return Status
*/
- protected function initZones( $doZones = array() ) {
+ protected function initZones( $doZones = [] ) {
$status = $this->newGood();
foreach ( (array)$doZones as $zone ) {
$root = $this->getZonePath( $zone );
* @return string|bool
*/
public function getZoneUrl( $zone, $ext = null ) {
- if ( in_array( $zone, array( 'public', 'thumb', 'transcoded' ) ) ) {
+ if ( in_array( $zone, [ 'public', 'thumb', 'transcoded' ] ) ) {
// standard public zones
if ( $ext !== null && isset( $this->zones[$zone]['urlsByExt'][$ext] ) ) {
// custom URL for extension/zone
*/
protected function getZoneLocation( $zone ) {
if ( !isset( $this->zones[$zone] ) ) {
- return array( null, null ); // bogus
+ return [ null, null ]; // bogus
}
- return array( $this->zones[$zone]['container'], $this->zones[$zone]['directory'] );
+ return [ $this->zones[$zone]['container'], $this->zones[$zone]['directory'] ];
}
/**
* latest: If true, load from the latest available data into File objects
* @return File|bool False on failure
*/
- public function findFile( $title, $options = array() ) {
+ public function findFile( $title, $options = [] ) {
$title = File::normalizeTitle( $title );
if ( !$title ) {
return false;
* @return array Map of (file name => File objects) for matches
*/
public function findFiles( array $items, $flags = 0 ) {
- $result = array();
+ $result = [];
foreach ( $items as $item ) {
if ( is_array( $item ) ) {
$title = $item['title'];
unset( $options['title'] );
} else {
$title = $item;
- $options = array();
+ $options = [];
}
$file = $this->findFile( $title, $options );
if ( $file ) {
$searchName = File::normalizeTitle( $title )->getDBkey(); // must be valid
if ( $flags & self::NAME_AND_TIME_ONLY ) {
- $result[$searchName] = array(
+ $result[$searchName] = [
'title' => $file->getTitle()->getDBkey(),
'timestamp' => $file->getTimestamp()
- );
+ ];
} else {
$result[$searchName] = $file;
}
* @param array $options Option array, same as findFile().
* @return File|bool False on failure
*/
- public function findFileFromKey( $sha1, $options = array() ) {
+ public function findFileFromKey( $sha1, $options = [] ) {
$time = isset( $options['time'] ) ? $options['time'] : false;
# First try to find a matching current version of a file...
if ( $this->fileFactoryKey ) {
* @return File[]
*/
public function findBySha1( $hash ) {
- return array();
+ return [];
}
/**
* @return array An Array of arrays or iterators of file objects and the hash as key
*/
public function findBySha1s( array $hashes ) {
- $result = array();
+ $result = [];
foreach ( $hashes as $hash ) {
$files = $this->findBySha1( $hash );
if ( count( $files ) ) {
* @return array
*/
public function findFilesByPrefix( $prefix, $limit ) {
- return array();
- }
-
- /**
- * Get the public root URL of the repository
- *
- * @deprecated since 1.20
- * @return string
- */
- public function getRootUrl() {
- return $this->getZoneUrl( 'public' );
+ return [];
}
/**
public function store( $srcPath, $dstZone, $dstRel, $flags = 0 ) {
$this->assertWritableRepo(); // fail out if read-only
- $status = $this->storeBatch( array( array( $srcPath, $dstZone, $dstRel ) ), $flags );
+ $status = $this->storeBatch( [ [ $srcPath, $dstZone, $dstRel ] ], $flags );
if ( $status->successCount == 0 ) {
$status->ok = false;
}
$status = $this->newGood();
$backend = $this->backend; // convenience
- $operations = array();
- $sourceFSFilesToDelete = array(); // cleanup for disk source files
+ $operations = [];
+ $sourceFSFilesToDelete = []; // cleanup for disk source files
// Validate each triplet and get the store operation...
foreach ( $triplets as $triplet ) {
list( $srcPath, $dstZone, $dstRel ) = $triplet;
$sourceFSFilesToDelete[] = $srcPath;
}
}
- $operations[] = array(
+ $operations[] = [
'op' => $opName,
'src' => $srcPath,
'dst' => $dstPath,
'overwrite' => $flags & self::OVERWRITE,
'overwriteSame' => $flags & self::OVERWRITE_SAME,
- );
+ ];
}
// Execute the store operation for each triplet
- $opts = array( 'force' => true );
+ $opts = [ 'force' => true ];
if ( $flags & self::SKIP_LOCKING ) {
$opts['nonLocking'] = true;
}
$status = $this->newGood();
- $operations = array();
+ $operations = [];
foreach ( $files as $path ) {
if ( is_array( $path ) ) {
// This is a pair, extract it
// Resolve source to a storage path if virtual
$path = $this->resolveToStoragePath( $path );
}
- $operations[] = array( 'op' => 'delete', 'src' => $path );
+ $operations[] = [ 'op' => 'delete', 'src' => $path ];
}
// Actually delete files from storage...
- $opts = array( 'force' => true );
+ $opts = [ 'force' => true ];
if ( $flags & self::SKIP_LOCKING ) {
$opts['nonLocking'] = true;
}
* This function can be used to write to otherwise read-only foreign repos.
* This is intended for copying generated thumbnails into the repo.
*
- * @param string $src Source file system path, storage path, or virtual URL
+ * @param string|FSFile $src Source file system path, storage path, or virtual URL
* @param string $dst Virtual URL or storage path
* @param array|string|null $options An array consisting of a key named headers
* listing extra headers. If a string, taken as content-disposition header.
* @return FileRepoStatus
*/
final public function quickImport( $src, $dst, $options = null ) {
- return $this->quickImportBatch( array( array( $src, $dst, $options ) ) );
+ return $this->quickImportBatch( [ [ $src, $dst, $options ] ] );
}
/**
* @return FileRepoStatus
*/
final public function quickPurge( $path ) {
- return $this->quickPurgeBatch( array( $path ) );
+ return $this->quickPurgeBatch( [ $path ] );
}
/**
public function quickCleanDir( $dir ) {
$status = $this->newGood();
$status->merge( $this->backend->clean(
- array( 'dir' => $this->resolveToStoragePath( $dir ) ) ) );
+ [ 'dir' => $this->resolveToStoragePath( $dir ) ] ) );
return $status;
}
* All path parameters may be a file system path, storage path, or virtual URL.
* When "headers" are given they are used as HTTP headers if supported.
*
- * @param array $triples List of (source path, destination path, disposition)
+ * @param array $triples List of (source path or FSFile, destination path, disposition)
* @return FileRepoStatus
*/
public function quickImportBatch( array $triples ) {
$status = $this->newGood();
- $operations = array();
+ $operations = [];
foreach ( $triples as $triple ) {
list( $src, $dst ) = $triple;
- $src = $this->resolveToStoragePath( $src );
+ if ( $src instanceof FSFile ) {
+ $op = 'store';
+ } else {
+ $src = $this->resolveToStoragePath( $src );
+ $op = FileBackend::isStoragePath( $src ) ? 'copy' : 'store';
+ }
$dst = $this->resolveToStoragePath( $dst );
if ( !isset( $triple[2] ) ) {
- $headers = array();
+ $headers = [];
} elseif ( is_string( $triple[2] ) ) {
// back-compat
- $headers = array( 'Content-Disposition' => $triple[2] );
+ $headers = [ 'Content-Disposition' => $triple[2] ];
} elseif ( is_array( $triple[2] ) && isset( $triple[2]['headers'] ) ) {
$headers = $triple[2]['headers'];
} else {
- $headers = array();
+ $headers = [];
}
- $operations[] = array(
- 'op' => FileBackend::isStoragePath( $src ) ? 'copy' : 'store',
+ $operations[] = [
+ 'op' => $op,
'src' => $src,
'dst' => $dst,
'headers' => $headers
- );
+ ];
$status->merge( $this->initDirectory( dirname( $dst ) ) );
}
$status->merge( $this->backend->doQuickOperations( $operations ) );
*/
public function quickPurgeBatch( array $paths ) {
$status = $this->newGood();
- $operations = array();
+ $operations = [];
foreach ( $paths as $path ) {
- $operations[] = array(
+ $operations[] = [
'op' => 'delete',
'src' => $this->resolveToStoragePath( $path ),
'ignoreMissingSource' => true
- );
+ ];
}
$status->merge( $this->backend->doQuickOperations( $operations ) );
* @param array $srcPaths Ordered list of source virtual URLs/storage paths
* @param string $dstPath Target file system path
* @param int $flags Bitwise combination of the following flags:
- * self::DELETE_SOURCE Delete the source files
+ * self::DELETE_SOURCE Delete the source files on success
* @return FileRepoStatus
*/
public function concatenate( array $srcPaths, $dstPath, $flags = 0 ) {
$status = $this->newGood();
- $sources = array();
+ $sources = [];
foreach ( $srcPaths as $srcPath ) {
// Resolve source to a storage path if virtual
$source = $this->resolveToStoragePath( $srcPath );
}
// Concatenate the chunks into one FS file
- $params = array( 'srcs' => $sources, 'dst' => $dstPath );
+ $params = [ 'srcs' => $sources, 'dst' => $dstPath ];
$status->merge( $this->backend->concatenate( $params ) );
if ( !$status->isOK() ) {
return $status;
* Options to $options include:
* - headers : name/value map of HTTP headers to use in response to GET/HEAD requests
*
- * @param string $srcPath The source file system path, storage path, or URL
+ * @param string|FSFile $src The source file system path, storage path, or URL
* @param string $dstRel The destination relative path
* @param string $archiveRel The relative path where the existing file is to
* be archived, if there is one. Relative to the public zone root.
* @return FileRepoStatus
*/
public function publish(
- $srcPath, $dstRel, $archiveRel, $flags = 0, array $options = array()
+ $src, $dstRel, $archiveRel, $flags = 0, array $options = []
) {
$this->assertWritableRepo(); // fail out if read-only
$status = $this->publishBatch(
- array( array( $srcPath, $dstRel, $archiveRel, $options ) ), $flags );
+ [ [ $src, $dstRel, $archiveRel, $options ] ], $flags );
if ( $status->successCount == 0 ) {
$status->ok = false;
}
return $status;
}
- $status = $this->newGood( array() );
+ $status = $this->newGood( [] );
- $operations = array();
- $sourceFSFilesToDelete = array(); // cleanup for disk source files
+ $operations = [];
+ $sourceFSFilesToDelete = []; // cleanup for disk source files
// Validate each triplet and get the store operation...
foreach ( $ntuples as $ntuple ) {
- list( $srcPath, $dstRel, $archiveRel ) = $ntuple;
- $options = isset( $ntuple[3] ) ? $ntuple[3] : array();
+ list( $src, $dstRel, $archiveRel ) = $ntuple;
+ $srcPath = ( $src instanceof FSFile ) ? $src->getPath() : $src;
+
+ $options = isset( $ntuple[3] ) ? $ntuple[3] : [];
// Resolve source to a storage path if virtual
$srcPath = $this->resolveToStoragePath( $srcPath );
if ( !$this->validateFilename( $dstRel ) ) {
}
// Set any desired headers to be use in GET/HEAD responses
- $headers = isset( $options['headers'] ) ? $options['headers'] : array();
+ $headers = isset( $options['headers'] ) ? $options['headers'] : [];
// Archive destination file if it exists.
// This will check if the archive file also exists and fail if does.
// copy() will overwrite, so the existence check is vulnerable to
// race conditions unless a functioning LockManager is used.
// LocalFile also uses SELECT FOR UPDATE for synchronization.
- $operations[] = array(
+ $operations[] = [
'op' => 'copy',
'src' => $dstPath,
'dst' => $archivePath,
'ignoreMissingSource' => true
- );
+ ];
// Copy (or move) the source file to the destination
if ( FileBackend::isStoragePath( $srcPath ) ) {
if ( $flags & self::DELETE_SOURCE ) {
- $operations[] = array(
+ $operations[] = [
'op' => 'move',
'src' => $srcPath,
'dst' => $dstPath,
'overwrite' => true, // replace current
'headers' => $headers
- );
+ ];
} else {
- $operations[] = array(
+ $operations[] = [
'op' => 'copy',
'src' => $srcPath,
'dst' => $dstPath,
'overwrite' => true, // replace current
'headers' => $headers
- );
+ ];
}
} else { // FS source path
- $operations[] = array(
+ $operations[] = [
'op' => 'store',
- 'src' => $srcPath,
+ 'src' => $src, // prefer FSFile objects
'dst' => $dstPath,
'overwrite' => true, // replace current
'headers' => $headers
- );
+ ];
if ( $flags & self::DELETE_SOURCE ) {
$sourceFSFilesToDelete[] = $srcPath;
}
$path = $this->resolveToStoragePath( $dir );
list( , $container, ) = FileBackend::splitStoragePath( $path );
- $params = array( 'dir' => $path );
+ $params = [ 'dir' => $path ];
if ( $this->isPrivate
|| $container === $this->zones['deleted']['container']
|| $container === $this->zones['temp']['container']
) {
# Take all available measures to prevent web accessibility of new deleted
# directories, in case the user has not configured offline storage
- $params = array( 'noAccess' => true, 'noListing' => true ) + $params;
+ $params = [ 'noAccess' => true, 'noListing' => true ] + $params;
}
return $this->backend->prepare( $params );
$status = $this->newGood();
$status->merge( $this->backend->clean(
- array( 'dir' => $this->resolveToStoragePath( $dir ) ) ) );
+ [ 'dir' => $this->resolveToStoragePath( $dir ) ] ) );
return $status;
}
* @return bool
*/
public function fileExists( $file ) {
- $result = $this->fileExistsBatch( array( $file ) );
+ $result = $this->fileExistsBatch( [ $file ] );
return $result[0];
}
* @return array Map of files and existence flags, or false
*/
public function fileExistsBatch( array $files ) {
- $paths = array_map( array( $this, 'resolveToStoragePath' ), $files );
- $this->backend->preloadFileStat( array( 'srcs' => $paths ) );
+ $paths = array_map( [ $this, 'resolveToStoragePath' ], $files );
+ $this->backend->preloadFileStat( [ 'srcs' => $paths ] );
- $result = array();
+ $result = [];
foreach ( $files as $key => $file ) {
$path = $this->resolveToStoragePath( $file );
- $result[$key] = $this->backend->fileExists( array( 'src' => $path ) );
+ $result[$key] = $this->backend->fileExists( [ 'src' => $path ] );
}
return $result;
public function delete( $srcRel, $archiveRel ) {
$this->assertWritableRepo(); // fail out if read-only
- return $this->deleteBatch( array( array( $srcRel, $archiveRel ) ) );
+ return $this->deleteBatch( [ [ $srcRel, $archiveRel ] ] );
}
/**
$this->assertWritableRepo(); // fail out if read-only
// Try creating directories
- $status = $this->initZones( array( 'public', 'deleted' ) );
+ $status = $this->initZones( [ 'public', 'deleted' ] );
if ( !$status->isOK() ) {
return $status;
}
$status = $this->newGood();
$backend = $this->backend; // convenience
- $operations = array();
+ $operations = [];
// Validate filenames and create archive directories
foreach ( $sourceDestPairs as $pair ) {
list( $srcRel, $archiveRel ) = $pair;
return $this->newFatal( 'directorycreateerror', $archiveDir );
}
- $operations[] = array(
+ $operations[] = [
'op' => 'move',
'src' => $srcPath,
'dst' => $archivePath,
// We may have 2+ identical files being deleted,
// all of which will map to the same destination file
'overwriteSame' => true // also see bug 31792
- );
+ ];
}
// Move the files by execute the operations for each pair.
// We're now committed to returning an OK result, which will
// lead to the files being moved in the DB also.
- $opts = array( 'force' => true );
+ $opts = [ 'force' => true ];
$status->merge( $backend->doOperations( $operations, $opts ) );
return $status;
public function getLocalCopy( $virtualUrl ) {
$path = $this->resolveToStoragePath( $virtualUrl );
- return $this->backend->getLocalCopy( array( 'src' => $path ) );
+ return $this->backend->getLocalCopy( [ 'src' => $path ] );
}
/**
public function getLocalReference( $virtualUrl ) {
$path = $this->resolveToStoragePath( $virtualUrl );
- return $this->backend->getLocalReference( array( 'src' => $path ) );
+ return $this->backend->getLocalReference( [ 'src' => $path ] );
}
/**
public function getFileProps( $virtualUrl ) {
$path = $this->resolveToStoragePath( $virtualUrl );
- return $this->backend->getFileProps( array( 'src' => $path ) );
+ return $this->backend->getFileProps( [ 'src' => $path ] );
}
/**
public function getFileTimestamp( $virtualUrl ) {
$path = $this->resolveToStoragePath( $virtualUrl );
- return $this->backend->getFileTimestamp( array( 'src' => $path ) );
+ return $this->backend->getFileTimestamp( [ 'src' => $path ] );
}
/**
public function getFileSize( $virtualUrl ) {
$path = $this->resolveToStoragePath( $virtualUrl );
- return $this->backend->getFileSize( array( 'src' => $path ) );
+ return $this->backend->getFileSize( [ 'src' => $path ] );
}
/**
public function getFileSha1( $virtualUrl ) {
$path = $this->resolveToStoragePath( $virtualUrl );
- return $this->backend->getFileSha1Base36( array( 'src' => $path ) );
+ return $this->backend->getFileSha1Base36( [ 'src' => $path ] );
}
/**
* @return Status
* @since 1.27
*/
- public function streamFileWithStatus( $virtualUrl, $headers = array() ) {
+ public function streamFileWithStatus( $virtualUrl, $headers = [] ) {
$path = $this->resolveToStoragePath( $virtualUrl );
- $params = array( 'src' => $path, 'headers' => $headers );
+ $params = [ 'src' => $path, 'headers' => $headers ];
return $this->backend->streamFile( $params );
}
* @param array $headers Additional HTTP headers to send on success
* @return bool Success
*/
- public function streamFile( $virtualUrl, $headers = array() ) {
+ public function streamFile( $virtualUrl, $headers = [] ) {
return $this->streamFileWithStatus( $virtualUrl, $headers )->isOK();
}
for ( $hexPos = 0; $hexPos < $this->hashLevels; $hexPos++ ) {
$path .= '/' . substr( $hexString, 0, $hexPos + 1 );
}
- $iterator = $this->backend->getFileList( array( 'dir' => $path ) );
+ $iterator = $this->backend->getFileList( [ 'dir' => $path ] );
foreach ( $iterator as $name ) {
// Each item returned is a public file
call_user_func( $callback, "{$path}/{$name}" );
switch ( $this->pathDisclosureProtection ) {
case 'none':
case 'simple': // b/c
- $callback = array( $this, 'passThrough' );
+ $callback = [ $this, 'passThrough' ];
break;
default: // 'paranoid'
- $callback = array( $this, 'paranoidClean' );
+ $callback = [ $this, 'paranoidClean' ];
}
return $callback;
}
* @return Status
*/
public function newFatal( $message /*, parameters...*/ ) {
- $status = call_user_func_array( array( 'Status', 'newFatal' ), func_get_args() );
+ $status = call_user_func_array( [ 'Status', 'newFatal' ], func_get_args() );
$status->cleanCallback = $this->getErrorCleanupFunction();
return $status;
* @return TempFileRepo
*/
public function getTempRepo() {
- return new TempFileRepo( array(
+ return new TempFileRepo( [
'name' => "{$this->name}-temp",
'backend' => $this->backend,
- 'zones' => array(
- 'public' => array(
+ 'zones' => [
+ 'public' => [
// Same place storeTemp() uses in the base repo, though
// the path hashing is mismatched, which is annoying.
'container' => $this->zones['temp']['container'],
'directory' => $this->zones['temp']['directory']
- ),
- 'thumb' => array(
+ ],
+ 'thumb' => [
'container' => $this->zones['temp']['container'],
'directory' => $this->zones['temp']['directory'] == ''
? 'thumb'
: $this->zones['temp']['directory'] . '/thumb'
- ),
- 'transcoded' => array(
+ ],
+ 'transcoded' => [
'container' => $this->zones['temp']['container'],
'directory' => $this->zones['temp']['directory'] == ''
? 'transcoded'
: $this->zones['temp']['directory'] . '/transcoded'
- )
- ),
+ ]
+ ],
'hashLevels' => $this->hashLevels, // performance
'isPrivate' => true // all in temp zone
- ) );
+ ] );
}
/**
* @since 1.22
*/
public function getInfo() {
- $ret = array(
+ $ret = [
'name' => $this->getName(),
'displayname' => $this->getDisplayName(),
'rootUrl' => $this->getZoneUrl( 'public' ),
'local' => $this->isLocal(),
- );
+ ];
- $optionalSettings = array(
+ $optionalSettings = [
'url', 'thumbUrl', 'initialCapital', 'descBaseUrl', 'scriptDirUrl', 'articleUrl',
'fetchDescription', 'descriptionCacheExpiry', 'scriptExtension', 'favicon'
- );
+ ];
foreach ( $optionalSettings as $k ) {
if ( isset( $this->$k ) ) {
$ret[$k] = $this->$k;