$conds['img_timestamp'] = $dbr->timestamp( $timestamp );
}
- $row = $dbr->selectRow( 'image', self::selectFields(), $conds, __METHOD__ );
+ $fileQuery = self::getQueryInfo();
+ $row = $dbr->selectRow(
+ $fileQuery['tables'], $fileQuery['fields'], $conds, __METHOD__, [], $fileQuery['joins']
+ );
if ( $row ) {
return self::newFromRow( $row, $repo );
} else {
/**
* Fields in the image table
- * @todo Deprecate this in favor of a method that returns tables and joins
- * as well, and use CommentStore::getJoin().
+ * @deprecated since 1.31, use self::getQueryInfo() instead.
* @return array
*/
static function selectFields() {
+ wfDeprecated( __METHOD__, '1.31' );
return [
'img_name',
'img_size',
] + CommentStore::newKey( 'img_description' )->getFields();
}
+ /**
+ * Return the tables, fields, and join conditions to be selected to create
+ * a new localfile object.
+ * @since 1.31
+ * @param string[] $options
+ * - omit-lazy: Omit fields that are lazily cached.
+ * @return array With three keys:
+ * - tables: (string[]) to include in the `$table` to `IDatabase->select()`
+ * - fields: (string[]) to include in the `$vars` to `IDatabase->select()`
+ * - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
+ */
+ public static function getQueryInfo( array $options = [] ) {
+ $commentQuery = CommentStore::newKey( 'img_description' )->getJoin();
+ $ret = [
+ 'tables' => [ 'image' ] + $commentQuery['tables'],
+ 'fields' => [
+ 'img_name',
+ 'img_size',
+ 'img_width',
+ 'img_height',
+ 'img_metadata',
+ 'img_bits',
+ 'img_media_type',
+ 'img_major_mime',
+ 'img_minor_mime',
+ 'img_user',
+ 'img_user_text',
+ 'img_timestamp',
+ 'img_sha1',
+ ] + $commentQuery['fields'],
+ 'joins' => $commentQuery['joins'],
+ ];
+
+ if ( in_array( 'omit-nonlazy', $options, true ) ) {
+ // Internal use only for getting only the lazy fields
+ $ret['fields'] = [];
+ }
+ if ( !in_array( 'omit-lazy', $options, true ) ) {
+ // Note: Keep this in sync with self::getLazyCacheFields()
+ $ret['fields'][] = 'img_metadata';
+ }
+
+ return $ret;
+ }
+
/**
* Do not call this except from inside a repo class.
* @param Title $title
}
/**
- * @param string $prefix
+ * Returns the list of object properties that are included as-is in the cache.
+ * @param string $prefix Must be the empty string
* @return array
+ * @since 1.31 No longer accepts a non-empty $prefix
*/
- function getCacheFields( $prefix = 'img_' ) {
- static $fields = [ 'size', 'width', 'height', 'bits', 'media_type',
- 'major_mime', 'minor_mime', 'metadata', 'timestamp', 'sha1', 'user',
- 'user_text' ];
- static $results = [];
-
- if ( $prefix == '' ) {
- return array_merge( $fields, [ 'description' ] );
- }
- if ( !isset( $results[$prefix] ) ) {
- $prefixedFields = [];
- foreach ( $fields as $field ) {
- $prefixedFields[] = $prefix . $field;
- }
- $prefixedFields += CommentStore::newKey( "{$prefix}description" )->getFields();
- $results[$prefix] = $prefixedFields;
+ protected function getCacheFields( $prefix = 'img_' ) {
+ if ( $prefix !== '' ) {
+ throw new InvalidArgumentException(
+ __METHOD__ . ' with a non-empty prefix is no longer supported.'
+ );
}
- return $results[$prefix];
+ // See self::getQueryInfo() for the fetching of the data from the DB,
+ // self::loadFromRow() for the loading of the object from the DB row,
+ // and self::loadFromCache() for the caching, and self::setProps() for
+ // populating the object from an array of data.
+ return [ 'size', 'width', 'height', 'bits', 'media_type',
+ 'major_mime', 'minor_mime', 'metadata', 'timestamp', 'sha1', 'user',
+ 'user_text', 'description' ];
}
/**
- * @param string $prefix
+ * Returns the list of object properties that are included as-is in the
+ * cache, only when they're not too big, and are lazily loaded by self::loadExtraFromDB().
+ * @param string $prefix Must be the empty string
* @return array
+ * @since 1.31 No longer accepts a non-empty $prefix
*/
- function getLazyCacheFields( $prefix = 'img_' ) {
- static $fields = [ 'metadata' ];
- static $results = [];
-
- if ( $prefix == '' ) {
- return $fields;
- }
-
- if ( !isset( $results[$prefix] ) ) {
- $prefixedFields = [];
- foreach ( $fields as $field ) {
- $prefixedFields[] = $prefix . $field;
- }
- $results[$prefix] = $prefixedFields;
+ protected function getLazyCacheFields( $prefix = 'img_' ) {
+ if ( $prefix !== '' ) {
+ throw new InvalidArgumentException(
+ __METHOD__ . ' with a non-empty prefix is no longer supported.'
+ );
}
- return $results[$prefix];
+ // Keep this in sync with the omit-lazy option in self::getQueryInfo().
+ return [ 'metadata' ];
}
/**
? $this->repo->getMasterDB()
: $this->repo->getReplicaDB();
- $row = $dbr->selectRow( 'image', $this->getCacheFields( 'img_' ),
- [ 'img_name' => $this->getName() ], $fname );
+ $fileQuery = static::getQueryInfo();
+ $row = $dbr->selectRow(
+ $fileQuery['tables'],
+ $fileQuery['fields'],
+ [ 'img_name' => $this->getName() ],
+ $fname,
+ [],
+ $fileQuery['joins']
+ );
if ( $row ) {
$this->loadFromRow( $row );
# Unconditionally set loaded=true, we don't want the accessors constantly rechecking
$this->extraDataLoaded = true;
- $fieldMap = $this->loadFieldsWithTimestamp( $this->repo->getReplicaDB(), $fname );
+ $fieldMap = $this->loadExtraFieldsWithTimestamp( $this->repo->getReplicaDB(), $fname );
if ( !$fieldMap ) {
- $fieldMap = $this->loadFieldsWithTimestamp( $this->repo->getMasterDB(), $fname );
+ $fieldMap = $this->loadExtraFieldsWithTimestamp( $this->repo->getMasterDB(), $fname );
}
if ( $fieldMap ) {
* @param string $fname
* @return array|bool
*/
- private function loadFieldsWithTimestamp( $dbr, $fname ) {
+ private function loadExtraFieldsWithTimestamp( $dbr, $fname ) {
$fieldMap = false;
- $row = $dbr->selectRow( 'image', $this->getLazyCacheFields( 'img_' ), [
+ $fileQuery = self::getQueryInfo( [ 'omit-nonlazy' ] );
+ $row = $dbr->selectRow(
+ $fileQuery['tables'],
+ $fileQuery['fields'],
+ [
'img_name' => $this->getName(),
- 'img_timestamp' => $dbr->timestamp( $this->getTimestamp() )
- ], $fname );
+ 'img_timestamp' => $dbr->timestamp( $this->getTimestamp() ),
+ ],
+ $fname,
+ [],
+ $fileQuery['joins']
+ );
if ( $row ) {
$fieldMap = $this->unprefixRow( $row, 'img_' );
} else {
# File may have been uploaded over in the meantime; check the old versions
- $row = $dbr->selectRow( 'oldimage', $this->getLazyCacheFields( 'oi_' ), [
+ $fileQuery = OldLocalFile::getQueryInfo( [ 'omit-nonlazy' ] );
+ $row = $dbr->selectRow(
+ $fileQuery['tables'],
+ $fileQuery['fields'],
+ [
'oi_name' => $this->getName(),
- 'oi_timestamp' => $dbr->timestamp( $this->getTimestamp() )
- ], $fname );
+ 'oi_timestamp' => $dbr->timestamp( $this->getTimestamp() ),
+ ],
+ $fname,
+ [],
+ $fileQuery['joins']
+ );
if ( $row ) {
$fieldMap = $this->unprefixRow( $row, 'oi_' );
}
}
+ if ( isset( $fieldMap['metadata'] ) ) {
+ $fieldMap['metadata'] = $this->repo->getReplicaDB()->decodeBlob( $fieldMap['metadata'] );
+ }
+
return $fieldMap;
}
function decodeRow( $row, $prefix = 'img_' ) {
$decoded = $this->unprefixRow( $row, $prefix );
+ $decoded['description'] = CommentStore::newKey( 'description' )
+ ->getComment( (object)$decoded )->text;
+
$decoded['timestamp'] = wfTimestamp( TS_MW, $decoded['timestamp'] );
$decoded['metadata'] = $this->repo->getReplicaDB()->decodeBlob( $decoded['metadata'] );
$this->dataLoaded = true;
$this->extraDataLoaded = true;
- $this->description = CommentStore::newKey( "{$prefix}description" )
- // $row is probably using getFields() from self::getCacheFields()
- ->getCommentLegacy( wfGetDB( DB_REPLICA ), $row )->text;
-
$array = $this->decodeRow( $row, $prefix );
foreach ( $array as $name => $value ) {
*/
function getHistory( $limit = null, $start = null, $end = null, $inc = true ) {
$dbr = $this->repo->getReplicaDB();
- $tables = [ 'oldimage' ];
- $fields = OldLocalFile::selectFields();
- $conds = $opts = $join_conds = [];
+ $oldFileQuery = OldLocalFile::getQueryInfo();
+
+ $tables = $oldFileQuery['tables'];
+ $fields = $oldFileQuery['fields'];
+ $join_conds = $oldFileQuery['joins'];
+ $conds = $opts = [];
$eq = $inc ? '=' : '';
$conds[] = "oi_name = " . $dbr->addQuotes( $this->title->getDBkey() );
$dbr = $this->repo->getReplicaDB();
if ( $this->historyLine == 0 ) { // called for the first time, return line from cur
- $this->historyRes = $dbr->select( 'image',
- self::selectFields() + [
+ $fileQuery = self::getQueryInfo();
+ $this->historyRes = $dbr->select( $fileQuery['tables'],
+ $fileQuery['fields'] + [
'oi_archive_name' => $dbr->addQuotes( '' ),
'oi_deleted' => 0,
],
[ 'img_name' => $this->title->getDBkey() ],
- $fname
+ $fname,
+ [],
+ $fileQuery['joins']
);
if ( 0 == $dbr->numRows( $this->historyRes ) ) {
return false;
}
} elseif ( $this->historyLine == 1 ) {
+ $fileQuery = OldLocalFile::getQueryInfo();
$this->historyRes = $dbr->select(
- 'oldimage',
- OldLocalFile::selectFields(),
+ $fileQuery['tables'],
+ $fileQuery['fields'],
[ 'oi_name' => $this->title->getDBkey() ],
$fname,
- [ 'ORDER BY' => 'oi_timestamp DESC' ]
+ [ 'ORDER BY' => 'oi_timestamp DESC' ],
+ $fileQuery['joins']
);
}
$this->historyLine++;
) {
$props = $this->repo->getFileProps( $srcPath );
} else {
- $mwProps = new MWFileProps( MimeMagic::singleton() );
+ $mwProps = new MWFileProps( MediaWiki\MediaWikiServices::getInstance()->getMimeAnalyzer() );
$props = $mwProps->getPropsFromPath( $srcPath, true );
}
}
);
} else {
# Update backlink pages pointing to this title if created
- LinksUpdate::queueRecursiveJobsForTable( $this->getTitle(), 'imagelinks' );
+ LinksUpdate::queueRecursiveJobsForTable(
+ $this->getTitle(),
+ 'imagelinks',
+ 'upload-image',
+ $user->getName()
+ );
}
$this->prerenderThumbnails();
}
# Invalidate cache for all pages using this file
- DeferredUpdates::addUpdate( new HTMLCacheUpdate( $this->getTitle(), 'imagelinks' ) );
+ DeferredUpdates::addUpdate(
+ new HTMLCacheUpdate( $this->getTitle(), 'imagelinks', 'file-upload' )
+ );
return Status::newGood();
}
}
if ( count( $oldRels ) ) {
+ $fileQuery = OldLocalFile::getQueryInfo();
$res = $dbw->select(
- 'oldimage',
- OldLocalFile::selectFields(),
+ $fileQuery['tables'],
+ $fileQuery['fields'],
[
'oi_name' => $this->file->getName(),
'oi_archive_name' => array_keys( $oldRels )
],
__METHOD__,
- [ 'FOR UPDATE' ]
+ [ 'FOR UPDATE' ],
+ $fileQuery['joins']
);
$rowsInsert = [];
if ( $res->numRows() ) {
$reason = $commentStoreFaReason->createComment( $dbw, $this->reason );
foreach ( $res as $row ) {
- // Legacy from OldLocalFile::selectFields() just above
- $comment = $commentStoreOiDesc->getCommentLegacy( $dbw, $row );
+ $comment = $commentStoreOiDesc->getComment( $row );
$rowsInsert[] = [
// Deletion-specific fields
'fa_storage_group' => 'deleted',
}
function doDBDeletes() {
- global $wgUpdateCompatibleMetadata;
+ global $wgCommentTableSchemaMigrationStage;
$dbw = $this->file->repo->getMasterDB();
list( $oldRels, $deleteCurrent ) = $this->getOldRels();
if ( $deleteCurrent ) {
$dbw->delete( 'image', [ 'img_name' => $this->file->getName() ], __METHOD__ );
- if ( $wgUpdateCompatibleMetadata > MIGRATION_OLD ) {
+ if ( $wgCommentTableSchemaMigrationStage > MIGRATION_OLD ) {
$dbw->delete(
'image_comment_temp', [ 'imgcomment_name' => $this->file->getName() ], __METHOD__
);
$conditions['fa_id'] = $this->ids;
}
+ $arFileQuery = ArchivedFile::getQueryInfo();
$result = $dbw->select(
- 'filearchive',
- ArchivedFile::selectFields(),
+ $arFileQuery['tables'],
+ $arFileQuery['fields'],
$conditions,
__METHOD__,
- [ 'ORDER BY' => 'fa_timestamp DESC' ]
+ [ 'ORDER BY' => 'fa_timestamp DESC' ],
+ $arFileQuery['joins']
);
$idsPresent = [];
];
}
- // Legacy from ArchivedFile::selectFields() just above
- $comment = $commentStoreFaDesc->getCommentLegacy( $dbw, $row );
+ $comment = $commentStoreFaDesc->getComment( $row );
if ( $first && !$exists ) {
// This revision will be published as the new current version
$destRel = $this->file->getRel();