52 parent::__construct( $info );
55 && $info[
'storageLayout'] ===
'sha1';
59 'backend' => $this->backend,
60 'repoName' => $this->name,
72 if ( isset( $row->img_name ) ) {
73 return call_user_func( $this->fileFromRowFactory, $row, $this );
74 } elseif ( isset( $row->oi_name ) ) {
75 return call_user_func( $this->oldFileFromRowFactory, $row, $this );
77 throw new MWException( __METHOD__ .
': invalid row' );
102 wfDebug( __METHOD__ .
": skipped because storage uses sha1 paths" );
103 return Status::newGood();
110 $storageKeys = array_unique( $storageKeys );
111 foreach ( $storageKeys as $key ) {
113 $path =
"$root/$hashPath$key";
114 $dbw->startAtomic( __METHOD__ );
119 if ( !$deleted && !$hidden ) {
120 wfDebug( __METHOD__ .
": deleting $key" );
121 $op = [
'op' =>
'delete',
'src' =>
$path ];
123 $status->error(
'undelete-cleanup-error',
$path );
124 $status->failCount++;
127 wfDebug( __METHOD__ .
": $key still in use" );
128 $status->successCount++;
130 $dbw->endAtomic( __METHOD__ );
144 $options = ( $lock ===
'lock' ) ? [
'FOR UPDATE' ] : [];
148 return (
bool)$dbw->selectField(
'filearchive',
'1',
149 [
'fa_storage_group' =>
'deleted',
'fa_storage_key' => $key ],
162 $options = ( $lock ===
'lock' ) ? [
'FOR UPDATE' ] : [];
165 $ext = File::normalizeExtension( substr( $key, strcspn( $key,
'.' ) + 1 ) );
169 return (
bool)$dbw->selectField(
'oldimage',
'1',
170 [
'oi_sha1' => $sha1,
171 'oi_archive_name ' . $dbw->buildLike( $dbw->anyString(),
".$ext" ),
172 $dbw->bitAnd(
'oi_deleted', File::DELETED_FILE ) => File::DELETED_FILE ],
184 $sha1 = strtok( $key,
'.' );
185 if ( is_string( $sha1 ) && strlen( $sha1 ) === 32 && $sha1[0] ===
'0' ) {
186 $sha1 = substr( $sha1, 1 );
201 if ( $memcKey ===
false ) {
208 $method = __METHOD__;
209 $redirDbKey = $this->wanCache->getWithSetCallback(
212 function ( $oldValue, &$ttl, array &$setOpts ) use ( $method,
$title ) {
215 $setOpts += Database::getCacheSetOptions(
$dbr );
217 $row =
$dbr->selectRow(
218 [
'page',
'redirect' ],
219 [
'rd_namespace',
'rd_title' ],
221 'page_namespace' =>
$title->getNamespace(),
222 'page_title' =>
$title->getDBkey(),
228 return ( $row && $row->rd_namespace ==
NS_FILE )
229 ? Title::makeTitle( $row->rd_namespace, $row->rd_title )->getDBkey()
232 [
'pcTTL' => WANObjectCache::TTL_PROC_LONG ]
236 if ( $redirDbKey !==
' ' && strval( $redirDbKey ) !==
'' ) {
238 return Title::newFromText( $redirDbKey,
NS_FILE );
248 foreach ( $items as $item ) {
249 if ( is_array( $item ) ) {
250 $title = File::normalizeTitle( $item[
'title'] );
252 $searchSet[
$title->getDBkey()] = $item;
255 $title = File::normalizeTitle( $item );
257 $searchSet[
$title->getDBkey()] = [];
262 $fileMatchesSearch =
function (
File $file, array $search ) {
265 $user = ( !empty( $search[
'private'] ) && $search[
'private'] instanceof
User )
272 ( empty( $search[
'time'] ) && !
$file->isOld() ) ||
273 ( !empty( $search[
'time'] ) && $search[
'time'] ===
$file->getTimestamp() )
275 ( !empty( $search[
'private'] ) || !
$file->isDeleted( File::DELETED_FILE ) ) &&
276 $file->userCan( File::DELETED_FILE, $user )
281 use ( $fileMatchesSearch, $flags )
283 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
285 foreach ( $res as $row ) {
289 $dbKeysLook = [ strtr(
$file->getName(),
' ',
'_' ) ];
290 if ( !empty( $info[
'initialCapital'] ) ) {
292 $dbKeysLook[] = $contLang->lcfirst(
$file->getName() );
294 foreach ( $dbKeysLook as $dbKey ) {
295 if ( isset( $searchSet[$dbKey] )
296 && $fileMatchesSearch(
$file, $searchSet[$dbKey] )
299 ? [
'title' => $dbKey,
'timestamp' =>
$file->getTimestamp() ]
301 unset( $searchSet[$dbKey] );
311 foreach ( array_keys( $searchSet ) as $dbKey ) {
315 if ( count( $imgNames ) ) {
316 $fileQuery = LocalFile::getQueryInfo();
317 $res =
$dbr->select( $fileQuery[
'tables'], $fileQuery[
'fields'], [
'img_name' => $imgNames ],
318 __METHOD__, [], $fileQuery[
'joins'] );
319 $applyMatchingFiles(
$res, $searchSet, $finalFiles );
324 foreach ( $searchSet as $dbKey => $search ) {
325 if ( isset( $search[
'time'] ) ) {
326 $oiConds[] =
$dbr->makeList(
329 'oi_timestamp' =>
$dbr->timestamp( $search[
'time'] )
336 if ( count( $oiConds ) ) {
338 $res =
$dbr->select( $fileQuery[
'tables'], $fileQuery[
'fields'],
340 __METHOD__, [], $fileQuery[
'joins'] );
341 $applyMatchingFiles(
$res, $searchSet, $finalFiles );
345 foreach ( $searchSet as $dbKey => $search ) {
346 if ( !empty( $search[
'ignoreRedirect'] ) ) {
350 $title = File::normalizeTitle( $dbKey );
353 if ( $redir && $redir->getNamespace() ==
NS_FILE ) {
355 if (
$file && $fileMatchesSearch(
$file, $search ) ) {
358 $finalFiles[$dbKey] = [
359 'title' =>
$file->getTitle()->getDBkey(),
360 'timestamp' =>
$file->getTimestamp()
363 $finalFiles[$dbKey] =
$file;
381 $fileQuery = LocalFile::getQueryInfo();
383 $fileQuery[
'tables'],
384 $fileQuery[
'fields'],
385 [
'img_sha1' => $hash ],
387 [
'ORDER BY' =>
'img_name' ],
392 foreach (
$res as $row ) {
415 $fileQuery = LocalFile::getQueryInfo();
417 $fileQuery[
'tables'],
418 $fileQuery[
'fields'],
421 [
'ORDER BY' =>
'img_name' ],
426 foreach (
$res as $row ) {
443 $selectOptions = [
'ORDER BY' =>
'img_name',
'LIMIT' => intval( $limit ) ];
447 $fileQuery = LocalFile::getQueryInfo();
449 $fileQuery[
'tables'],
450 $fileQuery[
'fields'],
451 'img_name ' .
$dbr->buildLike( $prefix,
$dbr->anyString() ),
459 foreach (
$res as $row ) {
487 return function ( $index ) {
501 return $this->wanCache->makeGlobalKey(
502 WikiMap::getCurrentWikiDbDomain()->getId(),
516 $this->
getMasterDB()->onTransactionPreCommitOrIdle(
517 function () use ( $key ) {
518 $this->wanCache->delete( $key );
534 return array_merge( parent::getInfo(), [
539 public function store( $srcPath, $dstZone, $dstRel, $flags = 0 ) {
565 public function delete( $srcRel, $archiveRel ) {
584 wfDebug( __METHOD__ .
": skipped because storage uses sha1 paths" );
585 return Status::newGood();
587 return parent::$function( ...
$args );
$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.
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(... $args)
Get a key for this repo in the local cache domain.
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.
newFile( $title, $time=false)
Create a new File object from the local repository.
getNameFromTitle(Title $title)
Get the name of a file from its title object.
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.
getDBFactory()
Get a callback to get a DB handle given an index (DB_REPLICA/DB_MASTER)
getInfo()
Return information about the repository.
deletedFileHasKey( $key, $lock=null)
Check if a deleted (filearchive) file has this sha1 key.
callable $oldFileFactoryKey
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...
callable $oldFileFromRowFactory
getSharedCacheKey(... $args)
Get a key on the primary cache for this repository.
cleanupDeletedBatch(array $storageKeys)
Delete files in the deleted directory if they are not referenced in the filearchive table.
invalidateImageRedirect(Title $title)
Invalidates image redirect cache related to that image.
checkRedirect(Title $title)
Checks if there is a redirect named as $title.
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 master DB.
storeBatch(array $triplets, $flags=0)
Store a batch of files.
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)
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)
Stable to override.
static getQueryInfo(array $options=[])
Return the tables, fields, and join conditions to be selected to create a new oldlocalfile object.
Represents a title within MediaWiki.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
if(!is_readable( $file)) $ext