79 parent::__construct( $info );
81 $this->dbDomain = WikiMap::getCurrentWikiDbDomain();
82 $this->hasAccessibleSharedCache =
true;
84 $this->
hasSha1Storage = ( $info[
'storageLayout'] ?? null ) ===
'sha1';
88 'backend' => $this->backend,
89 'repoName' => $this->name,
98 'splitMetadataThreshold',
99 'updateCompatibleMetadata',
100 'reserializeMetadata',
103 if ( isset( $info[$option] ) ) {
104 $this->$option = $info[$option];
115 if ( isset( $row->img_name ) ) {
116 return call_user_func( $this->fileFromRowFactory, $row, $this );
117 } elseif ( isset( $row->oi_name ) ) {
118 return call_user_func( $this->oldFileFromRowFactory, $row, $this );
120 throw new MWException( __METHOD__ .
': invalid row' );
146 wfDebug( __METHOD__ .
": skipped because storage uses sha1 paths" );
147 return Status::newGood();
154 $storageKeys = array_unique( $storageKeys );
155 foreach ( $storageKeys as $key ) {
157 $path =
"$root/$hashPath$key";
158 $dbw->startAtomic( __METHOD__ );
163 if ( !$deleted && !$hidden ) {
164 wfDebug( __METHOD__ .
": deleting $key" );
165 $op = [
'op' =>
'delete',
'src' =>
$path ];
167 $status->error(
'undelete-cleanup-error',
$path );
168 $status->failCount++;
171 wfDebug( __METHOD__ .
": $key still in use" );
172 $status->successCount++;
174 $dbw->endAtomic( __METHOD__ );
189 return (
bool)$dbw->selectField(
'filearchive',
'1',
190 [
'fa_storage_group' =>
'deleted',
'fa_storage_key' => $key ],
192 $lock ===
'lock' ? [
'FOR UPDATE' ] : []
205 $ext = File::normalizeExtension( substr( $key, strcspn( $key,
'.' ) + 1 ) );
208 return (
bool)$dbw->selectField(
'oldimage',
'1',
211 'oi_archive_name ' . $dbw->buildLike( $dbw->anyString(),
".$ext" ),
212 $dbw->bitAnd(
'oi_deleted', File::DELETED_FILE ) => File::DELETED_FILE,
215 $lock ===
'lock' ? [
'FOR UPDATE' ] : []
226 $sha1 = strtok( $key,
'.' );
227 if ( is_string( $sha1 ) && strlen( $sha1 ) === 32 && $sha1[0] ===
'0' ) {
228 $sha1 = substr( $sha1, 1 );
243 if ( $memcKey ===
false ) {
250 $method = __METHOD__;
251 $redirDbKey = $this->wanCache->getWithSetCallback(
254 function ( $oldValue, &$ttl, array &$setOpts ) use ( $method,
$title ) {
257 $setOpts += Database::getCacheSetOptions(
$dbr );
259 $row =
$dbr->selectRow(
260 [
'page',
'redirect' ],
261 [
'rd_namespace',
'rd_title' ],
263 'page_namespace' =>
$title->getNamespace(),
264 'page_title' =>
$title->getDBkey(),
270 return ( $row && $row->rd_namespace ==
NS_FILE )
271 ? Title::makeTitle( $row->rd_namespace, $row->rd_title )->getDBkey()
274 [
'pcTTL' => WANObjectCache::TTL_PROC_LONG ]
278 if ( $redirDbKey !==
' ' && strval( $redirDbKey ) !==
'' ) {
280 return Title::newFromText( $redirDbKey,
NS_FILE );
290 foreach ( $items as $item ) {
291 if ( is_array( $item ) ) {
292 $title = File::normalizeTitle( $item[
'title'] );
294 $searchSet[
$title->getDBkey()] = $item;
297 $title = File::normalizeTitle( $item );
299 $searchSet[
$title->getDBkey()] = [];
304 $fileMatchesSearch =
static function (
File $file, array $search ) {
310 $contextPerformer = RequestContext::getMain()->getAuthority();
311 $performer = ( !empty( $search[
'private'] ) && $search[
'private'] instanceof
Authority )
318 ( empty( $search[
'time'] ) && !
$file->isOld() ) ||
319 ( !empty( $search[
'time'] ) && $search[
'time'] ===
$file->getTimestamp() )
321 ( !empty( $search[
'private'] ) || !
$file->isDeleted( File::DELETED_FILE ) ) &&
322 $file->userCan( File::DELETED_FILE, $performer )
327 use ( $fileMatchesSearch, $flags )
329 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
331 foreach ( $res as $row ) {
335 $dbKeysLook = [ strtr(
$file->getName(),
' ',
'_' ) ];
336 if ( !empty( $info[
'initialCapital'] ) ) {
338 $dbKeysLook[] = $contLang->lcfirst(
$file->getName() );
340 foreach ( $dbKeysLook as $dbKey ) {
341 if ( isset( $searchSet[$dbKey] )
342 && $fileMatchesSearch(
$file, $searchSet[$dbKey] )
345 ? [
'title' => $dbKey,
'timestamp' =>
$file->getTimestamp() ]
347 unset( $searchSet[$dbKey] );
357 foreach ( array_keys( $searchSet ) as $dbKey ) {
361 if ( count( $imgNames ) ) {
362 $fileQuery = LocalFile::getQueryInfo();
363 $res =
$dbr->select( $fileQuery[
'tables'], $fileQuery[
'fields'], [
'img_name' => $imgNames ],
364 __METHOD__, [], $fileQuery[
'joins'] );
365 $applyMatchingFiles(
$res, $searchSet, $finalFiles );
370 foreach ( $searchSet as $dbKey => $search ) {
371 if ( isset( $search[
'time'] ) ) {
372 $oiConds[] =
$dbr->makeList(
375 'oi_timestamp' =>
$dbr->timestamp( $search[
'time'] )
382 if ( count( $oiConds ) ) {
384 $res =
$dbr->select( $fileQuery[
'tables'], $fileQuery[
'fields'],
386 __METHOD__, [], $fileQuery[
'joins'] );
387 $applyMatchingFiles(
$res, $searchSet, $finalFiles );
391 foreach ( $searchSet as $dbKey => $search ) {
392 if ( !empty( $search[
'ignoreRedirect'] ) ) {
396 $title = File::normalizeTitle( $dbKey );
399 if ( $redir && $redir->getNamespace() ===
NS_FILE ) {
401 if (
$file && $fileMatchesSearch(
$file, $search ) ) {
404 $finalFiles[$dbKey] = [
405 'title' =>
$file->getTitle()->getDBkey(),
406 'timestamp' =>
$file->getTimestamp()
409 $finalFiles[$dbKey] =
$file;
427 $fileQuery = LocalFile::getQueryInfo();
429 $fileQuery[
'tables'],
430 $fileQuery[
'fields'],
431 [
'img_sha1' => $hash ],
433 [
'ORDER BY' =>
'img_name' ],
438 foreach (
$res as $row ) {
461 $fileQuery = LocalFile::getQueryInfo();
463 $fileQuery[
'tables'],
464 $fileQuery[
'fields'],
467 [
'ORDER BY' =>
'img_name' ],
472 foreach (
$res as $row ) {
489 $selectOptions = [
'ORDER BY' =>
'img_name',
'LIMIT' => intval( $limit ) ];
493 $fileQuery = LocalFile::getQueryInfo();
495 $fileQuery[
'tables'],
496 $fileQuery[
'fields'],
497 'img_name ' .
$dbr->buildLike( $prefix,
$dbr->anyString() ),
505 foreach (
$res as $row ) {
544 return static function ( $index ) {
562 ? $this->wanCache->makeGlobalKey(
563 'filerepo-' . $kClassSuffix,
580 function () use ( $key ) {
581 $this->wanCache->delete( $key );
597 return array_merge( parent::getInfo(), [
602 public function store( $srcPath, $dstZone, $dstRel, $flags = 0 ) {
628 public function delete( $srcRel, $archiveRel ) {
647 wfDebug( __METHOD__ .
": skipped because storage uses sha1 paths" );
648 return Status::newGood();
650 return parent::$function( ...
$args );
702 if ( !$this->blobStore ) {
703 $this->blobStore = MediaWikiServices::getInstance()->getBlobStoreFactory()
704 ->newBlobStore( $this->dbDomain );
$wgFavicon
The URL path of the shortcut icon.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
if(ini_get('mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Proxy backend that manages file layout rewriting for FileRepo.
doOperation(array $op, array $opts=[])
Same as doOperations() except it takes a single operation.
Base class for file repositories.
assertWritableRepo()
Throw an exception if this repo is read-only by design.
newGood( $value=null)
Create a new good result.
getLocalCacheKey( $kClassSuffix,... $components)
Get a site-local, repository-qualified, WAN cache key.
hasSha1Storage()
Returns whether or not storage is SHA-1 based.
getZonePath( $zone)
Get the storage path corresponding to one of the zones.
getDeletedHashPath( $key)
Get a relative path for a deletion archive key, e.g.
getNameFromTitle( $title)
Get the name of a file from its title.
newFile( $title, $time=false)
Create a new File object from the local repository.
Implements some public methods and some protected utility functions which are required by multiple ch...
A repository that stores files in the local filesystem and registers them in the wiki's own database.
skipWriteOperationIfSha1( $function, array $args)
Skips the write operation if storage is sha1-based, executes it normally otherwise.
int null $splitMetadataThreshold
getDBFactory()
Get a callback to get a DB handle given an index (DB_REPLICA/DB_PRIMARY)
getSharedCacheKey( $kClassSuffix,... $components)
Get a global, repository-qualified, WAN cache key.
isMetadataUpdateEnabled()
getInfo()
Return information about the repository.
isSplitMetadataEnabled()
Returns true if files should split up large metadata, storing parts of it in the BlobStore.
deletedFileHasKey( $key, $lock=null)
Check if a deleted (filearchive) file has this sha1 key.
callable $oldFileFactoryKey
isJsonMetadataEnabled()
Returns true if files should store metadata in JSON format.
cleanupBatch(array $files, $flags=0)
Deletes a batch of files.
publishBatch(array $ntuples, $flags=0)
Publish a batch of files.
findFiles(array $items, $flags=0)
Find many files at once.
findFilesByPrefix( $prefix, $limit)
Return an array of files where the name starts with $prefix.
findBySha1s(array $hashes)
Get an array of arrays or iterators of file objects for files that have the given SHA-1 content hashe...
getBlobStore()
Get a BlobStore for storing and retrieving large metadata, or null if that can't be done.
callable $oldFileFromRowFactory
string $dbDomain
DB domain of the repo wiki.
invalidateImageRedirect( $title)
Invalidates image redirect cache related to that image.
cleanupDeletedBatch(array $storageKeys)
Delete files in the deleted directory if they are not referenced in the filearchive table.
bool $updateCompatibleMetadata
getPrimaryDB()
Get a connection to the primary DB.
checkRedirect( $title)
Checks if there is a redirect named as $title.
hasAcessibleSharedCache()
Check whether the repo has a shared cache, accessible from the current site context.
bool $hasAccessibleSharedCache
Whether shared cache keys are exposed/accessible.
getReplicaDB()
Get a connection to the replica DB.
store( $srcPath, $dstZone, $dstRel, $flags=0)
Store a file to a given destination.
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...
getMasterDB()
Get a connection to the primary DB.
storeBatch(array $triplets, $flags=0)
Store a batch of files.
getSplitMetadataThreshold()
Get the threshold above which metadata items should be split into separate storage,...
callable $fileFromRowFactory
__construct(array $info=null)
deleteBatch(array $sourceDestPairs)
Move a group of files to the deletion archive.
hiddenFileHasKey( $key, $lock=null)
Check if a hidden (revision delete) file has this sha1 key.
static getHashFromKey( $key)
Gets the SHA1 hash from a storage key.
newFromArchiveName( $title, $archiveName)
bool $reserializeMetadata
isMetadataReserializeEnabled()
findBySha1( $hash)
Get an array or iterator of file objects for files that have a given SHA-1 content hash.
static newFromArchiveName( $title, $repo, $archiveName)
static getQueryInfo(array $options=[])
Return the tables, fields, and join conditions to be selected to create a new oldlocalfile object.
Interface for objects (potentially) representing an editable wiki page.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
if(!is_readable( $file)) $ext